2 * HTMLForm enhancements:
3 * Set up 'hide-if' behaviors for form fields that have them.
10 * Helper function for hide-if to find the nearby form field.
12 * Find the closest match for the given name, "closest" being the minimum
13 * level of parents to go to find a form field matching the given name or
14 * ending in array keys matching the given name (e.g. "baz" matches
20 * @param {string} name
21 * @return {jQuery|OO.ui.Widget|null}
23 function hideIfGetField( $el
, name
) {
24 var $found
, $p
, $widget
,
25 suffix
= name
.replace( /^([^\[]+)/, '[$1]' );
27 function nameFilter() {
28 return this.name
=== name
||
29 ( this.name
=== ( 'wp' + name
) ) ||
30 this.name
.slice( -suffix
.length
) === suffix
;
33 for ( $p
= $el
.parent(); $p
.length
> 0; $p
= $p
.parent() ) {
34 $found
= $p
.find( '[name]' ).filter( nameFilter
);
35 if ( $found
.length
) {
36 $widget
= $found
.closest( '.oo-ui-widget[data-ooui]' );
37 if ( $widget
.length
) {
38 return OO
.ui
.Widget
.static.infuse( $widget
);
47 * Helper function for hide-if to return a test function and list of
48 * dependent fields for a hide-if specification.
55 * @return {Array} return.0 Dependent fields, array of jQuery objects or OO.ui.Widgets
56 * @return {Function} return.1 Test function
58 function hideIfParse( $el
, spec
) {
59 var op
, i
, l
, v
, field
, $field
, fields
, func
, funcs
, getVal
;
70 for ( i
= 1; i
< l
; i
++ ) {
71 if ( !$.isArray( spec
[ i
] ) ) {
72 throw new Error( op
+ ' parameters must be arrays' );
74 v
= hideIfParse( $el
, spec
[ i
] );
75 fields
= fields
.concat( v
[ 0 ] );
84 for ( i
= 0; i
< l
; i
++ ) {
85 if ( !funcs
[ i
]() ) {
96 for ( i
= 0; i
< l
; i
++ ) {
108 for ( i
= 0; i
< l
; i
++ ) {
109 if ( !funcs
[ i
]() ) {
120 for ( i
= 0; i
< l
; i
++ ) {
121 if ( funcs
[ i
]() ) {
130 return [ fields
, func
];
134 throw new Error( 'NOT takes exactly one parameter' );
136 if ( !$.isArray( spec
[ 1 ] ) ) {
137 throw new Error( 'NOT parameters must be arrays' );
139 v
= hideIfParse( $el
, spec
[ 1 ] );
142 return [ fields
, function () {
149 throw new Error( op
+ ' takes exactly two parameters' );
151 field
= hideIfGetField( $el
, spec
[ 1 ] );
153 return [ [], function () {
159 if ( field
instanceof OO
.ui
.Widget
) {
160 if ( field
.supports( 'isSelected' ) ) {
161 getVal = function () {
162 var selected
= field
.isSelected();
163 return selected
? field
.getValue() : '';
166 getVal = function () {
167 return field
.getValue();
172 if ( $field
.prop( 'type' ) === 'radio' || $field
.prop( 'type' ) === 'checkbox' ) {
173 getVal = function () {
174 var $selected
= $field
.filter( ':checked' );
175 return $selected
.length
? $selected
.val() : '';
178 getVal = function () {
187 return getVal() === v
;
192 return getVal() !== v
;
197 return [ [ field
], func
];
200 throw new Error( 'Unrecognized operation \'' + op
+ '\'' );
204 mw
.hook( 'htmlform.enhance' ).add( function ( $root
) {
205 $root
.find( '.mw-htmlform-hide-if' ).each( function () {
206 var v
, i
, fields
, test
, func
, spec
, self
, modules
, data
,extraModules
,
210 if ( $el
.is( '[data-ooui]' ) ) {
211 modules
.push( 'mediawiki.htmlform.ooui' );
212 data
= $el
.data( 'mw-modules' );
214 // We can trust this value, 'data-mw-*' attributes are banned from user content in Sanitizer
215 extraModules
= data
.split( ',' );
216 modules
.push
.apply( modules
, extraModules
);
220 mw
.loader
.using( modules
).done( function () {
221 if ( $el
.is( '[data-ooui]' ) ) {
222 // self should be a FieldLayout that mixes in mw.htmlform.Element
223 self
= OO
.ui
.FieldLayout
.static.infuse( $el
);
225 // The original element has been replaced with infused one
229 spec
= $el
.data( 'hideIf' );
236 v
= hideIfParse( $el
, spec
);
239 // The .toggle() method works mostly the same for jQuery objects and OO.ui.Widget
241 self
.toggle( !test() );
243 for ( i
= 0; i
< fields
.length
; i
++ ) {
244 // The .on() method works mostly the same for jQuery objects and OO.ui.Widget
245 fields
[ i
].on( 'change', func
);
252 }( mediaWiki
, jQuery
) );