-(function( wp, $ ){
+/* global _wpWidgetCustomizerPreviewSettings */
+wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( $, _, wp, api ) {
- if ( ! wp || ! wp.customize ) { return; }
+ var self;
- var api = wp.customize,
- OldPreview;
+ self = {
+ renderedSidebars: {},
+ renderedWidgets: {},
+ registeredSidebars: [],
+ registeredWidgets: {},
+ widgetSelectors: [],
+ preview: null,
+ l10n: {
+ widgetTooltip: ''
+ },
+ selectiveRefreshableWidgets: {}
+ };
/**
- * wp.customize.WidgetCustomizerPreview
+ * Init widgets preview.
*
+ * @since 4.5.0
*/
- api.WidgetCustomizerPreview = {
- renderedSidebars: {}, // @todo Make rendered a property of the Backbone model
- renderedWidgets: {}, // @todo Make rendered a property of the Backbone model
- registeredSidebars: [], // @todo Make a Backbone collection
- registeredWidgets: {}, // @todo Make array, Backbone collection
- widgetSelectors: [],
- preview: null,
- l10n: {},
+ self.init = function() {
+ var self = this;
+
+ self.preview = api.preview;
+ if ( ! _.isEmpty( self.selectiveRefreshableWidgets ) ) {
+ self.addPartials();
+ }
+
+ self.buildWidgetSelectors();
+ self.highlightControls();
+
+ self.preview.bind( 'highlight-widget', self.highlightWidget );
+
+ api.preview.bind( 'active', function() {
+ self.highlightControls();
+ } );
+ };
+
+ /**
+ * Partial representing a widget instance.
+ *
+ * @class
+ * @augments wp.customize.selectiveRefresh.Partial
+ * @since 4.5.0
+ */
+ self.WidgetPartial = api.selectiveRefresh.Partial.extend({
+
+ /**
+ * Constructor.
+ *
+ * @since 4.5.0
+ * @param {string} id - Partial ID.
+ * @param {Object} options
+ * @param {Object} options.params
+ */
+ initialize: function( id, options ) {
+ var partial = this, matches;
+ matches = id.match( /^widget\[(.+)]$/ );
+ if ( ! matches ) {
+ throw new Error( 'Illegal id for widget partial.' );
+ }
- init: function () {
- var self = this;
- this.buildWidgetSelectors();
- this.highlightControls();
+ partial.widgetId = matches[1];
+ partial.widgetIdParts = self.parseWidgetId( partial.widgetId );
+ options = options || {};
+ options.params = _.extend(
+ {
+ settings: [ self.getWidgetSettingId( partial.widgetId ) ],
+ containerInclusive: true
+ },
+ options.params || {}
+ );
- this.preview.bind( 'highlight-widget', self.highlightWidget );
+ api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
},
/**
- * Calculate the selector for the sidebar's widgets based on the registered sidebar's info
+ * Refresh widget partial.
+ *
+ * @returns {Promise}
*/
- buildWidgetSelectors: function () {
- var self = this;
-
- $.each( this.registeredSidebars, function ( i, sidebar ) {
- var widgetTpl = [
- sidebar.before_widget.replace('%1$s', '').replace('%2$s', ''),
- sidebar.before_title,
- sidebar.after_title,
- sidebar.after_widget
- ].join(''),
- emptyWidget,
- widgetSelector,
- widgetClasses;
-
- emptyWidget = $(widgetTpl);
- widgetSelector = emptyWidget.prop('tagName');
- widgetClasses = emptyWidget.prop('className');
-
- // Prevent a rare case when before_widget, before_title, after_title and after_widget is empty.
- if ( ! widgetClasses ) {
- return;
- }
+ refresh: function() {
+ var partial = this, refreshDeferred;
+ if ( ! self.selectiveRefreshableWidgets[ partial.widgetIdParts.idBase ] ) {
+ refreshDeferred = $.Deferred();
+ refreshDeferred.reject();
+ partial.fallback();
+ return refreshDeferred.promise();
+ } else {
+ return api.selectiveRefresh.Partial.prototype.refresh.call( partial );
+ }
+ },
+
+ /**
+ * Send widget-updated message to parent so spinner will get removed from widget control.
+ *
+ * @inheritdoc
+ * @param {wp.customize.selectiveRefresh.Placement} placement
+ */
+ renderContent: function( placement ) {
+ var partial = this;
+ if ( api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement ) ) {
+ api.preview.send( 'widget-updated', partial.widgetId );
+ api.selectiveRefresh.trigger( 'widget-updated', partial );
+ }
+ }
+ });
- widgetClasses = widgetClasses.replace(/^\s+|\s+$/g, '');
+ /**
+ * Partial representing a widget area.
+ *
+ * @class
+ * @augments wp.customize.selectiveRefresh.Partial
+ * @since 4.5.0
+ */
+ self.SidebarPartial = api.selectiveRefresh.Partial.extend({
+
+ /**
+ * Constructor.
+ *
+ * @since 4.5.0
+ * @param {string} id - Partial ID.
+ * @param {Object} options
+ * @param {Object} options.params
+ */
+ initialize: function( id, options ) {
+ var partial = this, matches;
+ matches = id.match( /^sidebar\[(.+)]$/ );
+ if ( ! matches ) {
+ throw new Error( 'Illegal id for sidebar partial.' );
+ }
+ partial.sidebarId = matches[1];
+
+ options = options || {};
+ options.params = _.extend(
+ {
+ settings: [ 'sidebars_widgets[' + partial.sidebarId + ']' ]
+ },
+ options.params || {}
+ );
- if ( widgetClasses ) {
- widgetSelector += '.' + widgetClasses.split(/\s+/).join('.');
+ api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
+
+ if ( ! partial.params.sidebarArgs ) {
+ throw new Error( 'The sidebarArgs param was not provided.' );
+ }
+ if ( partial.params.settings.length > 1 ) {
+ throw new Error( 'Expected SidebarPartial to only have one associated setting' );
+ }
+ },
+
+ /**
+ * Set up the partial.
+ *
+ * @since 4.5.0
+ */
+ ready: function() {
+ var sidebarPartial = this;
+
+ // Watch for changes to the sidebar_widgets setting.
+ _.each( sidebarPartial.settings(), function( settingId ) {
+ api( settingId ).bind( _.bind( sidebarPartial.handleSettingChange, sidebarPartial ) );
+ } );
+
+ // Trigger an event for this sidebar being updated whenever a widget inside is rendered.
+ api.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
+ var isAssignedWidgetPartial = (
+ placement.partial.extended( self.WidgetPartial ) &&
+ ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), placement.partial.widgetId ) )
+ );
+ if ( isAssignedWidgetPartial ) {
+ api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
+ }
+ } );
+
+ // Make sure that a widget partial has a container in the DOM prior to a refresh.
+ api.bind( 'change', function( widgetSetting ) {
+ var widgetId, parsedId;
+ parsedId = self.parseWidgetSettingId( widgetSetting.id );
+ if ( ! parsedId ) {
+ return;
+ }
+ widgetId = parsedId.idBase;
+ if ( parsedId.number ) {
+ widgetId += '-' + String( parsedId.number );
}
- self.widgetSelectors.push(widgetSelector);
- });
+ if ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), widgetId ) ) {
+ sidebarPartial.ensureWidgetPlacementContainers( widgetId );
+ }
+ } );
},
/**
- * Highlight the widget on widget updates or widget control mouse overs.
+ * Get the before/after boundary nodes for all instances of this sidebar (usually one).
+ *
+ * Note that TreeWalker is not implemented in IE8.
*
- * @param {string} widgetId ID of the widget.
+ * @since 4.5.0
+ * @returns {Array.<{before: Comment, after: Comment, instanceNumber: number}>}
*/
- highlightWidget: function( widgetId ) {
- var $body = $( document.body ),
- $widget = $( '#' + widgetId );
+ findDynamicSidebarBoundaryNodes: function() {
+ var partial = this, regExp, boundaryNodes = {}, recursiveCommentTraversal;
+ regExp = /^(dynamic_sidebar_before|dynamic_sidebar_after):(.+):(\d+)$/;
+ recursiveCommentTraversal = function( childNodes ) {
+ _.each( childNodes, function( node ) {
+ var matches;
+ if ( 8 === node.nodeType ) {
+ matches = node.nodeValue.match( regExp );
+ if ( ! matches || matches[2] !== partial.sidebarId ) {
+ return;
+ }
+ if ( _.isUndefined( boundaryNodes[ matches[3] ] ) ) {
+ boundaryNodes[ matches[3] ] = {
+ before: null,
+ after: null,
+ instanceNumber: parseInt( matches[3], 10 )
+ };
+ }
+ if ( 'dynamic_sidebar_before' === matches[1] ) {
+ boundaryNodes[ matches[3] ].before = node;
+ } else {
+ boundaryNodes[ matches[3] ].after = node;
+ }
+ } else if ( 1 === node.nodeType ) {
+ recursiveCommentTraversal( node.childNodes );
+ }
+ } );
+ };
- $body.find( '.widget-customizer-highlighted-widget' ).removeClass( 'widget-customizer-highlighted-widget' );
+ recursiveCommentTraversal( document.body.childNodes );
+ return _.values( boundaryNodes );
+ },
- $widget.addClass( 'widget-customizer-highlighted-widget' );
- setTimeout( function () {
- $widget.removeClass( 'widget-customizer-highlighted-widget' );
- }, 500 );
+ /**
+ * Get the placements for this partial.
+ *
+ * @since 4.5.0
+ * @returns {Array}
+ */
+ placements: function() {
+ var partial = this;
+ return _.map( partial.findDynamicSidebarBoundaryNodes(), function( boundaryNodes ) {
+ return new api.selectiveRefresh.Placement( {
+ partial: partial,
+ container: null,
+ startNode: boundaryNodes.before,
+ endNode: boundaryNodes.after,
+ context: {
+ instanceNumber: boundaryNodes.instanceNumber
+ }
+ } );
+ } );
},
/**
- * Show a title and highlight widgets on hover. On shift+clicking
- * focus the widget control.
+ * Get the list of widget IDs associated with this widget area.
+ *
+ * @since 4.5.0
+ *
+ * @returns {Array}
*/
- highlightControls: function() {
- var self = this,
- selector = this.widgetSelectors.join(',');
+ getWidgetIds: function() {
+ var sidebarPartial = this, settingId, widgetIds;
+ settingId = sidebarPartial.settings()[0];
+ if ( ! settingId ) {
+ throw new Error( 'Missing associated setting.' );
+ }
+ if ( ! api.has( settingId ) ) {
+ throw new Error( 'Setting does not exist.' );
+ }
+ widgetIds = api( settingId ).get();
+ if ( ! _.isArray( widgetIds ) ) {
+ throw new Error( 'Expected setting to be array of widget IDs' );
+ }
+ return widgetIds.slice( 0 );
+ },
- $(selector).attr( 'title', this.l10n.widgetTooltip );
+ /**
+ * Reflow widgets in the sidebar, ensuring they have the proper position in the DOM.
+ *
+ * @since 4.5.0
+ *
+ * @return {Array.<wp.customize.selectiveRefresh.Placement>} List of placements that were reflowed.
+ */
+ reflowWidgets: function() {
+ var sidebarPartial = this, sidebarPlacements, widgetIds, widgetPartials, sortedSidebarContainers = [];
+ widgetIds = sidebarPartial.getWidgetIds();
+ sidebarPlacements = sidebarPartial.placements();
+
+ widgetPartials = {};
+ _.each( widgetIds, function( widgetId ) {
+ var widgetPartial = api.selectiveRefresh.partial( 'widget[' + widgetId + ']' );
+ if ( widgetPartial ) {
+ widgetPartials[ widgetId ] = widgetPartial;
+ }
+ } );
+
+ _.each( sidebarPlacements, function( sidebarPlacement ) {
+ var sidebarWidgets = [], needsSort = false, thisPosition, lastPosition = -1;
+
+ // Gather list of widget partial containers in this sidebar, and determine if a sort is needed.
+ _.each( widgetPartials, function( widgetPartial ) {
+ _.each( widgetPartial.placements(), function( widgetPlacement ) {
+
+ if ( sidebarPlacement.context.instanceNumber === widgetPlacement.context.sidebar_instance_number ) {
+ thisPosition = widgetPlacement.container.index();
+ sidebarWidgets.push( {
+ partial: widgetPartial,
+ placement: widgetPlacement,
+ position: thisPosition
+ } );
+ if ( thisPosition < lastPosition ) {
+ needsSort = true;
+ }
+ lastPosition = thisPosition;
+ }
+ } );
+ } );
+
+ if ( needsSort ) {
+ _.each( sidebarWidgets, function( sidebarWidget ) {
+ sidebarPlacement.endNode.parentNode.insertBefore(
+ sidebarWidget.placement.container[0],
+ sidebarPlacement.endNode
+ );
+
+ // @todo Rename partial-placement-moved?
+ api.selectiveRefresh.trigger( 'partial-content-moved', sidebarWidget.placement );
+ } );
- $(document).on( 'mouseenter', selector, function () {
- self.preview.send( 'highlight-widget-control', $( this ).prop( 'id' ) );
- });
+ sortedSidebarContainers.push( sidebarPlacement );
+ }
+ } );
+
+ if ( sortedSidebarContainers.length > 0 ) {
+ api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
+ }
+
+ return sortedSidebarContainers;
+ },
+
+ /**
+ * Make sure there is a widget instance container in this sidebar for the given widget ID.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} widgetId
+ * @returns {wp.customize.selectiveRefresh.Partial} Widget instance partial.
+ */
+ ensureWidgetPlacementContainers: function( widgetId ) {
+ var sidebarPartial = this, widgetPartial, wasInserted = false, partialId = 'widget[' + widgetId + ']';
+ widgetPartial = api.selectiveRefresh.partial( partialId );
+ if ( ! widgetPartial ) {
+ widgetPartial = new self.WidgetPartial( partialId, {
+ params: {}
+ } );
+ api.selectiveRefresh.partial.add( widgetPartial.id, widgetPartial );
+ }
- // Open expand the widget control when shift+clicking the widget element
- $(document).on( 'click', selector, function ( e ) {
- if ( ! e.shiftKey ) {
+ // Make sure that there is a container element for the widget in the sidebar, if at least a placeholder.
+ _.each( sidebarPartial.placements(), function( sidebarPlacement ) {
+ var foundWidgetPlacement, widgetContainerElement;
+
+ foundWidgetPlacement = _.find( widgetPartial.placements(), function( widgetPlacement ) {
+ return ( widgetPlacement.context.sidebar_instance_number === sidebarPlacement.context.instanceNumber );
+ } );
+ if ( foundWidgetPlacement ) {
return;
}
- e.preventDefault();
- self.preview.send( 'focus-widget-control', $( this ).prop( 'id' ) );
- });
+ widgetContainerElement = $(
+ sidebarPartial.params.sidebarArgs.before_widget.replace( '%1$s', widgetId ).replace( '%2$s', 'widget' ) +
+ sidebarPartial.params.sidebarArgs.after_widget
+ );
+
+ widgetContainerElement.attr( 'data-customize-partial-id', widgetPartial.id );
+ widgetContainerElement.attr( 'data-customize-partial-type', 'widget' );
+ widgetContainerElement.attr( 'data-customize-widget-id', widgetId );
+
+ /*
+ * Make sure the widget container element has the customize-container context data.
+ * The sidebar_instance_number is used to disambiguate multiple instances of the
+ * same sidebar are rendered onto the template, and so the same widget is embedded
+ * multiple times.
+ */
+ widgetContainerElement.data( 'customize-partial-placement-context', {
+ 'sidebar_id': sidebarPartial.sidebarId,
+ 'sidebar_instance_number': sidebarPlacement.context.instanceNumber
+ } );
+
+ sidebarPlacement.endNode.parentNode.insertBefore( widgetContainerElement[0], sidebarPlacement.endNode );
+ wasInserted = true;
+ } );
+
+ if ( wasInserted ) {
+ sidebarPartial.reflowWidgets();
+ }
+
+ return widgetPartial;
+ },
+
+ /**
+ * Handle change to the sidebars_widgets[] setting.
+ *
+ * @since 4.5.0
+ *
+ * @param {Array} newWidgetIds New widget ids.
+ * @param {Array} oldWidgetIds Old widget ids.
+ */
+ handleSettingChange: function( newWidgetIds, oldWidgetIds ) {
+ var sidebarPartial = this, needsRefresh, widgetsRemoved, widgetsAdded, addedWidgetPartials = [];
+
+ needsRefresh = (
+ ( oldWidgetIds.length > 0 && 0 === newWidgetIds.length ) ||
+ ( newWidgetIds.length > 0 && 0 === oldWidgetIds.length )
+ );
+ if ( needsRefresh ) {
+ sidebarPartial.fallback();
+ return;
+ }
+
+ // Handle removal of widgets.
+ widgetsRemoved = _.difference( oldWidgetIds, newWidgetIds );
+ _.each( widgetsRemoved, function( removedWidgetId ) {
+ var widgetPartial = api.selectiveRefresh.partial( 'widget[' + removedWidgetId + ']' );
+ if ( widgetPartial ) {
+ _.each( widgetPartial.placements(), function( placement ) {
+ var isRemoved = (
+ placement.context.sidebar_id === sidebarPartial.sidebarId ||
+ ( placement.context.sidebar_args && placement.context.sidebar_args.id === sidebarPartial.sidebarId )
+ );
+ if ( isRemoved ) {
+ placement.container.remove();
+ }
+ } );
+ }
+ } );
+
+ // Handle insertion of widgets.
+ widgetsAdded = _.difference( newWidgetIds, oldWidgetIds );
+ _.each( widgetsAdded, function( addedWidgetId ) {
+ var widgetPartial = sidebarPartial.ensureWidgetPlacementContainers( addedWidgetId );
+ addedWidgetPartials.push( widgetPartial );
+ } );
+
+ _.each( addedWidgetPartials, function( widgetPartial ) {
+ widgetPartial.refresh();
+ } );
+
+ api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
+ },
+
+ /**
+ * Note that the meat is handled in handleSettingChange because it has the context of which widgets were removed.
+ *
+ * @since 4.5.0
+ */
+ refresh: function() {
+ var partial = this, deferred = $.Deferred();
+
+ deferred.fail( function() {
+ partial.fallback();
+ } );
+
+ if ( 0 === partial.placements().length ) {
+ deferred.reject();
+ } else {
+ _.each( partial.reflowWidgets(), function( sidebarPlacement ) {
+ api.selectiveRefresh.trigger( 'partial-content-rendered', sidebarPlacement );
+ } );
+ deferred.resolve();
+ }
+
+ return deferred.promise();
+ }
+ });
+
+ api.selectiveRefresh.partialConstructor.sidebar = self.SidebarPartial;
+ api.selectiveRefresh.partialConstructor.widget = self.WidgetPartial;
+
+ /**
+ * Add partials for the registered widget areas (sidebars).
+ *
+ * @since 4.5.0
+ */
+ self.addPartials = function() {
+ _.each( self.registeredSidebars, function( registeredSidebar ) {
+ var partial, partialId = 'sidebar[' + registeredSidebar.id + ']';
+ partial = api.selectiveRefresh.partial( partialId );
+ if ( ! partial ) {
+ partial = new self.SidebarPartial( partialId, {
+ params: {
+ sidebarArgs: registeredSidebar
+ }
+ } );
+ api.selectiveRefresh.partial.add( partial.id, partial );
+ }
+ } );
+ };
+
+ /**
+ * Calculate the selector for the sidebar's widgets based on the registered sidebar's info.
+ *
+ * @since 3.9.0
+ */
+ self.buildWidgetSelectors = function() {
+ var self = this;
+
+ $.each( self.registeredSidebars, function( i, sidebar ) {
+ var widgetTpl = [
+ sidebar.before_widget.replace( '%1$s', '' ).replace( '%2$s', '' ),
+ sidebar.before_title,
+ sidebar.after_title,
+ sidebar.after_widget
+ ].join( '' ),
+ emptyWidget,
+ widgetSelector,
+ widgetClasses;
+
+ emptyWidget = $( widgetTpl );
+ widgetSelector = emptyWidget.prop( 'tagName' );
+ widgetClasses = emptyWidget.prop( 'className' );
+
+ // Prevent a rare case when before_widget, before_title, after_title and after_widget is empty.
+ if ( ! widgetClasses ) {
+ return;
+ }
+
+ widgetClasses = widgetClasses.replace( /^\s+|\s+$/g, '' );
+
+ if ( widgetClasses ) {
+ widgetSelector += '.' + widgetClasses.split( /\s+/ ).join( '.' );
+ }
+ self.widgetSelectors.push( widgetSelector );
+ });
+ };
+
+ /**
+ * Highlight the widget on widget updates or widget control mouse overs.
+ *
+ * @since 3.9.0
+ * @param {string} widgetId ID of the widget.
+ */
+ self.highlightWidget = function( widgetId ) {
+ var $body = $( document.body ),
+ $widget = $( '#' + widgetId );
+
+ $body.find( '.widget-customizer-highlighted-widget' ).removeClass( 'widget-customizer-highlighted-widget' );
+
+ $widget.addClass( 'widget-customizer-highlighted-widget' );
+ setTimeout( function() {
+ $widget.removeClass( 'widget-customizer-highlighted-widget' );
+ }, 500 );
+ };
+
+ /**
+ * Show a title and highlight widgets on hover. On shift+clicking
+ * focus the widget control.
+ *
+ * @since 3.9.0
+ */
+ self.highlightControls = function() {
+ var self = this,
+ selector = this.widgetSelectors.join( ',' );
+
+ $( selector ).attr( 'title', this.l10n.widgetTooltip );
+
+ $( document ).on( 'mouseenter', selector, function() {
+ self.preview.send( 'highlight-widget-control', $( this ).prop( 'id' ) );
+ });
+
+ // Open expand the widget control when shift+clicking the widget element
+ $( document ).on( 'click', selector, function( e ) {
+ if ( ! e.shiftKey ) {
+ return;
+ }
+ e.preventDefault();
+
+ self.preview.send( 'focus-widget-control', $( this ).prop( 'id' ) );
+ });
+ };
+
+ /**
+ * Parse a widget ID.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} widgetId Widget ID.
+ * @returns {{idBase: string, number: number|null}}
+ */
+ self.parseWidgetId = function( widgetId ) {
+ var matches, parsed = {
+ idBase: '',
+ number: null
+ };
+
+ matches = widgetId.match( /^(.+)-(\d+)$/ );
+ if ( matches ) {
+ parsed.idBase = matches[1];
+ parsed.number = parseInt( matches[2], 10 );
+ } else {
+ parsed.idBase = widgetId; // Likely an old single widget.
}
+
+ return parsed;
};
/**
- * Capture the instance of the Preview since it is private
+ * Parse a widget setting ID.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} settingId Widget setting ID.
+ * @returns {{idBase: string, number: number|null}|null}
*/
- OldPreview = api.Preview;
- api.Preview = OldPreview.extend( {
- initialize: function( params, options ) {
- api.WidgetCustomizerPreview.preview = this;
- OldPreview.prototype.initialize.call( this, params, options );
+ self.parseWidgetSettingId = function( settingId ) {
+ var matches, parsed = {
+ idBase: '',
+ number: null
+ };
+
+ matches = settingId.match( /^widget_([^\[]+?)(?:\[(\d+)])?$/ );
+ if ( ! matches ) {
+ return null;
+ }
+ parsed.idBase = matches[1];
+ if ( matches[2] ) {
+ parsed.number = parseInt( matches[2], 10 );
}
- } );
+ return parsed;
+ };
- $(function () {
- var settings = window._wpWidgetCustomizerPreviewSettings;
- if ( ! settings ) {
- return;
+ /**
+ * Convert a widget ID into a Customizer setting ID.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} widgetId Widget ID.
+ * @returns {string} settingId Setting ID.
+ */
+ self.getWidgetSettingId = function( widgetId ) {
+ var parsed = this.parseWidgetId( widgetId ), settingId;
+
+ settingId = 'widget_' + parsed.idBase;
+ if ( parsed.number ) {
+ settingId += '[' + String( parsed.number ) + ']';
}
- $.extend( api.WidgetCustomizerPreview, settings );
+ return settingId;
+ };
- api.WidgetCustomizerPreview.init();
+ api.bind( 'preview-ready', function() {
+ $.extend( self, _wpWidgetCustomizerPreviewSettings );
+ self.init();
});
-})( window.wp, jQuery );
+ return self;
+})( jQuery, _, wp, wp.customize );