Widget Customizer: Make the available widgets panel a Backbone view.
see #27690. Built from https://develop.svn.wordpress.org/trunk@27986 git-svn-id: http://core.svn.wordpress.org/trunk@27816 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
fabc65b787
commit
5f76bf3b0d
|
@ -15,7 +15,12 @@
|
|||
delete api.Widgets.data.l10n;
|
||||
|
||||
/**
|
||||
* Set up model
|
||||
* wp.customize.Widgets.WidgetModel
|
||||
*
|
||||
* A single widget model.
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
api.Widgets.WidgetModel = Backbone.Model.extend({
|
||||
id: null,
|
||||
|
@ -34,6 +39,14 @@
|
|||
height: null
|
||||
});
|
||||
|
||||
/**
|
||||
* wp.customize.Widgets.WidgetCollection
|
||||
*
|
||||
* Collection for widget models.
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
api.Widgets.WidgetCollection = Backbone.Collection.extend({
|
||||
model: api.Widgets.WidgetModel,
|
||||
|
||||
|
@ -92,6 +105,14 @@
|
|||
});
|
||||
api.Widgets.availableWidgets = new api.Widgets.WidgetCollection( api.Widgets.data.availableWidgets );
|
||||
|
||||
/**
|
||||
* wp.customize.Widgets.SidebarModel
|
||||
*
|
||||
* A single sidebar model.
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Model
|
||||
*/
|
||||
api.Widgets.SidebarModel = Backbone.Model.extend({
|
||||
after_title: null,
|
||||
after_widget: null,
|
||||
|
@ -104,11 +125,251 @@
|
|||
is_rendered: false
|
||||
});
|
||||
|
||||
/**
|
||||
* wp.customize.Widgets.SidebarCollection
|
||||
*
|
||||
* Collection for sidebar models.
|
||||
*
|
||||
* @constructor
|
||||
* @augments Backbone.Collection
|
||||
*/
|
||||
api.Widgets.SidebarCollection = Backbone.Collection.extend({
|
||||
model: api.Widgets.SidebarModel
|
||||
});
|
||||
api.Widgets.registeredSidebars = new api.Widgets.SidebarCollection( api.Widgets.data.registeredSidebars );
|
||||
|
||||
/**
|
||||
* wp.customize.Widgets.AvailableWidgetsPanelView
|
||||
*
|
||||
* View class for the available widgets panel.
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.Backbone.View
|
||||
* @augments Backbone.View
|
||||
*/
|
||||
api.Widgets.AvailableWidgetsPanelView = wp.Backbone.View.extend({
|
||||
|
||||
el: '#available-widgets',
|
||||
|
||||
events: {
|
||||
'input #widgets-search': 'search',
|
||||
'keyup #widgets-search': 'search',
|
||||
'change #widgets-search': 'search',
|
||||
'search #widgets-search': 'search',
|
||||
'focus .widget-tpl' : 'focus',
|
||||
'click .widget-tpl' : '_submit',
|
||||
'keypress .widget-tpl' : '_submit',
|
||||
'keydown' : 'keyboardAccessible'
|
||||
},
|
||||
|
||||
// Cache current selected widget
|
||||
selected: null,
|
||||
|
||||
// Cache sidebar control which has opened panel
|
||||
currentSidebarControl: null,
|
||||
$search: null,
|
||||
|
||||
initialize: function() {
|
||||
var self = this;
|
||||
|
||||
this.$search = $( '#widgets-search' );
|
||||
|
||||
_.bindAll( this, 'close' );
|
||||
|
||||
this.listenTo( this.collection, 'update', this.updateList );
|
||||
|
||||
this.updateList();
|
||||
|
||||
// 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 ) {
|
||||
var isAddNewBtn = $( e.target ).is( '.add-new-widget, .add-new-widget *' );
|
||||
if ( $( 'body' ).hasClass( 'adding-widget' ) && ! isAddNewBtn ) {
|
||||
self.close();
|
||||
}
|
||||
} );
|
||||
|
||||
// Close the panel if the URL in the preview changes
|
||||
api.Widgets.Previewer.bind( 'url', this.close );
|
||||
},
|
||||
|
||||
// Performs a search and handles selected widget
|
||||
search: function( event ) {
|
||||
var firstVisible;
|
||||
|
||||
this.collection.doSearch( event.target.value );
|
||||
|
||||
// Remove a widget from being selected if it is no longer visible
|
||||
if ( this.selected && ! this.selected.is( ':visible' ) ) {
|
||||
this.selected.removeClass( 'selected' );
|
||||
this.selected = null;
|
||||
}
|
||||
|
||||
// If a widget was selected but the filter value has been cleared out, clear selection
|
||||
if ( this.selected && ! event.target.value ) {
|
||||
this.selected.removeClass( 'selected' );
|
||||
this.selected = null;
|
||||
}
|
||||
|
||||
// If a filter has been entered and a widget hasn't been selected, select the first one shown
|
||||
if ( ! this.selected && event.target.value ) {
|
||||
firstVisible = this.$el.find( '> .widget-tpl:visible:first' );
|
||||
if ( firstVisible.length ) {
|
||||
this.select( firstVisible );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Changes visibilty of available widgets
|
||||
updateList: function() {
|
||||
// First hide all widgets...
|
||||
this.$el.find( '.widget-tpl' ).hide();
|
||||
|
||||
// ..and then show only available widgets which could be filtered
|
||||
this.collection.each( function( widget ) {
|
||||
var widgetTpl = $( '#widget-tpl-' + widget.id );
|
||||
widgetTpl.toggle( ! widget.get( 'is_disabled' ) );
|
||||
if ( widget.get( 'is_disabled' ) && widgetTpl.is( this.selected ) ) {
|
||||
this.selected = null;
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
// Hightlights a widget
|
||||
select: function( widgetTpl ) {
|
||||
this.selected = $( widgetTpl );
|
||||
this.selected.siblings( '.widget-tpl' ).removeClass( 'selected' );
|
||||
this.selected.addClass( 'selected' );
|
||||
},
|
||||
|
||||
// Hightlights a widget on focus
|
||||
focus: function( event ) {
|
||||
this.select( $( event.currentTarget ) );
|
||||
},
|
||||
|
||||
// Submit handler for keypress and click on widget
|
||||
_submit: function( event ) {
|
||||
// Only proceed with keypress if it is Enter or Spacebar
|
||||
if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.submit( $( event.currentTarget ) );
|
||||
},
|
||||
|
||||
// Adds a selected widget to the sidebar
|
||||
submit: function( widgetTpl ) {
|
||||
var widgetId, widget;
|
||||
|
||||
if ( ! widgetTpl ) {
|
||||
widgetTpl = this.selected;
|
||||
}
|
||||
|
||||
if ( ! widgetTpl || ! this.currentSidebarControl ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.select( widgetTpl );
|
||||
|
||||
widgetId = $( this.selected ).data( 'widget-id' );
|
||||
widget = this.collection.findWhere( { id: widgetId } );
|
||||
if ( ! widget ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentSidebarControl.addWidget( widget.get( 'id_base' ) );
|
||||
|
||||
this.close();
|
||||
},
|
||||
|
||||
// Opens the panel
|
||||
open: function( sidebarControl ) {
|
||||
this.currentSidebarControl = sidebarControl;
|
||||
|
||||
// Wide widget controls appear over the preview, and so they need to be collapsed when the panel opens
|
||||
_( this.currentSidebarControl.getWidgetFormControls() ).each( function( control ) {
|
||||
if ( control.params.is_wide ) {
|
||||
control.collapseForm();
|
||||
}
|
||||
} );
|
||||
|
||||
$( 'body' ).addClass( 'adding-widget' );
|
||||
|
||||
this.$el.find( '.selected' ).removeClass( 'selected' );
|
||||
|
||||
// Reset search
|
||||
this.collection.doSearch( '' );
|
||||
|
||||
this.$search.focus();
|
||||
},
|
||||
|
||||
// Closes the panel
|
||||
close: function( options ) {
|
||||
options = options || {};
|
||||
|
||||
if ( options.returnFocus && this.currentSidebarControl ) {
|
||||
this.currentSidebarControl.container.find( '.add-new-widget' ).focus();
|
||||
}
|
||||
|
||||
this.currentSidebarControl = null;
|
||||
this.selected = null;
|
||||
|
||||
$( 'body' ).removeClass( 'adding-widget' );
|
||||
|
||||
this.$search.val( '' );
|
||||
},
|
||||
|
||||
// Add keyboard accessiblity to the panel
|
||||
keyboardAccessible: function( event ) {
|
||||
var isEnter = ( event.which === 13 ),
|
||||
isEsc = ( event.which === 27 ),
|
||||
isDown = ( event.which === 40 ),
|
||||
isUp = ( event.which === 38 ),
|
||||
selected = null,
|
||||
firstVisible = this.$el.find( '> .widget-tpl:visible:first' ),
|
||||
lastVisible = this.$el.find( '> .widget-tpl:visible:last' ),
|
||||
isSearchFocused = $( event.target ).is( this.$search );
|
||||
|
||||
if ( isDown || isUp ) {
|
||||
if ( isDown ) {
|
||||
if ( isSearchFocused ) {
|
||||
selected = firstVisible;
|
||||
} else if ( this.selected && this.selected.nextAll( '.widget-tpl:visible' ).length !== 0 ) {
|
||||
selected = this.selected.nextAll( '.widget-tpl:visible:first' );
|
||||
}
|
||||
} else if ( isUp ) {
|
||||
if ( isSearchFocused ) {
|
||||
selected = lastVisible;
|
||||
} else if ( this.selected && this.selected.prevAll( '.widget-tpl:visible' ).length !== 0 ) {
|
||||
selected = this.selected.prevAll( '.widget-tpl:visible:first' );
|
||||
}
|
||||
}
|
||||
|
||||
this.select( selected );
|
||||
|
||||
if ( selected ) {
|
||||
selected.focus();
|
||||
} else {
|
||||
this.$search.focus();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If enter pressed but nothing entered, don't do anything
|
||||
if ( isEnter && ! this.$search.val() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isEnter ) {
|
||||
this.submit();
|
||||
} else if ( isEsc ) {
|
||||
this.close( { returnFocus: true } );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Handlers for the widget-synced event, organized by widget ID base.
|
||||
* Other widgets may provide their own update handlers by adding
|
||||
|
@ -121,7 +382,7 @@
|
|||
* @param {jQuery} widget
|
||||
* @param {String} newForm
|
||||
*/
|
||||
rss: function ( e, widget, newForm ) {
|
||||
rss: function( e, widget, newForm ) {
|
||||
var oldWidgetError = widget.find( '.widget-error:first' ),
|
||||
newWidgetError = $( '<div>' + newForm + '</div>' ).find( '.widget-error:first' );
|
||||
|
||||
|
@ -136,8 +397,13 @@
|
|||
};
|
||||
|
||||
/**
|
||||
* Widget Form control
|
||||
* wp.customize.Widgets.WidgetControl
|
||||
*
|
||||
* Customizer control for widgets.
|
||||
* Note that 'widget_form' must match the WP_Widget_Form_Customize_Control::$type
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.customize.Control
|
||||
*/
|
||||
api.Widgets.WidgetControl = api.Control.extend({
|
||||
/**
|
||||
|
@ -246,7 +512,7 @@
|
|||
} );
|
||||
|
||||
// Reposition whenever a sidebar's widgets are changed
|
||||
api.each( function ( setting ) {
|
||||
api.each( function( setting ) {
|
||||
if ( 0 === setting.id.indexOf( 'sidebars_widgets[' ) ) {
|
||||
setting.bind( function() {
|
||||
if ( control.container.hasClass( 'expanded' ) ) {
|
||||
|
@ -264,7 +530,7 @@
|
|||
_setupControlToggle: function() {
|
||||
var control = this, close_btn;
|
||||
|
||||
control.container.find( '.widget-top' ).on( 'click', function ( e ) {
|
||||
control.container.find( '.widget-top' ).on( 'click', function( e ) {
|
||||
e.preventDefault();
|
||||
var sidebar_widgets_control = control.getSidebarWidgetsControl();
|
||||
if ( sidebar_widgets_control.is_reordering ) {
|
||||
|
@ -275,7 +541,7 @@
|
|||
|
||||
close_btn = control.container.find( '.widget-control-close' );
|
||||
// @todo Hitting Enter on this link does nothing; will be resolved in core with <http://core.trac.wordpress.org/ticket/26633>
|
||||
close_btn.on( 'click', function ( e ) {
|
||||
close_btn.on( 'click', function( e ) {
|
||||
e.preventDefault();
|
||||
control.collapseForm();
|
||||
control.container.find( '.widget-top .widget-action:first' ).focus(); // keyboard accessibility
|
||||
|
@ -317,7 +583,7 @@
|
|||
*
|
||||
* @param {jQuery} li
|
||||
*/
|
||||
select_sidebar_item = function ( li ) {
|
||||
select_sidebar_item = function( li ) {
|
||||
li.siblings( '.selected' ).removeClass( 'selected' );
|
||||
li.addClass( 'selected' );
|
||||
var is_self_sidebar = ( li.data( 'id' ) === control.params.sidebar_id );
|
||||
|
@ -363,7 +629,7 @@
|
|||
* Handle clicks for up/down/move on the reorder nav
|
||||
*/
|
||||
reorder_nav = control.container.find( '.widget-reorder-nav' );
|
||||
reorder_nav.find( '.move-widget, .move-widget-down, .move-widget-up' ).on( 'click keypress', function ( event ) {
|
||||
reorder_nav.find( '.move-widget, .move-widget-down, .move-widget-up' ).on( 'click keypress', function( event ) {
|
||||
if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
|
||||
return;
|
||||
}
|
||||
|
@ -393,7 +659,7 @@
|
|||
/**
|
||||
* Handle selecting a sidebar to move to
|
||||
*/
|
||||
control.container.find( '.widget-area-select' ).on( 'click keypress', 'li', function ( e ) {
|
||||
control.container.find( '.widget-area-select' ).on( 'click keypress', 'li', function( e ) {
|
||||
if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
|
||||
return;
|
||||
}
|
||||
|
@ -472,7 +738,7 @@
|
|||
save_btn.val( l10n.saveBtnLabel );
|
||||
save_btn.attr( 'title', l10n.saveBtnTooltip );
|
||||
save_btn.removeClass( 'button-primary' ).addClass( 'button-secondary' );
|
||||
save_btn.on( 'click', function ( e ) {
|
||||
save_btn.on( 'click', function( e ) {
|
||||
e.preventDefault();
|
||||
control.updateWidget( { disable_form: true } );
|
||||
} );
|
||||
|
@ -491,7 +757,7 @@
|
|||
} );
|
||||
|
||||
// Handle widgets that support live previews
|
||||
widget_content.on( 'change input propertychange', ':input', function ( e ) {
|
||||
widget_content.on( 'change input propertychange', ':input', function( e ) {
|
||||
if ( control.live_update_mode ) {
|
||||
if ( e.type === 'change' ) {
|
||||
control.updateWidget();
|
||||
|
@ -505,21 +771,21 @@
|
|||
control.setting.previewer.channel.bind( 'synced', function() {
|
||||
control.container.removeClass( 'previewer-loading' );
|
||||
} );
|
||||
api.Widgets.Previewer.bind( 'widget-updated', function ( updated_widget_id ) {
|
||||
api.Widgets.Previewer.bind( 'widget-updated', function( updated_widget_id ) {
|
||||
if ( updated_widget_id === control.params.widget_id ) {
|
||||
control.container.removeClass( 'previewer-loading' );
|
||||
}
|
||||
} );
|
||||
|
||||
// Update widget control to indicate whether it is currently rendered (cf. Widget Visibility)
|
||||
api.Widgets.Previewer.bind( 'rendered-widgets', function ( rendered_widgets ) {
|
||||
api.Widgets.Previewer.bind( 'rendered-widgets', function( rendered_widgets ) {
|
||||
var is_rendered = !! rendered_widgets[control.params.widget_id];
|
||||
control.container.toggleClass( 'widget-rendered', is_rendered );
|
||||
} );
|
||||
|
||||
form_update_event_handler = api.Widgets.formSyncHandlers[ control.params.widget_id_base ];
|
||||
if ( form_update_event_handler ) {
|
||||
$( document ).on( 'widget-synced', function ( e, widget_el ) {
|
||||
$( document ).on( 'widget-synced', function( e, widget_el ) {
|
||||
if ( widget_root.is( widget_el ) ) {
|
||||
form_update_event_handler.apply( document, arguments );
|
||||
}
|
||||
|
@ -538,7 +804,7 @@
|
|||
// Configure remove button
|
||||
remove_btn = control.container.find( 'a.widget-control-remove' );
|
||||
// @todo Hitting Enter on this link does nothing; will be resolved in core with <http://core.trac.wordpress.org/ticket/26633>
|
||||
remove_btn.on( 'click', function ( e ) {
|
||||
remove_btn.on( 'click', function( e ) {
|
||||
e.preventDefault();
|
||||
|
||||
// Find an adjacent element to add focus to when this widget goes away
|
||||
|
@ -592,7 +858,7 @@
|
|||
* @returns {jQuery} inputs
|
||||
* @private
|
||||
*/
|
||||
_getInputs: function ( container ) {
|
||||
_getInputs: function( container ) {
|
||||
return $( container ).find( ':input[name]' );
|
||||
},
|
||||
|
||||
|
@ -604,8 +870,8 @@
|
|||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
_getInputsSignature: function ( inputs ) {
|
||||
var inputs_signatures = _( inputs ).map( function ( input ) {
|
||||
_getInputsSignature: function( inputs ) {
|
||||
var inputs_signatures = _( inputs ).map( function( input ) {
|
||||
input = $( input );
|
||||
var signature_parts;
|
||||
if ( input.is( ':checkbox, :radio' ) ) {
|
||||
|
@ -625,7 +891,7 @@
|
|||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
_getInputStatePropertyName: function ( input ) {
|
||||
_getInputStatePropertyName: function( input ) {
|
||||
input = $( input );
|
||||
if ( input.is( ':radio, :checkbox' ) ) {
|
||||
return 'checked';
|
||||
|
@ -661,7 +927,7 @@
|
|||
* @param {Function|null} [args.complete=null] Function which is called when the request finishes. Context is bound to the control. First argument is any error. Following arguments are for success.
|
||||
* @param {Boolean} [args.ignore_active_element=false] Whether or not updating a field will be deferred if focus is still on the element.
|
||||
*/
|
||||
updateWidget: function ( args ) {
|
||||
updateWidget: function( args ) {
|
||||
var control = this,
|
||||
instance_override,
|
||||
complete_callback,
|
||||
|
@ -726,7 +992,7 @@
|
|||
}
|
||||
data += '&' + widget_content.find( '~ :input' ).serialize();
|
||||
|
||||
jqxhr = $.post( wp.ajax.settings.url, data, function ( r ) {
|
||||
jqxhr = $.post( wp.ajax.settings.url, data, function( r ) {
|
||||
var message,
|
||||
sanitized_form,
|
||||
sanitized_inputs,
|
||||
|
@ -763,7 +1029,7 @@
|
|||
|
||||
// Sync sanitized field states to existing fields if they are aligned
|
||||
if ( has_same_inputs_in_response && control.live_update_mode ) {
|
||||
inputs.each( function ( i ) {
|
||||
inputs.each( function( i ) {
|
||||
var input = $( this ),
|
||||
sanitized_input = $( sanitized_inputs[i] ),
|
||||
property = control._getInputStatePropertyName( this ),
|
||||
|
@ -827,7 +1093,7 @@
|
|||
}
|
||||
}
|
||||
} );
|
||||
jqxhr.fail( function ( jqXHR, textStatus ) {
|
||||
jqxhr.fail( function( jqXHR, textStatus ) {
|
||||
if ( complete_callback ) {
|
||||
complete_callback.call( control, textStatus );
|
||||
}
|
||||
|
@ -872,7 +1138,7 @@
|
|||
*
|
||||
* @param {boolean|undefined} [do_expand] If not supplied, will be inverse of current visibility
|
||||
*/
|
||||
toggleForm: function ( do_expand ) {
|
||||
toggleForm: function( do_expand ) {
|
||||
var control = this, widget, inside, complete;
|
||||
|
||||
widget = control.container.find( 'div.widget:first' );
|
||||
|
@ -888,7 +1154,7 @@
|
|||
|
||||
if ( do_expand ) {
|
||||
// Close all other widget controls before expanding this one
|
||||
api.control.each( function ( other_control ) {
|
||||
api.control.each( function( other_control ) {
|
||||
if ( control.params.type === other_control.params.type && control !== other_control ) {
|
||||
other_control.collapseForm();
|
||||
}
|
||||
|
@ -974,7 +1240,7 @@
|
|||
*
|
||||
* @param {Number} offset 1|-1
|
||||
*/
|
||||
_moveWidgetByOne: function ( offset ) {
|
||||
_moveWidgetByOne: function( offset ) {
|
||||
var control = this,
|
||||
i,
|
||||
sidebar_widgets_setting,
|
||||
|
@ -997,7 +1263,7 @@
|
|||
*
|
||||
* @param {Boolean} [toggle]
|
||||
*/
|
||||
toggleWidgetMoveArea: function ( toggle ) {
|
||||
toggleWidgetMoveArea: function( toggle ) {
|
||||
var control = this, move_widget_area;
|
||||
move_widget_area = control.container.find( '.move-widget-area' );
|
||||
if ( typeof toggle === 'undefined' ) {
|
||||
|
@ -1043,8 +1309,13 @@
|
|||
} );
|
||||
|
||||
/**
|
||||
* Sidebar Widgets control
|
||||
* wp.customize.Widgets.SidebarControl
|
||||
*
|
||||
* Customizer control for widgets.
|
||||
* Note that 'sidebar_widgets' must match the WP_Widget_Area_Customize_Control::$type
|
||||
*
|
||||
* @constructor
|
||||
* @augments wp.customize.Control
|
||||
*/
|
||||
api.Widgets.SidebarControl = api.Control.extend({
|
||||
/**
|
||||
|
@ -1074,12 +1345,12 @@
|
|||
removed_widget_ids = _( old_widget_ids ).difference( new_widget_ids );
|
||||
|
||||
// Filter out any persistent widget_ids for widgets which have been deactivated
|
||||
new_widget_ids = _( new_widget_ids ).filter( function ( new_widget_id ) {
|
||||
new_widget_ids = _( new_widget_ids ).filter( function( new_widget_id ) {
|
||||
var parsed_widget_id = parse_widget_id( new_widget_id );
|
||||
return !! api.Widgets.availableWidgets.findWhere( { id_base: parsed_widget_id.id_base } );
|
||||
} );
|
||||
|
||||
widget_form_controls = _( new_widget_ids ).map( function ( widget_id ) {
|
||||
widget_form_controls = _( new_widget_ids ).map( function( widget_id ) {
|
||||
var widget_form_control = api.Widgets.getWidgetFormControlForWidget( widget_id );
|
||||
if ( ! widget_form_control ) {
|
||||
widget_form_control = control.addWidget( widget_id );
|
||||
|
@ -1088,7 +1359,7 @@
|
|||
} );
|
||||
|
||||
// Sort widget controls to their new positions
|
||||
widget_form_controls.sort( function ( a, b ) {
|
||||
widget_form_controls.sort( function( a, b ) {
|
||||
var a_index = _.indexOf( new_widget_ids, a.params.widget_id ),
|
||||
b_index = _.indexOf( new_widget_ids, b.params.widget_id );
|
||||
if ( a_index === b_index ) {
|
||||
|
@ -1109,12 +1380,12 @@
|
|||
control._applyCardinalOrderClassNames();
|
||||
|
||||
// If the widget was dragged into the sidebar, make sure the sidebar_id param is updated
|
||||
_( widget_form_controls ).each( function ( widget_form_control ) {
|
||||
_( widget_form_controls ).each( function( widget_form_control ) {
|
||||
widget_form_control.params.sidebar_id = control.params.sidebar_id;
|
||||
} );
|
||||
|
||||
// Cleanup after widget removal
|
||||
_( removed_widget_ids ).each( function ( removed_widget_id ) {
|
||||
_( removed_widget_ids ).each( function( removed_widget_id ) {
|
||||
|
||||
// Using setTimeout so that when moving a widget to another sidebar, the other sidebars_widgets settings get a chance to update
|
||||
setTimeout( function() {
|
||||
|
@ -1126,7 +1397,7 @@
|
|||
widget;
|
||||
|
||||
// Check if the widget is in another sidebar
|
||||
api.each( function ( other_setting ) {
|
||||
api.each( function( other_setting ) {
|
||||
if ( other_setting.id === control.setting.id || 0 !== other_setting.id.indexOf( 'sidebars_widgets[' ) || other_setting.id === 'sidebars_widgets[wp_inactive_widgets]' ) {
|
||||
return;
|
||||
}
|
||||
|
@ -1178,13 +1449,13 @@
|
|||
} );
|
||||
|
||||
// Update the model with whether or not the sidebar is rendered
|
||||
api.Widgets.Previewer.bind( 'rendered-sidebars', function ( rendered_sidebars ) {
|
||||
api.Widgets.Previewer.bind( 'rendered-sidebars', function( rendered_sidebars ) {
|
||||
var is_rendered = !! rendered_sidebars[control.params.sidebar_id];
|
||||
registered_sidebar.set( 'is_rendered', is_rendered );
|
||||
} );
|
||||
|
||||
// Show the sidebar section when it becomes visible
|
||||
registered_sidebar.on( 'change:is_rendered', function ( ) {
|
||||
registered_sidebar.on( 'change:is_rendered', function( ) {
|
||||
var section_selector = '#accordion-section-sidebar-widgets-' + this.get( 'id' ), section;
|
||||
section = $( section_selector );
|
||||
if ( this.get( 'is_rendered' ) ) {
|
||||
|
@ -1219,7 +1490,7 @@
|
|||
connectWith: '.accordion-section-content:has(.customize-control-sidebar_widgets)',
|
||||
update: function() {
|
||||
var widget_container_ids = control.section_content.sortable( 'toArray' ), widget_ids;
|
||||
widget_ids = $.map( widget_container_ids, function ( widget_container_id ) {
|
||||
widget_ids = $.map( widget_container_ids, function( widget_container_id ) {
|
||||
return $( '#' + widget_container_id ).find( ':input[name=widget-id]' ).val();
|
||||
} );
|
||||
control.setting( widget_ids );
|
||||
|
@ -1306,7 +1577,7 @@
|
|||
*
|
||||
* @param {Boolean} toggle to enable/disable reordering
|
||||
*/
|
||||
toggleReordering: function ( toggle ) {
|
||||
toggleReordering: function( toggle ) {
|
||||
var control = this;
|
||||
toggle = Boolean( toggle );
|
||||
if ( toggle === control.section_content.hasClass( 'reordering' ) ) {
|
||||
|
@ -1317,7 +1588,7 @@
|
|||
control.section_content.toggleClass( 'reordering', toggle );
|
||||
|
||||
if ( toggle ) {
|
||||
_( control.getWidgetFormControls() ).each( function ( form_control ) {
|
||||
_( control.getWidgetFormControls() ).each( function( form_control ) {
|
||||
form_control.collapseForm();
|
||||
} );
|
||||
}
|
||||
|
@ -1329,7 +1600,7 @@
|
|||
getWidgetFormControls: function() {
|
||||
var control = this, form_controls;
|
||||
|
||||
form_controls = _( control.setting() ).map( function ( widget_id ) {
|
||||
form_controls = _( control.setting() ).map( function( widget_id ) {
|
||||
var setting_id = widget_id_to_setting_id( widget_id ),
|
||||
form_control = api.control( setting_id );
|
||||
|
||||
|
@ -1345,7 +1616,7 @@
|
|||
* @param {string} widget_id or an id_base for adding a previously non-existing widget
|
||||
* @returns {object} widget_form control instance
|
||||
*/
|
||||
addWidget: function ( widget_id ) {
|
||||
addWidget: function( widget_id ) {
|
||||
var control = this,
|
||||
control_html,
|
||||
widget_el,
|
||||
|
@ -1377,7 +1648,7 @@
|
|||
|
||||
control_html = $( '#widget-tpl-' + widget.get( 'id' ) ).html();
|
||||
if ( widget.get( 'is_multi' ) ) {
|
||||
control_html = control_html.replace( /<[^<>]+>/g, function ( m ) {
|
||||
control_html = control_html.replace( /<[^<>]+>/g, function( m ) {
|
||||
return m.replace( /__i__|%i%/g, widget_number );
|
||||
} );
|
||||
} else {
|
||||
|
@ -1435,7 +1706,7 @@
|
|||
api.control.add( setting_id, widget_form_control );
|
||||
|
||||
// Make sure widget is removed from the other sidebars
|
||||
api.each( function ( other_setting ) {
|
||||
api.each( function( other_setting ) {
|
||||
if ( other_setting.id === control.setting.id ) {
|
||||
return;
|
||||
}
|
||||
|
@ -1462,7 +1733,7 @@
|
|||
widget_form_control.expandForm();
|
||||
widget_form_control.updateWidget( {
|
||||
instance: widget_form_control.setting(),
|
||||
complete: function ( error ) {
|
||||
complete: function( error ) {
|
||||
if ( error ) {
|
||||
throw error;
|
||||
}
|
||||
|
@ -1488,7 +1759,9 @@
|
|||
|
||||
api.bind( 'ready', function() {
|
||||
// Set up the widgets panel
|
||||
api.Widgets.availableWidgetsPanel.setup();
|
||||
api.Widgets.availableWidgetsPanel = new api.Widgets.AvailableWidgetsPanelView({
|
||||
collection: api.Widgets.availableWidgets
|
||||
});
|
||||
|
||||
// Highlight widget control
|
||||
api.Widgets.Previewer.bind( 'highlight-widget-control', api.Widgets.highlightWidgetFormControl );
|
||||
|
@ -1540,10 +1813,10 @@
|
|||
* @param {string} widget_id
|
||||
* @return {object|null}
|
||||
*/
|
||||
api.Widgets.getSidebarWidgetControlContainingWidget = function ( widget_id ) {
|
||||
api.Widgets.getSidebarWidgetControlContainingWidget = function( widget_id ) {
|
||||
var found_control = null;
|
||||
// @todo this can use widget_id_to_setting_id(), then pass into wp.customize.control( x ).getSidebarWidgetsControl()
|
||||
api.control.each( function ( control ) {
|
||||
api.control.each( function( control ) {
|
||||
if ( control.params.type === 'sidebar_widgets' && -1 !== _.indexOf( control.setting(), widget_id ) ) {
|
||||
found_control = control;
|
||||
}
|
||||
|
@ -1557,10 +1830,10 @@
|
|||
* @param {string} widget_id
|
||||
* @return {object|null}
|
||||
*/
|
||||
api.Widgets.getWidgetFormControlForWidget = function ( widget_id ) {
|
||||
api.Widgets.getWidgetFormControlForWidget = function( widget_id ) {
|
||||
var found_control = null;
|
||||
// @todo We can just use widget_id_to_setting_id() here
|
||||
api.control.each( function ( control ) {
|
||||
api.control.each( function( control ) {
|
||||
if ( control.params.type === 'widget_form' && control.params.widget_id === widget_id ) {
|
||||
found_control = control;
|
||||
}
|
||||
|
@ -1569,214 +1842,6 @@
|
|||
return found_control;
|
||||
};
|
||||
|
||||
/**
|
||||
* Available Widgets Panel
|
||||
*/
|
||||
api.Widgets.availableWidgetsPanel = {
|
||||
active_sidebar_widgets_control: null,
|
||||
selected_widget_tpl: null,
|
||||
container: null,
|
||||
filter_input: null,
|
||||
|
||||
/**
|
||||
* Set up event listeners
|
||||
*/
|
||||
setup: function() {
|
||||
var panel = this;
|
||||
|
||||
panel.container = $( '#available-widgets' );
|
||||
panel.filter_input = $( '#available-widgets-filter' ).find( 'input' );
|
||||
|
||||
api.Widgets.availableWidgets.on( 'change update', panel.update_available_widgets_list );
|
||||
panel.update_available_widgets_list();
|
||||
|
||||
// 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 ) {
|
||||
var is_add_new_widget_btn = $( e.target ).is( '.add-new-widget, .add-new-widget *' );
|
||||
if ( $( 'body' ).hasClass( 'adding-widget' ) && ! is_add_new_widget_btn ) {
|
||||
panel.close();
|
||||
}
|
||||
} );
|
||||
|
||||
// Close the panel if the URL in the preview changes
|
||||
api.Widgets.Previewer.bind( 'url', function() {
|
||||
panel.close();
|
||||
} );
|
||||
|
||||
// Submit a selection when clicked or keypressed
|
||||
panel.container.find( '.widget-tpl' ).on( 'click keypress', function( event ) {
|
||||
|
||||
// Only proceed with keypress if it is Enter or Spacebar
|
||||
if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
panel.submit( this );
|
||||
} );
|
||||
|
||||
panel.filter_input.on( 'input keyup change', function( event ) {
|
||||
var first_visible_widget;
|
||||
|
||||
api.Widgets.availableWidgets.doSearch( event.target.value );
|
||||
|
||||
// Remove a widget from being selected if it is no longer visible
|
||||
if ( panel.selected_widget_tpl && ! panel.selected_widget_tpl.is( ':visible' ) ) {
|
||||
panel.selected_widget_tpl.removeClass( 'selected' );
|
||||
panel.selected_widget_tpl = null;
|
||||
}
|
||||
|
||||
// If a widget was selected but the filter value has been cleared out, clear selection
|
||||
if ( panel.selected_widget_tpl && ! event.target.value ) {
|
||||
panel.selected_widget_tpl.removeClass( 'selected' );
|
||||
panel.selected_widget_tpl = null;
|
||||
}
|
||||
|
||||
// If a filter has been entered and a widget hasn't been selected, select the first one shown
|
||||
if ( ! panel.selected_widget_tpl && event.target.value ) {
|
||||
first_visible_widget = panel.container.find( '> .widget-tpl:visible:first' );
|
||||
if ( first_visible_widget.length ) {
|
||||
panel.select( first_visible_widget );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// Select a widget when it is focused on
|
||||
panel.container.find( ' > .widget-tpl' ).on( 'focus', function() {
|
||||
panel.select( this );
|
||||
} );
|
||||
|
||||
panel.container.on( 'keydown', function ( event ) {
|
||||
var is_enter = ( event.which === 13 ),
|
||||
is_esc = ( event.which === 27 ),
|
||||
is_down = ( event.which === 40 ),
|
||||
is_up = ( event.which === 38 ),
|
||||
selected_widget_tpl = null,
|
||||
first_visible_widget = panel.container.find( '> .widget-tpl:visible:first' ),
|
||||
last_visible_widget = panel.container.find( '> .widget-tpl:visible:last' ),
|
||||
is_input_focused = $( event.target ).is( panel.filter_input );
|
||||
|
||||
if ( is_down || is_up ) {
|
||||
if ( is_down ) {
|
||||
if ( is_input_focused ) {
|
||||
selected_widget_tpl = first_visible_widget;
|
||||
} else if ( panel.selected_widget_tpl && panel.selected_widget_tpl.nextAll( '.widget-tpl:visible' ).length !== 0 ) {
|
||||
selected_widget_tpl = panel.selected_widget_tpl.nextAll( '.widget-tpl:visible:first' );
|
||||
}
|
||||
} else if ( is_up ) {
|
||||
if ( is_input_focused ) {
|
||||
selected_widget_tpl = last_visible_widget;
|
||||
} else if ( panel.selected_widget_tpl && panel.selected_widget_tpl.prevAll( '.widget-tpl:visible' ).length !== 0 ) {
|
||||
selected_widget_tpl = panel.selected_widget_tpl.prevAll( '.widget-tpl:visible:first' );
|
||||
}
|
||||
}
|
||||
panel.select( selected_widget_tpl );
|
||||
if ( selected_widget_tpl ) {
|
||||
selected_widget_tpl.focus();
|
||||
} else {
|
||||
panel.filter_input.focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If enter pressed but nothing entered, don't do anything
|
||||
if ( is_enter && ! panel.filter_input.val() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( is_enter ) {
|
||||
panel.submit();
|
||||
} else if ( is_esc ) {
|
||||
panel.close( { return_focus: true } );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates widgets list.
|
||||
*/
|
||||
update_available_widgets_list: function() {
|
||||
var panel = api.Widgets.availableWidgetsPanel;
|
||||
|
||||
// First hide all widgets...
|
||||
panel.container.find( '.widget-tpl' ).hide();
|
||||
|
||||
// ..and then show only available widgets which could be filtered
|
||||
api.Widgets.availableWidgets.each( function ( widget ) {
|
||||
var widget_tpl = $( '#widget-tpl-' + widget.id );
|
||||
widget_tpl.toggle( ! widget.get( 'is_disabled' ) );
|
||||
if ( widget.get( 'is_disabled' ) && widget_tpl.is( panel.selected_widget_tpl ) ) {
|
||||
panel.selected_widget_tpl = null;
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* @param widget_tpl
|
||||
*/
|
||||
select: function ( widget_tpl ) {
|
||||
var panel = this;
|
||||
panel.selected_widget_tpl = $( widget_tpl );
|
||||
panel.selected_widget_tpl.siblings( '.widget-tpl' ).removeClass( 'selected' );
|
||||
panel.selected_widget_tpl.addClass( 'selected' );
|
||||
},
|
||||
|
||||
submit: function ( widget_tpl ) {
|
||||
var panel = this, widget_id, widget;
|
||||
if ( ! widget_tpl ) {
|
||||
widget_tpl = panel.selected_widget_tpl;
|
||||
}
|
||||
if ( ! widget_tpl || ! panel.active_sidebar_widgets_control ) {
|
||||
return;
|
||||
}
|
||||
panel.select( widget_tpl );
|
||||
|
||||
widget_id = $( panel.selected_widget_tpl ).data( 'widget-id' );
|
||||
widget = api.Widgets.availableWidgets.findWhere( {id: widget_id} );
|
||||
if ( ! widget ) {
|
||||
throw new Error( 'Widget unexpectedly not found.' );
|
||||
}
|
||||
panel.active_sidebar_widgets_control.addWidget( widget.get( 'id_base' ) );
|
||||
panel.close();
|
||||
},
|
||||
|
||||
/**
|
||||
* @param sidebars_widgets_control
|
||||
*/
|
||||
open: function ( sidebars_widgets_control ) {
|
||||
var panel = this;
|
||||
panel.active_sidebar_widgets_control = sidebars_widgets_control;
|
||||
|
||||
// Wide widget controls appear over the preview, and so they need to be collapsed when the panel opens
|
||||
_( sidebars_widgets_control.getWidgetFormControls() ).each( function ( control ) {
|
||||
if ( control.params.is_wide ) {
|
||||
control.collapseForm();
|
||||
}
|
||||
} );
|
||||
|
||||
$( 'body' ).addClass( 'adding-widget' );
|
||||
panel.container.find( '.widget-tpl' ).removeClass( 'selected' );
|
||||
api.Widgets.availableWidgets.doSearch( '' );
|
||||
panel.filter_input.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the panel
|
||||
*/
|
||||
close: function ( options ) {
|
||||
var panel = this;
|
||||
options = options || {};
|
||||
if ( options.return_focus && panel.active_sidebar_widgets_control ) {
|
||||
panel.active_sidebar_widgets_control.container.find( '.add-new-widget' ).focus();
|
||||
}
|
||||
panel.active_sidebar_widgets_control = null;
|
||||
panel.selected_widget_tpl = null;
|
||||
$( 'body' ).removeClass( 'adding-widget' );
|
||||
panel.filter_input.val( '' );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} widget_id
|
||||
* @returns {Object}
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue