// If the available widgets panel is open and the customize controls are
// interacted with (i.e. available widgets panel is blurred) then close the
- // available widgets panel.
- $( '#customize-controls' ).on( 'click keydown', function( e ) {
+ // available widgets panel. Also close on back button click.
+ $( '#customize-controls, #available-widgets .customize-section-title' ).on( 'click keydown', function( e ) {
var isAddNewBtn = $( e.target ).is( '.add-new-widget, .add-new-widget *' );
if ( $( 'body' ).hasClass( 'adding-widget' ) && ! isAddNewBtn ) {
self.close();
// Adds a selected widget to the sidebar
submit: function( widgetTpl ) {
- var widgetId, widget;
+ var widgetId, widget, widgetFormControl;
if ( ! widgetTpl ) {
widgetTpl = this.selected;
return;
}
- this.currentSidebarControl.addWidget( widget.get( 'id_base' ) );
+ widgetFormControl = this.currentSidebarControl.addWidget( widget.get( 'id_base' ) );
+ if ( widgetFormControl ) {
+ widgetFormControl.focus();
+ }
this.close();
},
// Reset search
this.collection.doSearch( '' );
- this.$search.focus();
+ if ( ! api.settings.browser.mobile ) {
+ this.$search.focus();
+ }
},
// Closes the panel
this.close( { returnFocus: true } );
}
- if ( isTab && ( isShift && isSearchFocused || ! isShift && isLastWidgetFocused ) ) {
+ if ( this.currentSidebarControl && isTab && ( isShift && isSearchFocused || ! isShift && isLastWidgetFocused ) ) {
this.currentSidebarControl.container.find( '.add-new-widget' ).focus();
event.preventDefault();
}
* Update available sidebars when their rendered state changes
*/
updateAvailableSidebars = function() {
- var $sidebarItems = $moveWidgetArea.find( 'li' ), selfSidebarItem;
+ var $sidebarItems = $moveWidgetArea.find( 'li' ), selfSidebarItem,
+ renderedSidebarCount = 0;
selfSidebarItem = $sidebarItems.filter( function(){
return $( this ).data( 'id' ) === self.params.sidebar_id;
$sidebarItems.each( function() {
var li = $( this ),
- sidebarId,
- sidebar;
+ sidebarId, sidebar, sidebarIsRendered;
sidebarId = li.data( 'id' );
sidebar = api.Widgets.registeredSidebars.get( sidebarId );
+ sidebarIsRendered = sidebar.get( 'is_rendered' );
- li.toggle( sidebar.get( 'is_rendered' ) );
+ li.toggle( sidebarIsRendered );
- if ( li.hasClass( 'selected' ) && ! sidebar.get( 'is_rendered' ) ) {
+ if ( sidebarIsRendered ) {
+ renderedSidebarCount += 1;
+ }
+
+ if ( li.hasClass( 'selected' ) && ! sidebarIsRendered ) {
selectSidebarItem( selfSidebarItem );
}
} );
+
+ if ( renderedSidebarCount > 1 ) {
+ self.container.find( '.move-widget' ).show();
+ } else {
+ self.container.find( '.move-widget' ).hide();
+ }
};
updateAvailableSidebars();
if ( isMoveUp ) {
self.moveUp();
- $( '#screen-reader-messages' ).text( l10n.widgetMovedUp );
+ wp.a11y.speak( l10n.widgetMovedUp );
} else {
self.moveDown();
- $( '#screen-reader-messages' ).text( l10n.widgetMovedDown );
+ wp.a11y.speak( l10n.widgetMovedDown );
}
$( this ).focus(); // re-focus after the container was moved
/**
* Handle selecting a sidebar to move to
*/
- this.container.find( '.widget-area-select' ).on( 'click keypress', 'li', function( e ) {
+ this.container.find( '.widget-area-select' ).on( 'click keypress', 'li', function( event ) {
if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
return;
}
- e.preventDefault();
+ event.preventDefault();
selectSidebarItem( $( this ) );
} );
// Handle widgets that support live previews
$widgetContent.on( 'change input propertychange', ':input', function( e ) {
- if ( self.liveUpdateMode ) {
- if ( e.type === 'change' ) {
- self.updateWidget();
- } else if ( this.checkValidity && this.checkValidity() ) {
- updateWidgetDebounced();
- }
+ if ( ! self.liveUpdateMode ) {
+ return;
+ }
+ if ( e.type === 'change' || ( this.checkValidity && this.checkValidity() ) ) {
+ updateWidgetDebounced();
}
} );
},
/**
- * Get the property that represents the state of an input.
+ * Get the state for an input depending on its type.
*
- * @param {jQuery|DOMElement} input
- * @returns {string}
+ * @param {jQuery|Element} input
+ * @returns {string|boolean|array|*}
* @private
*/
- _getInputStatePropertyName: function( input ) {
- var $input = $( input );
+ _getInputState: function( input ) {
+ input = $( input );
+ if ( input.is( ':radio, :checkbox' ) ) {
+ return input.prop( 'checked' );
+ } else if ( input.is( 'select[multiple]' ) ) {
+ return input.find( 'option:selected' ).map( function () {
+ return $( this ).val();
+ } ).get();
+ } else {
+ return input.val();
+ }
+ },
- if ( $input.is( ':radio, :checkbox' ) ) {
- return 'checked';
+ /**
+ * 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 {
- return 'value';
+ input.val( state );
}
},
params.wp_customize = 'on';
params.nonce = api.Widgets.data.nonce;
params.theme = api.settings.theme.stylesheet;
+ params.customized = wp.customize.previewer.query().customized;
data = $.param( params );
$inputs = this._getInputs( $widgetContent );
// 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.
$inputs.each( function() {
- var input = $( this ),
- property = self._getInputStatePropertyName( this );
- input.data( 'state' + updateNumber, input.prop( property ) );
+ $( this ).data( 'state' + updateNumber, self._getInputState( this ) );
} );
if ( instanceOverride ) {
}
data += '&' + $widgetContent.find( '~ :input' ).serialize();
+ if ( this._previousUpdateRequest ) {
+ this._previousUpdateRequest.abort();
+ }
jqxhr = $.post( wp.ajax.settings.url, data );
+ this._previousUpdateRequest = jqxhr;
jqxhr.done( function( r ) {
var message, sanitizedForm, $sanitizedInputs, hasSameInputsInResponse,
$inputs.each( function( i ) {
var $input = $( this ),
$sanitizedInput = $( $sanitizedInputs[i] ),
- property = self._getInputStatePropertyName( this ),
submittedState, sanitizedState, canUpdateState;
submittedState = $input.data( 'state' + updateNumber );
- sanitizedState = $sanitizedInput.prop( property );
+ sanitizedState = self._getInputState( $sanitizedInput );
$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 ) {
- $input.prop( property, sanitizedState );
+ self._setInputState( $input, sanitizedState );
}
} );
if ( expanded ) {
- self.expandControlSection();
+ if ( self.section() && api.section( self.section() ) ) {
+ self.expandControlSection();
+ }
// Close all other widget controls before expanding this one
api.control.each( function( otherControl ) {
items: '> .customize-control-widget_form',
handle: '.widget-top',
axis: 'y',
+ tolerance: 'pointer',
connectWith: '.accordion-section-content:has(.customize-control-sidebar_widgets)',
update: function() {
var widgetContainerIds = self.$sectionContent.sortable( 'toArray' ), widgetIds;
});
if ( ! widgetControls.length ) {
+ this.container.find( '.reorder-toggle' ).hide();
return;
+ } else {
+ this.container.find( '.reorder-toggle' ).show();
}
$( widgetControls ).each( function () {
},
/**
+ * Get the widget_form Customize controls associated with the current sidebar.
+ *
+ * @since 3.9
* @return {wp.customize.controlConstructor.widget_form[]}
*/
getWidgetFormControls: function() {
- var formControls;
+ var formControls = [];
- formControls = _( this.setting() ).map( function( widgetId ) {
+ _( this.setting() ).each( function( widgetId ) {
var settingId = widgetIdToSettingId( widgetId ),
formControl = api.control( settingId );
-
- if ( ! formControl ) {
- return;
+ if ( formControl ) {
+ formControls.push( formControl );
}
-
- return formControl;
} );
return formControls;
controlContainer.slideDown( function() {
if ( isExistingWidget ) {
- widgetFormControl.expand();
widgetFormControl.updateWidget( {
- instance: widgetFormControl.setting(),
- complete: function( error ) {
- if ( error ) {
- throw error;
- }
- widgetFormControl.focus();
- }
+ instance: widgetFormControl.setting()
} );
- } else {
- widgetFormControl.focus();
}
} );
sidebar_widgets: api.Widgets.SidebarControl
});
+ // Refresh the nonce if login sends updated nonces over.
+ api.bind( 'nonce-refresh', function( nonces ) {
+ api.Widgets.data.nonce = nonces['update-widget'];
+ });
+
/**
* Init Customizer for widgets.
*/