Customize Widgets: Improve sync logic for select[multiple] inputs.

The current logic doesn't account for the special case of `select[multiple]` inputs which lack a single value to synchronize: The value to synchronize is an array of zero or more values.
This change replaces `_getInputStatePropertyName()` with `_getInputState()`, which returns the state for an input depending on its type, and `_setInputState()`, which updates an input's state based on its type.

props westonruter.
fixes #31885.

git-svn-id: https://develop.svn.wordpress.org/trunk@32012 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Dominik Schilling (ocean90) 2015-04-04 16:33:24 +00:00
parent 58ee5beced
commit 9be177ec95
1 changed files with 44 additions and 16 deletions

View File

@ -927,19 +927,50 @@
}, },
/** /**
* Get the property that represents the state of an input. * Get the state for an input depending on its type.
* *
* @param {jQuery|DOMElement} input * @param {jQuery|Element} input
* @returns {string} * @returns {string|boolean|array|*}
* @private * @private
*/ */
_getInputStatePropertyName: function( input ) { _getInputState: function( input ) {
var $input = $( input ); input = $( input );
if ( input.is( ':radio, :checkbox' ) ) {
if ( $input.is( ':radio, :checkbox' ) ) { return input.prop( 'checked' );
return 'checked'; } else if ( input.is( 'select[multiple]' ) ) {
return input.find( 'option:selected' ).map( function () {
return $( this ).val();
} ).get();
} else { } else {
return 'value'; return input.val();
}
},
/**
* Update an input's state based on its type.
*
* @param {jQuery|Element} input
* @param {string|boolean|array|*} state
* @private
*/
_setInputState: function ( input, state ) {
input = $( input );
if ( input.is( ':radio, :checkbox' ) ) {
input.prop( 'checked', state );
} else if ( input.is( 'select[multiple]' ) ) {
if ( ! $.isArray( state ) ) {
state = [];
} else {
// Make sure all state items are strings since the DOM value is a string
state = _.map( state, function ( value ) {
return String( value );
} );
}
input.find( 'option' ).each( function () {
$( this ).prop( 'selected', -1 !== _.indexOf( state, String( this.value ) ) );
} );
} else {
input.val( state );
} }
}, },
@ -1016,9 +1047,7 @@
// we know if it got sanitized; if there is no difference in the sanitized value, // we know if it got sanitized; if there is no difference in the sanitized value,
// then we do not need to touch the UI and mess up the user's ongoing editing. // then we do not need to touch the UI and mess up the user's ongoing editing.
$inputs.each( function() { $inputs.each( function() {
var input = $( this ), $( this ).data( 'state' + updateNumber, self._getInputState( this ) );
property = self._getInputStatePropertyName( this );
input.data( 'state' + updateNumber, input.prop( property ) );
} ); } );
if ( instanceOverride ) { if ( instanceOverride ) {
@ -1071,16 +1100,15 @@
$inputs.each( function( i ) { $inputs.each( function( i ) {
var $input = $( this ), var $input = $( this ),
$sanitizedInput = $( $sanitizedInputs[i] ), $sanitizedInput = $( $sanitizedInputs[i] ),
property = self._getInputStatePropertyName( this ),
submittedState, sanitizedState, canUpdateState; submittedState, sanitizedState, canUpdateState;
submittedState = $input.data( 'state' + updateNumber ); submittedState = $input.data( 'state' + updateNumber );
sanitizedState = $sanitizedInput.prop( property ); sanitizedState = self._getInputState( $sanitizedInput );
$input.data( 'sanitized', sanitizedState ); $input.data( 'sanitized', sanitizedState );
canUpdateState = ( submittedState !== sanitizedState && ( args.ignoreActiveElement || ! $input.is( document.activeElement ) ) ); canUpdateState = ( ! _.isEqual( submittedState, sanitizedState ) && ( args.ignoreActiveElement || ! $input.is( document.activeElement ) ) );
if ( canUpdateState ) { if ( canUpdateState ) {
$input.prop( property, sanitizedState ); self._setInputState( $input, sanitizedState );
} }
} ); } );