/** * DropdownWidgets are not menus themselves, rather they contain a menu of options created with * OO.ui.MenuOptionWidget. The DropdownWidget takes care of opening and displaying the menu so that * users can interact with it. * * @example * // Example: A DropdownWidget with a menu that contains three options * var dropDown = new OO.ui.DropdownWidget( { * label: 'Dropdown menu: Select a menu option', * menu: { * items: [ * new OO.ui.MenuOptionWidget( { * data: 'a', * label: 'First' * } ), * new OO.ui.MenuOptionWidget( { * data: 'b', * label: 'Second' * } ), * new OO.ui.MenuOptionWidget( { * data: 'c', * label: 'Third' * } ) * ] * } * } ); * * $( 'body' ).append( dropDown.$element ); * * For more information, please see the [OOjs UI documentation on MediaWiki] [1]. * * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options * * @class * @extends OO.ui.Widget * @mixins OO.ui.IconElement * @mixins OO.ui.IndicatorElement * @mixins OO.ui.LabelElement * @mixins OO.ui.TitledElement * @mixins OO.ui.TabIndexedElement * * @constructor * @param {Object} [config] Configuration options * @cfg {Object} [menu] Configuration options to pass to menu widget */ OO.ui.DropdownWidget = function OoUiDropdownWidget( config ) { // Configuration initialization config = $.extend( { indicator: 'down' }, config ); // Parent constructor OO.ui.DropdownWidget.super.call( this, config ); // Properties (must be set before TabIndexedElement constructor call) this.$handle = this.$( '' ); // Mixin constructors OO.ui.IconElement.call( this, config ); OO.ui.IndicatorElement.call( this, config ); OO.ui.LabelElement.call( this, config ); OO.ui.TitledElement.call( this, $.extend( {}, config, { $titled: this.$label } ) ); OO.ui.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$handle } ) ); // Properties this.menu = new OO.ui.MenuSelectWidget( $.extend( { widget: this }, config.menu ) ); // Events this.$handle.on( { click: this.onClick.bind( this ), keypress: this.onKeyPress.bind( this ) } ); this.menu.connect( this, { select: 'onMenuSelect' } ); // Initialization this.$handle .addClass( 'oo-ui-dropdownWidget-handle' ) .append( this.$icon, this.$label, this.$indicator ); this.$element .addClass( 'oo-ui-dropdownWidget' ) .append( this.$handle, this.menu.$element ); }; /* Setup */ OO.inheritClass( OO.ui.DropdownWidget, OO.ui.Widget ); OO.mixinClass( OO.ui.DropdownWidget, OO.ui.IconElement ); OO.mixinClass( OO.ui.DropdownWidget, OO.ui.IndicatorElement ); OO.mixinClass( OO.ui.DropdownWidget, OO.ui.LabelElement ); OO.mixinClass( OO.ui.DropdownWidget, OO.ui.TitledElement ); OO.mixinClass( OO.ui.DropdownWidget, OO.ui.TabIndexedElement ); /* Methods */ /** * Get the menu. * * @return {OO.ui.MenuSelectWidget} Menu of widget */ OO.ui.DropdownWidget.prototype.getMenu = function () { return this.menu; }; /** * Handles menu select events. * * @private * @param {OO.ui.MenuOptionWidget} item Selected menu item */ OO.ui.DropdownWidget.prototype.onMenuSelect = function ( item ) { var selectedLabel; if ( !item ) { return; } selectedLabel = item.getLabel(); // If the label is a DOM element, clone it, because setLabel will append() it if ( selectedLabel instanceof jQuery ) { selectedLabel = selectedLabel.clone(); } this.setLabel( selectedLabel ); }; /** * Handle mouse click events. * * @private * @param {jQuery.Event} e Mouse click event */ OO.ui.DropdownWidget.prototype.onClick = function ( e ) { if ( !this.isDisabled() && e.which === 1 ) { this.menu.toggle(); } return false; }; /** * Handle key press events. * * @private * @param {jQuery.Event} e Key press event */ OO.ui.DropdownWidget.prototype.onKeyPress = function ( e ) { if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) { this.menu.toggle(); return false; } };