Merge "Align "What's this" vertically"
[lhc/web/wiklou.git] / resources / src / mediawiki.widgets / mw.widgets.SelectWithInputWidget.js
1 /*!
2 * MediaWiki Widgets - SelectWithInputWidget class.
3 *
4 * @copyright 2011-2017 MediaWiki Widgets Team and others; see AUTHORS.txt
5 * @license The MIT License (MIT); see LICENSE.txt
6 */
7 ( function ( $, mw ) {
8
9 /**
10 * Select with input widget. Displays an OO.ui.TextInputWidget along with
11 * an OO.ui.DropdownInputWidget.
12 * TODO Explain the OTHER option
13 *
14 * mw.loader.using( 'mediawiki.widgets.SelectWithInputWidget', function () {
15 * var swi = new mw.widgets.SelectWithInputWidget( {
16 * or: true,
17 * dropdowninput: {
18 * options: [
19 * { data: 'other', label: 'Other' },
20 * { data: 'a', label: 'First' },
21 * { data: 'b', label: 'Second' },
22 * { data: 'c', label: 'Third' }
23 * ]
24 * },
25 * textinput: {
26 * }
27 * } );
28 *
29 * $( 'body' ).append( swi.$element );
30 * } );
31 *
32 * @class mw.widgets.SelectWithInputWidget
33 * @extends OO.ui.Widget
34 *
35 * @constructor
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 */
42 mw.widgets.SelectWithInputWidget = function MwWidgetsSelectWithInputWidget( config ) {
43 // Config initialization
44 config = $.extend( { or: false }, config );
45
46 // Properties
47 this.textinput = new OO.ui.TextInputWidget( config.textinput );
48 this.dropdowninput = new OO.ui.DropdownInputWidget( config.dropdowninput );
49 this.or = config.or;
50
51 // Events
52 this.dropdowninput.on( 'change', this.onChange.bind( this ) );
53
54 // Parent constructor
55 mw.widgets.SelectWithInputWidget.parent.call( this, config );
56
57 // Initialization
58 this.$element
59 .addClass( 'mw-widget-selectWithInputWidget' )
60 .append(
61 this.dropdowninput.$element,
62 this.textinput.$element
63 );
64 this.onChange();
65 };
66
67 /* Setup */
68 OO.inheritClass( mw.widgets.SelectWithInputWidget, OO.ui.Widget );
69
70 /* Static Methods */
71
72 /**
73 * @inheritdoc
74 */
75 mw.widgets.SelectWithInputWidget.static.reusePreInfuseDOM = function ( node, config ) {
76 config = mw.widgets.SelectWithInputWidget.parent.static.reusePreInfuseDOM( node, config );
77 config.dropdowninput = OO.ui.DropdownInputWidget.static.reusePreInfuseDOM(
78 $( node ).find( '.oo-ui-dropdownInputWidget' ),
79 config.dropdowninput
80 );
81 config.textinput = OO.ui.TextInputWidget.static.reusePreInfuseDOM(
82 $( node ).find( '.oo-ui-textInputWidget' ),
83 config.textinput
84 );
85 return config;
86 };
87
88 /**
89 * @inheritdoc
90 */
91 mw.widgets.SelectWithInputWidget.static.gatherPreInfuseState = function ( node, config ) {
92 var state = mw.widgets.SelectWithInputWidget.parent.static.gatherPreInfuseState( node, config );
93 state.dropdowninput = OO.ui.DropdownInputWidget.static.gatherPreInfuseState(
94 $( node ).find( '.oo-ui-dropdownInputWidget' ),
95 config.dropdowninput
96 );
97 state.textinput = OO.ui.TextInputWidget.static.gatherPreInfuseState(
98 $( node ).find( '.oo-ui-textInputWidget' ),
99 config.textinput
100 );
101 return state;
102 };
103
104 /* Methods */
105
106 /**
107 * @inheritdoc
108 */
109 mw.widgets.SelectWithInputWidget.prototype.restorePreInfuseState = function ( state ) {
110 mw.widgets.SelectWithInputWidget.parent.prototype.restorePreInfuseState.call( this, state );
111 this.dropdowninput.restorePreInfuseState( state.dropdowninput );
112 this.textinput.restorePreInfuseState( state.textinput );
113 };
114
115 /**
116 * @inheritdoc
117 */
118 mw.widgets.SelectWithInputWidget.prototype.setDisabled = function ( disabled ) {
119 var textinputIsHidden = this.or && this.dropdowninput.getValue() !== 'other';
120 mw.widgets.SelectWithInputWidget.parent.prototype.setDisabled.call( this, disabled );
121 this.dropdowninput.setDisabled( disabled );
122 // It is impossible to submit a form with hidden fields failing validation, e.g. one that
123 // is required. However, validity is not checked for disabled fields, as these are not
124 // submitted with the form. So we should also disable fields when hiding them.
125 this.textinput.setDisabled( textinputIsHidden || disabled );
126 };
127
128 /**
129 * Handle change events on the DropdownInput
130 *
131 * @param {string|undefined} value
132 * @private
133 */
134 mw.widgets.SelectWithInputWidget.prototype.onChange = function ( value ) {
135 if ( this.or ) {
136 value = value || this.dropdowninput.getValue();
137 this.textinput.$element.toggle( value === 'other' );
138 // It is impossible to submit a form with hidden fields failing validation, e.g. one that
139 // is required. However, validity is not checked for disabled fields, as these are not
140 // submitted with the form. So we should also disable fields when hiding them.
141 this.textinput.setDisabled( value !== 'other' || this.isDisabled() );
142 }
143 };
144
145 }( jQuery, mediaWiki ) );