diff options
Diffstat (limited to 'vendor/oojs/oojs-ui/src/widgets/ComboBoxWidget.js')
-rw-r--r-- | vendor/oojs/oojs-ui/src/widgets/ComboBoxWidget.js | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/vendor/oojs/oojs-ui/src/widgets/ComboBoxWidget.js b/vendor/oojs/oojs-ui/src/widgets/ComboBoxWidget.js new file mode 100644 index 00000000..346d17ee --- /dev/null +++ b/vendor/oojs/oojs-ui/src/widgets/ComboBoxWidget.js @@ -0,0 +1,230 @@ +/** + * ComboBoxWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value + * can be entered manually) and a {@link OO.ui.MenuSelectWidget menu of options} (from which + * a value can be chosen instead). Users can choose options from the combo box in one of two ways: + * + * - by typing a value in the text input field. If the value exactly matches the value of a menu + * option, that option will appear to be selected. + * - by choosing a value from the menu. The value of the chosen option will then appear in the text + * input field. + * + * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1]. + * + * @example + * // Example: A ComboBoxWidget. + * var comboBox = new OO.ui.ComboBoxWidget( { + * label: 'ComboBoxWidget', + * input: { value: 'Option One' }, + * menu: { + * items: [ + * new OO.ui.MenuOptionWidget( { + * data: 'Option 1', + * label: 'Option One' + * } ), + * new OO.ui.MenuOptionWidget( { + * data: 'Option 2', + * label: 'Option Two' + * } ), + * new OO.ui.MenuOptionWidget( { + * data: 'Option 3', + * label: 'Option Three' + * } ), + * new OO.ui.MenuOptionWidget( { + * data: 'Option 4', + * label: 'Option Four' + * } ), + * new OO.ui.MenuOptionWidget( { + * data: 'Option 5', + * label: 'Option Five' + * } ) + * ] + * } + * } ); + * $( 'body' ).append( comboBox.$element ); + * + * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options + * + * @class + * @extends OO.ui.Widget + * @mixins OO.ui.TabIndexedElement + * + * @constructor + * @param {Object} [config] Configuration options + * @cfg {Object} [menu] Configuration options to pass to the {@link OO.ui.MenuSelectWidget menu select widget}. + * @cfg {Object} [input] Configuration options to pass to the {@link OO.ui.TextInputWidget text input widget}. + * @cfg {jQuery} [$overlay] Render the menu into a separate layer. This configuration is useful in cases where + * the expanded menu is larger than its containing `<div>`. The specified overlay layer is usually on top of the + * containing `<div>` and has a larger area. By default, the menu uses relative positioning. + */ +OO.ui.ComboBoxWidget = function OoUiComboBoxWidget( config ) { + // Configuration initialization + config = config || {}; + + // Parent constructor + OO.ui.ComboBoxWidget.super.call( this, config ); + + // Properties (must be set before TabIndexedElement constructor call) + this.$indicator = this.$( '<span>' ); + + // Mixin constructors + OO.ui.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$indicator } ) ); + + // Properties + this.$overlay = config.$overlay || this.$element; + this.input = new OO.ui.TextInputWidget( $.extend( + { + indicator: 'down', + $indicator: this.$indicator, + disabled: this.isDisabled() + }, + config.input + ) ); + this.input.$input.eq( 0 ).attr( { + role: 'combobox', + 'aria-autocomplete': 'list' + } ); + this.menu = new OO.ui.TextInputMenuSelectWidget( this.input, $.extend( + { + widget: this, + input: this.input, + disabled: this.isDisabled() + }, + config.menu + ) ); + + // Events + this.$indicator.on( { + click: this.onClick.bind( this ), + keypress: this.onKeyPress.bind( this ) + } ); + this.input.connect( this, { + change: 'onInputChange', + enter: 'onInputEnter' + } ); + this.menu.connect( this, { + choose: 'onMenuChoose', + add: 'onMenuItemsChange', + remove: 'onMenuItemsChange' + } ); + + // Initialization + this.$element.addClass( 'oo-ui-comboBoxWidget' ).append( this.input.$element ); + this.$overlay.append( this.menu.$element ); + this.onMenuItemsChange(); +}; + +/* Setup */ + +OO.inheritClass( OO.ui.ComboBoxWidget, OO.ui.Widget ); +OO.mixinClass( OO.ui.ComboBoxWidget, OO.ui.TabIndexedElement ); + +/* Methods */ + +/** + * Get the combobox's menu. + * @return {OO.ui.TextInputMenuSelectWidget} Menu widget + */ +OO.ui.ComboBoxWidget.prototype.getMenu = function () { + return this.menu; +}; + +/** + * Handle input change events. + * + * @private + * @param {string} value New value + */ +OO.ui.ComboBoxWidget.prototype.onInputChange = function ( value ) { + var match = this.menu.getItemFromData( value ); + + this.menu.selectItem( match ); + if ( this.menu.getHighlightedItem() ) { + this.menu.highlightItem( match ); + } + + if ( !this.isDisabled() ) { + this.menu.toggle( true ); + } +}; + +/** + * Handle mouse click events. + * + * + * @private + * @param {jQuery.Event} e Mouse click event + */ +OO.ui.ComboBoxWidget.prototype.onClick = function ( e ) { + if ( !this.isDisabled() && e.which === 1 ) { + this.menu.toggle(); + this.input.$input[ 0 ].focus(); + } + return false; +}; + +/** + * Handle key press events. + * + * + * @private + * @param {jQuery.Event} e Key press event + */ +OO.ui.ComboBoxWidget.prototype.onKeyPress = function ( e ) { + if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) { + this.menu.toggle(); + this.input.$input[ 0 ].focus(); + return false; + } +}; + +/** + * Handle input enter events. + * + * @private + */ +OO.ui.ComboBoxWidget.prototype.onInputEnter = function () { + if ( !this.isDisabled() ) { + this.menu.toggle( false ); + } +}; + +/** + * Handle menu choose events. + * + * @private + * @param {OO.ui.OptionWidget} item Chosen item + */ +OO.ui.ComboBoxWidget.prototype.onMenuChoose = function ( item ) { + this.input.setValue( item.getData() ); +}; + +/** + * Handle menu item change events. + * + * @private + */ +OO.ui.ComboBoxWidget.prototype.onMenuItemsChange = function () { + var match = this.menu.getItemFromData( this.input.getValue() ); + this.menu.selectItem( match ); + if ( this.menu.getHighlightedItem() ) { + this.menu.highlightItem( match ); + } + this.$element.toggleClass( 'oo-ui-comboBoxWidget-empty', this.menu.isEmpty() ); +}; + +/** + * @inheritdoc + */ +OO.ui.ComboBoxWidget.prototype.setDisabled = function ( disabled ) { + // Parent method + OO.ui.ComboBoxWidget.super.prototype.setDisabled.call( this, disabled ); + + if ( this.input ) { + this.input.setDisabled( this.isDisabled() ); + } + if ( this.menu ) { + this.menu.setDisabled( this.isDisabled() ); + } + + return this; +}; |