X-Git-Url: https://git.cyclocoop.org/?a=blobdiff_plain;f=resources%2Fsrc%2Fmediawiki%2Fmediawiki.htmlform.js;h=f7aa7f8bd011d0d28ecd065af8a80a9e5d913733;hb=2b8254b2b5f5d1a698f298204410f22a393ab9fb;hp=5ba1a54dd677373bdbd406d7bb6c2553734fa82b;hpb=c45d497eda452d619b61b0da231c1c753d8cac93;p=lhc%2Fweb%2Fwiklou.git diff --git a/resources/src/mediawiki/mediawiki.htmlform.js b/resources/src/mediawiki/mediawiki.htmlform.js index 5ba1a54dd6..f7aa7f8bd0 100644 --- a/resources/src/mediawiki/mediawiki.htmlform.js +++ b/resources/src/mediawiki/mediawiki.htmlform.js @@ -5,6 +5,177 @@ */ ( function ( mw, $ ) { + var cloneCounter = 0; + + /** + * Helper function for hide-if to find the nearby form field. + * + * Find the closest match for the given name, "closest" being the minimum + * level of parents to go to find a form field matching the given name or + * ending in array keys matching the given name (e.g. "baz" matches + * "foo[bar][baz]"). + * + * @param {jQuery} element + * @param {string} name + * @return {jQuery|null} + */ + function hideIfGetField( $el, name ) { + var sel, $found, $p; + + sel = '[name="' + name + '"],' + + '[name="wp' + name + '"],' + + '[name$="' + name.replace( /^([^\[]+)/, '[$1]' ) + '"]'; + for ( $p = $el.parent(); $p.length > 0; $p = $p.parent() ) { + $found = $p.find( sel ); + if ( $found.length > 0 ) { + return $found; + } + } + return null; + } + + /** + * Helper function for hide-if to return a test function and list of + * dependent fields for a hide-if specification. + * + * @param {jQuery} element + * @param {Array} hide-if spec + * @return {Array} 2 elements: jQuery of dependent fields, and test function + */ + function hideIfParse( $el, spec ) { + var op, i, l, v, $field, $fields, func, funcs, getVal; + + op = spec[0]; + l = spec.length; + switch ( op ) { + case 'AND': + case 'OR': + case 'NAND': + case 'NOR': + funcs = []; + $fields = $(); + for ( i = 1; i < l; i++ ) { + if ( !$.isArray( spec[i] ) ) { + throw new Error( op + ' parameters must be arrays' ); + } + v = hideIfParse( $el, spec[i] ); + $fields = $fields.add( v[0] ); + funcs.push( v[1] ); + } + + l = funcs.length; + switch ( op ) { + case 'AND': + func = function () { + var i; + for ( i = 0; i < l; i++ ) { + if ( !funcs[i]() ) { + return false; + } + } + return true; + }; + break; + + case 'OR': + func = function () { + var i; + for ( i = 0; i < l; i++ ) { + if ( funcs[i]() ) { + return true; + } + } + return false; + }; + break; + + case 'NAND': + func = function () { + var i; + for ( i = 0; i < l; i++ ) { + if ( !funcs[i]() ) { + return true; + } + } + return false; + }; + break; + + case 'NOR': + func = function () { + var i; + for ( i = 0; i < l; i++ ) { + if ( funcs[i]() ) { + return false; + } + } + return true; + }; + break; + } + + return [ $fields, func ]; + + case 'NOT': + if ( l !== 2 ) { + throw new Error( 'NOT takes exactly one parameter' ); + } + if ( !$.isArray( spec[1] ) ) { + throw new Error( 'NOT parameters must be arrays' ); + } + v = hideIfParse( $el, spec[1] ); + $fields = v[0]; + func = v[1]; + return [ $fields, function () { + return !func(); + } ]; + + case '===': + case '!==': + if ( l !== 3 ) { + throw new Error( op + ' takes exactly two parameters' ); + } + $field = hideIfGetField( $el, spec[1] ); + if ( !$field ) { + return [ $(), function () { + return false; + } ]; + } + v = spec[2]; + + if ( $field.first().attr( 'type' ) === 'radio' || + $field.first().attr( 'type' ) === 'checkbox' + ) { + getVal = function () { + var $selected = $field.filter( ':checked' ); + return $selected.length > 0 ? $selected.val() : ''; + }; + } else { + getVal = function () { + return $field.val(); + }; + } + + switch ( op ) { + case '===': + func = function () { + return getVal() === v; + }; + break; + case '!==': + func = function () { + return getVal() !== v; + }; + break; + } + + return [ $field, func ]; + + default: + throw new Error( 'Unrecognized operation \'' + op + '\'' ); + } + } + /** * jQuery plugin to fade or snap to visible state. * @@ -48,12 +219,12 @@ } ); }; - $( function () { + function enhance( $root ) { // Animate the SelectOrOther fields, to only show the text field when // 'other' is selected. - $( '.mw-htmlform-select-or-other' ).liveAndTestAtStart( function ( instant ) { - var $other = $( '#' + $( this ).attr( 'id' ) + '-other' ); + $root.find( '.mw-htmlform-select-or-other' ).liveAndTestAtStart( function ( instant ) { + var $other = $root.find( '#' + $( this ).attr( 'id' ) + '-other' ); $other = $other.add( $other.siblings( 'br' ) ); if ( $( this ).val() === 'other' ) { $other.goIn( instant ); @@ -62,73 +233,126 @@ } } ); - } ); + // Set up hide-if elements + $root.find( '.mw-htmlform-hide-if' ).each( function () { + var $el = $( this ), + spec = $el.data( 'hideIf' ), + v, $fields, test, func; - function addMulti( $oldContainer, $container ) { - var name = $oldContainer.find( 'input:first-child' ).attr( 'name' ), - oldClass = ( ' ' + $oldContainer.attr( 'class' ) + ' ' ).replace( /(mw-htmlform-field-HTMLMultiSelectField|mw-chosen)/g, '' ), - $select = $( '' ), + dataPlaceholder = mw.message( 'htmlform-chosen-placeholder' ); + oldClass = $.trim( oldClass ); + $select.attr( { + name: name, + multiple: 'multiple', + 'data-placeholder': dataPlaceholder.plain(), + 'class': 'htmlform-chzn-select mw-input ' + oldClass + } ); + $oldContainer.find( 'input' ).each( function () { + var $oldInput = $( this ), + checked = $oldInput.prop( 'checked' ), + $option = $( '