def29fcc068b5e163c68372641cd9e346aea8045
2 * Utility functions for jazzing up HTMLForm elements.
4 * @class jQuery.plugin.htmlform
9 * Helper function for hide-if to find the nearby form field.
11 * Find the closest match for the given name, "closest" being the minimum
12 * level of parents to go to find a form field matching the given name or
13 * ending in array keys matching the given name (e.g. "baz" matches
16 * @param {jQuery} element
17 * @param {string} name
18 * @return {jQuery|null}
20 function hideIfGetField( $el
, name
) {
23 sel
= '[name="' + name
+ '"],' +
24 '[name="wp' + name
+ '"],' +
25 '[name$="' + name
.replace( /^([^\[]+)/, '[$1]' ) + '"]';
26 for ( $p
= $el
.parent(); $p
.length
> 0; $p
= $p
.parent() ) {
27 $found
= $p
.find( sel
);
28 if ( $found
.length
> 0 ) {
36 * Helper function for hide-if to return a test function and list of
37 * dependent fields for a hide-if specification.
39 * @param {jQuery} element
40 * @param {Array} hide-if spec
41 * @return {Array} 2 elements: jQuery of dependent fields, and test function
43 function hideIfParse( $el
, spec
) {
44 var op
, i
, l
, v
, $field
, $fields
, func
, funcs
, getVal
;
55 for ( i
= 1; i
< l
; i
++ ) {
56 if ( !$.isArray( spec
[i
] ) ) {
57 throw new Error( op
+ ' parameters must be arrays' );
59 v
= hideIfParse( $el
, spec
[i
] );
60 $fields
= $fields
.add( v
[0] );
69 for ( i
= 0; i
< l
; i
++ ) {
81 for ( i
= 0; i
< l
; i
++ ) {
93 for ( i
= 0; i
< l
; i
++ ) {
105 for ( i
= 0; i
< l
; i
++ ) {
115 return [ $fields
, func
];
119 throw new Error( 'NOT takes exactly one parameter' );
121 if ( !$.isArray( spec
[1] ) ) {
122 throw new Error( 'NOT parameters must be arrays' );
124 v
= hideIfParse( $el
, spec
[1] );
127 return [ $fields
, function () {
134 throw new Error( op
+ ' takes exactly two parameters' );
136 $field
= hideIfGetField( $el
, spec
[1] );
138 return [ $(), function () {
144 if ( $field
.first().attr( 'type' ) === 'radio' ||
145 $field
.first().attr( 'type' ) === 'checkbox'
147 getVal = function () {
148 var $selected
= $field
.filter( ':checked' );
149 return $selected
.length
> 0 ? $selected
.val() : '';
152 getVal = function () {
160 return getVal() === v
;
165 return getVal() !== v
;
170 return [ $field
, func
];
173 throw new Error( 'Unrecognized operation \'' + op
+ '\'' );
178 * jQuery plugin to fade or snap to visible state.
180 * @param {boolean} [instantToggle=false]
184 $.fn
.goIn = function ( instantToggle
) {
185 if ( instantToggle
=== true ) {
186 return $( this ).show();
188 return $( this ).stop( true, true ).fadeIn();
192 * jQuery plugin to fade or snap to hiding state.
194 * @param {boolean} [instantToggle=false]
198 $.fn
.goOut = function ( instantToggle
) {
199 if ( instantToggle
=== true ) {
200 return $( this ).hide();
202 return $( this ).stop( true, true ).fadeOut();
206 * Bind a function to the jQuery object via live(), and also immediately trigger
207 * the function on the objects with an 'instant' parameter set to true.
208 * @param {Function} callback
209 * @param {boolean|jQuery.Event} callback.immediate True when the event is called immediately,
210 * an event object when triggered from an event.
212 $.fn
.liveAndTestAtStart = function ( callback
) {
214 .live( 'change', callback
)
216 callback
.call( this, true );
222 // Animate the SelectOrOther fields, to only show the text field when
223 // 'other' is selected.
224 $( '.mw-htmlform-select-or-other' ).liveAndTestAtStart( function ( instant
) {
225 var $other
= $( '#' + $( this ).attr( 'id' ) + '-other' );
226 $other
= $other
.add( $other
.siblings( 'br' ) );
227 if ( $( this ).val() === 'other' ) {
228 $other
.goIn( instant
);
230 $other
.goOut( instant
);
234 // Set up hide-if elements
235 $( '.mw-htmlform-hide-if' ).each( function () {
237 spec
= $el
.data( 'hideIf' ),
238 v
, $fields
, test
, func
;
244 v
= hideIfParse( $el
, spec
);
254 $fields
.change( func
);
260 function addMulti( $oldContainer
, $container
) {
261 var name
= $oldContainer
.find( 'input:first-child' ).attr( 'name' ),
262 oldClass
= ( ' ' + $oldContainer
.attr( 'class' ) + ' ' ).replace( /(mw-htmlform-field-HTMLMultiSelectField|mw-chosen)/g, '' ),
263 $select
= $( '<select>' ),
264 dataPlaceholder
= mw
.message( 'htmlform-chosen-placeholder' );
265 oldClass
= $.trim( oldClass
);
268 multiple
: 'multiple',
269 'data-placeholder': dataPlaceholder
.plain(),
270 'class': 'htmlform-chzn-select mw-input ' + oldClass
272 $oldContainer
.find( 'input' ).each( function () {
273 var $oldInput
= $( this ),
274 checked
= $oldInput
.prop( 'checked' ),
275 $option
= $( '<option>' );
276 $option
.prop( 'value', $oldInput
.prop( 'value' ) );
278 $option
.prop( 'selected', true );
280 $option
.text( $oldInput
.prop( 'value' ) );
281 $select
.append( $option
);
283 $container
.append( $select
);
286 function convertCheckboxesToMulti( $oldContainer
, type
) {
287 var $fieldLabel
= $( '<td>' ),
289 $fieldLabelText
= $( '<label>' ),
291 if ( type
=== 'tr' ) {
292 addMulti( $oldContainer
, $td
);
293 $container
= $( '<tr>' );
294 $container
.append( $td
);
295 } else if ( type
=== 'div' ) {
296 $fieldLabel
= $( '<div>' );
297 $container
= $( '<div>' );
298 addMulti( $oldContainer
, $container
);
300 $fieldLabel
.attr( 'class', 'mw-label' );
301 $fieldLabelText
.text( $oldContainer
.find( '.mw-label label' ).text() );
302 $fieldLabel
.append( $fieldLabelText
);
303 $container
.prepend( $fieldLabel
);
304 $oldContainer
.replaceWith( $container
);
308 if ( $( '.mw-chosen' ).length
) {
309 mw
.loader
.using( 'jquery.chosen', function () {
310 $( '.mw-chosen' ).each( function () {
311 var type
= this.nodeName
.toLowerCase(),
312 $converted
= convertCheckboxesToMulti( $( this ), type
);
313 $converted
.find( '.htmlform-chzn-select' ).chosen( { width
: 'auto' } );
319 var $matrixTooltips
= $( '.mw-htmlform-matrix .mw-htmlform-tooltip' );
320 if ( $matrixTooltips
.length
) {
321 mw
.loader
.using( 'jquery.tipsy', function () {
322 $matrixTooltips
.tipsy( { gravity
: 's' } );
329 * @mixins jQuery.plugin.htmlform
331 }( mediaWiki
, jQuery
) );