2 * MediaWiki Widgets - SelectWithInputWidget class.
4 * @copyright 2011-2017 MediaWiki Widgets Team and others; see AUTHORS.txt
5 * @license The MIT License (MIT); see LICENSE.txt
10 * Select with input widget. Displays an OO.ui.TextInputWidget along with
11 * an OO.ui.DropdownInputWidget.
12 * TODO Explain the OTHER option
14 * mw.loader.using( 'mediawiki.widgets.SelectWithInputWidget', function () {
15 * var swi = new mw.widgets.SelectWithInputWidget( {
19 * { data: 'other', label: 'Other' },
20 * { data: 'a', label: 'First' },
21 * { data: 'b', label: 'Second' },
22 * { data: 'c', label: 'Third' }
29 * $( 'body' ).append( swi.$element );
32 * @class mw.widgets.SelectWithInputWidget
33 * @extends OO.ui.Widget
36 * @param {Object} [config] Configuration options
37 * @cfg {Object} [dropdowninput] Config for the dropdown
38 * @cfg {Object} [textinput] Config for the text input
39 * @cfg {boolean} [or=false] Config for whether the widget is dropdown AND input
40 * or dropdown OR input
41 * @cfg {boolean} [required=false] Config for whether input is required
43 mw
.widgets
.SelectWithInputWidget
= function MwWidgetsSelectWithInputWidget( config
) {
44 // Config initialization
45 config
= $.extend( { or
: false, required
: false }, config
);
48 this.textinput
= new OO
.ui
.TextInputWidget( config
.textinput
);
49 this.dropdowninput
= new OO
.ui
.DropdownInputWidget( config
.dropdowninput
);
51 this.required
= config
.required
;
54 this.dropdowninput
.on( 'change', this.onChange
.bind( this ) );
55 this.textinput
.on( 'change', function () {
56 this.emit( 'change', this.getValue() );
60 mw
.widgets
.SelectWithInputWidget
.parent
.call( this, config
);
64 .addClass( 'mw-widget-selectWithInputWidget' )
66 this.dropdowninput
.$element
,
67 this.textinput
.$element
73 OO
.inheritClass( mw
.widgets
.SelectWithInputWidget
, OO
.ui
.Widget
);
80 mw
.widgets
.SelectWithInputWidget
.static.reusePreInfuseDOM = function ( node
, config
) {
81 config
= mw
.widgets
.SelectWithInputWidget
.parent
.static.reusePreInfuseDOM( node
, config
);
82 config
.dropdowninput
= OO
.ui
.DropdownInputWidget
.static.reusePreInfuseDOM(
83 $( node
).find( '.oo-ui-dropdownInputWidget' ),
86 config
.textinput
= OO
.ui
.TextInputWidget
.static.reusePreInfuseDOM(
87 $( node
).find( '.oo-ui-textInputWidget' ),
96 mw
.widgets
.SelectWithInputWidget
.static.gatherPreInfuseState = function ( node
, config
) {
97 var state
= mw
.widgets
.SelectWithInputWidget
.parent
.static.gatherPreInfuseState( node
, config
);
98 state
.dropdowninput
= OO
.ui
.DropdownInputWidget
.static.gatherPreInfuseState(
99 $( node
).find( '.oo-ui-dropdownInputWidget' ),
102 state
.textinput
= OO
.ui
.TextInputWidget
.static.gatherPreInfuseState(
103 $( node
).find( '.oo-ui-textInputWidget' ),
114 mw
.widgets
.SelectWithInputWidget
.prototype.restorePreInfuseState = function ( state
) {
115 mw
.widgets
.SelectWithInputWidget
.parent
.prototype.restorePreInfuseState
.call( this, state
);
116 this.dropdowninput
.restorePreInfuseState( state
.dropdowninput
);
117 this.textinput
.restorePreInfuseState( state
.textinput
);
123 mw
.widgets
.SelectWithInputWidget
.prototype.setDisabled = function ( disabled
) {
124 var textinputIsHidden
= this.or
&& this.dropdowninput
.getValue() !== 'other';
125 mw
.widgets
.SelectWithInputWidget
.parent
.prototype.setDisabled
.call( this, disabled
);
126 this.dropdowninput
.setDisabled( disabled
);
127 // It is impossible to submit a form with hidden fields failing validation, e.g. one that
128 // is required. However, validity is not checked for disabled fields, as these are not
129 // submitted with the form. So we should also disable fields when hiding them.
130 this.textinput
.setDisabled( textinputIsHidden
|| disabled
);
131 // If the widget is required, set the text field as required, but only if the widget is visible.
132 if ( this.required
) {
133 this.textinput
.setRequired( !this.textinput
.isDisabled() );
138 * Set the value from outside.
140 * @param {string|undefined} value
142 mw
.widgets
.SelectWithInputWidget
.prototype.setValue = function ( value
) {
143 var selectable
= false;
146 if ( value
!== 'other' ) {
147 selectable
= !!this.dropdowninput
.dropdownWidget
.getMenu().findItemFromData( value
);
151 this.dropdowninput
.setValue( value
);
152 this.textinput
.setValue( undefined );
154 this.dropdowninput
.setValue( 'other' );
155 this.textinput
.setValue( value
);
158 this.emit( 'change', value
);
163 * Get the value from outside.
167 mw
.widgets
.SelectWithInputWidget
.prototype.getValue = function () {
169 if ( this.dropdowninput
.getValue() !== 'other' ) {
170 return this.dropdowninput
.getValue();
173 return this.textinput
.getValue();
180 * Handle change events on the DropdownInput
182 * @param {string|undefined} value
185 mw
.widgets
.SelectWithInputWidget
.prototype.onChange = function ( value
) {
187 value
= value
|| this.dropdowninput
.getValue();
188 this.textinput
.$element
.toggle( value
=== 'other' );
189 // It is impossible to submit a form with hidden fields failing validation, e.g. one that
190 // is required. However, validity is not checked for disabled fields, as these are not
191 // submitted with the form. So we should also disable fields when hiding them.
192 this.textinput
.setDisabled( value
!== 'other' || this.isDisabled() );
195 this.emit( 'change', this.getValue() );