<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[27985] trunk/src: Widget Customizer: Move `WidgetCustomizer` to `wp.customize.Widgets`.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/27985">27985</a></dd>
<dt>Author</dt> <dd>ocean90</dd>
<dt>Date</dt> <dd>2014-04-07 09:03:18 +0000 (Mon, 07 Apr 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Widget Customizer: Move `WidgetCustomizer` to `wp.customize.Widgets`. First pass.
see <a href="http://core.trac.wordpress.org/ticket/27690">#27690</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadmincsscustomizecontrolscss">trunk/src/wp-admin/css/customize-controls.css</a></li>
<li><a href="#trunksrcwpadmincsscustomizewidgetscss">trunk/src/wp-admin/css/customize-widgets.css</a></li>
<li><a href="#trunksrcwpadminjscustomizewidgetsjs">trunk/src/wp-admin/js/customize-widgets.js</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizecontrolphp">trunk/src/wp-includes/class-wp-customize-control.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizewidgetsphp">trunk/src/wp-includes/class-wp-customize-widgets.php</a></li>
<li><a href="#trunksrcwpincludesjscustomizepreviewwidgetsjs">trunk/src/wp-includes/js/customize-preview-widgets.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadmincsscustomizecontrolscss"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-admin/css/customize-controls.css (27984 => 27985)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/css/customize-controls.css 2014-04-07 09:02:06 UTC (rev 27984)
+++ trunk/src/wp-admin/css/customize-controls.css 2014-04-07 09:03:18 UTC (rev 27985)
</span><span class="lines">@@ -490,6 +490,7 @@
</span><span class="cx"> overflow: hidden;
</span><span class="cx"> -webkit-border-radius: 2px;
</span><span class="cx"> border: 1px solid #eee;
</span><ins>+ -webkit-border-radius: 2px;
</ins><span class="cx"> border-radius: 2px;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunksrcwpadmincsscustomizewidgetscss"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-admin/css/customize-widgets.css (27984 => 27985)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/css/customize-widgets.css 2014-04-07 09:02:06 UTC (rev 27984)
+++ trunk/src/wp-admin/css/customize-widgets.css 2014-04-07 09:03:18 UTC (rev 27985)
</span><span class="lines">@@ -108,13 +108,6 @@
</span><span class="cx"> display: none;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-
-/* MP6-compat */
-#customize-theme-controls .accordion-section-content .widget {
- color: black;
-}
-
-
</del><span class="cx"> /**
</span><span class="cx"> * Widget reordering styles
</span><span class="cx"> **/
</span><span class="lines">@@ -326,7 +319,7 @@
</span><span class="cx">
</span><span class="cx"> body.adding-widget .add-new-widget,
</span><span class="cx"> body.adding-widget .add-new-widget:hover {
</span><del>- background: #EEE;
</del><ins>+ background: #eee;
</ins><span class="cx"> border-color: #999;
</span><span class="cx"> color: #333;
</span><span class="cx"> -webkit-box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, 0.5);
</span></span></pre></div>
<a id="trunksrcwpadminjscustomizewidgetsjs"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-admin/js/customize-widgets.js (27984 => 27985)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-admin/js/customize-widgets.js 2014-04-07 09:02:06 UTC (rev 27984)
+++ trunk/src/wp-admin/js/customize-widgets.js 2014-04-07 09:03:18 UTC (rev 27985)
</span><span class="lines">@@ -1,45 +1,23 @@
</span><del>-/*global wp, Backbone, _, jQuery, WidgetCustomizer_exports */
-/*exported WidgetCustomizer */
-var WidgetCustomizer = ( function ($) {
- 'use strict';
</del><ins>+/* global _wpCustomizeWidgetsSettings */
+(function( wp, $ ){
</ins><span class="cx">
</span><del>- var Widget,
- WidgetCollection,
- Sidebar,
- SidebarCollection,
- OldPreviewer,
- builtin_form_sync_handlers,
- customize = wp.customize, self = {
- nonce: null,
- i18n: {
- save_btn_label: '',
- save_btn_tooltip: '',
- remove_btn_label: '',
- remove_btn_tooltip: '',
- error: ''
- },
- available_widgets: [], // available widgets for instantiating
- registered_widgets: [], // all widgets registered
- active_sidebar_control: null,
- previewer: null,
- saved_widget_ids: {},
- registered_sidebars: [],
- tpl: {
- move_widget_area: '',
- widget_reorder_nav: ''
- }
- };
- $.extend( self, WidgetCustomizer_exports );
</del><ins>+ if ( ! wp || ! wp.customize ) { return; }
</ins><span class="cx">
</span><del>- // Lots of widgets expect this old ajaxurl global to be available
- if ( typeof window.ajaxurl === 'undefined' ) {
- window.ajaxurl = wp.ajax.settings.url;
- }
</del><ins>+ // Set up our namespace...
+ var api = wp.customize,
+ l10n, OldPreviewer;
</ins><span class="cx">
</span><ins>+ api.Widgets = api.Widgets || {};
+
+ // Link settings
+ api.Widgets.data = _wpCustomizeWidgetsSettings || {};
+ l10n = api.Widgets.data.l10n;
+ delete api.Widgets.data.l10n;
+
</ins><span class="cx"> /**
</span><span class="cx"> * Set up model
</span><span class="cx"> */
</span><del>- Widget = self.Widget = Backbone.Model.extend( {
</del><ins>+ api.Widgets.WidgetModel = Backbone.Model.extend({
</ins><span class="cx"> id: null,
</span><span class="cx"> temp_id: null,
</span><span class="cx"> classname: null,
</span><span class="lines">@@ -54,10 +32,10 @@
</span><span class="cx"> params: [],
</span><span class="cx"> width: null,
</span><span class="cx"> height: null
</span><del>- } );
</del><ins>+ });
</ins><span class="cx">
</span><del>- WidgetCollection = self.WidgetCollection = Backbone.Collection.extend( {
- model: Widget,
</del><ins>+ api.Widgets.WidgetCollection = Backbone.Collection.extend({
+ model: api.Widgets.WidgetModel,
</ins><span class="cx">
</span><span class="cx"> // Controls searching on the current widget collection
</span><span class="cx"> // and triggers an update event
</span><span class="lines">@@ -80,7 +58,7 @@
</span><span class="cx"> // If search is blank, show all themes
</span><span class="cx"> // Useful for resetting the views when you clean the input
</span><span class="cx"> if ( this.terms === '' ) {
</span><del>- this.reset( WidgetCustomizer_exports.available_widgets );
</del><ins>+ this.reset( api.Widgets.data.availableWidgets );
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Trigger an 'update' event
</span><span class="lines">@@ -93,7 +71,7 @@
</span><span class="cx"> var match, results, haystack;
</span><span class="cx">
</span><span class="cx"> // Start with a full collection
</span><del>- this.reset( WidgetCustomizer_exports.available_widgets, { silent: true } );
</del><ins>+ this.reset( api.Widgets.data.availableWidgets, { silent: true } );
</ins><span class="cx">
</span><span class="cx"> // Escape the term string for RegExp meta characters
</span><span class="cx"> term = term.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' );
</span><span class="lines">@@ -111,10 +89,10 @@
</span><span class="cx">
</span><span class="cx"> this.reset( results );
</span><span class="cx"> }
</span><del>- } );
- self.available_widgets = new WidgetCollection( self.available_widgets );
</del><ins>+ });
+ api.Widgets.availableWidgets = new api.Widgets.WidgetCollection( api.Widgets.data.availableWidgets );
</ins><span class="cx">
</span><del>- Sidebar = self.Sidebar = Backbone.Model.extend( {
</del><ins>+ api.Widgets.SidebarModel = Backbone.Model.extend({
</ins><span class="cx"> after_title: null,
</span><span class="cx"> after_widget: null,
</span><span class="cx"> before_title: null,
</span><span class="lines">@@ -124,502 +102,44 @@
</span><span class="cx"> id: null,
</span><span class="cx"> name: null,
</span><span class="cx"> is_rendered: false
</span><del>- } );
</del><ins>+ });
</ins><span class="cx">
</span><del>- SidebarCollection = self.SidebarCollection = Backbone.Collection.extend( {
- model: Sidebar
- } );
- self.registered_sidebars = new SidebarCollection( self.registered_sidebars );
</del><ins>+ api.Widgets.SidebarCollection = Backbone.Collection.extend({
+ model: api.Widgets.SidebarModel
+ });
+ api.Widgets.registeredSidebars = new api.Widgets.SidebarCollection( api.Widgets.data.registeredSidebars );
</ins><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * Handlers for the widget-synced event, organized by widget ID base.
</span><span class="cx"> * Other widgets may provide their own update handlers by adding
</span><span class="cx"> * listeners for the widget-synced event.
</span><span class="cx"> */
</span><del>- builtin_form_sync_handlers = {
</del><ins>+ api.Widgets.formSyncHandlers = {
</ins><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * @param {jQuery.Event} e
</span><del>- * @param {jQuery} widget_el
- * @param {String} new_form
</del><ins>+ * @param {jQuery} widget
+ * @param {String} newForm
</ins><span class="cx"> */
</span><del>- rss: function ( e, widget_el, new_form ) {
- var old_widget_error = widget_el.find( '.widget-error:first' ),
- new_widget_error = $( '<div>' + new_form + '</div>' ).find( '.widget-error:first' );
</del><ins>+ rss: function ( e, widget, newForm ) {
+ var oldWidgetError = widget.find( '.widget-error:first' ),
+ newWidgetError = $( '<div>' + newForm + '</div>' ).find( '.widget-error:first' );
</ins><span class="cx">
</span><del>- if ( old_widget_error.length && new_widget_error.length ) {
- old_widget_error.replaceWith( new_widget_error );
- } else if ( old_widget_error.length ) {
- old_widget_error.remove();
- } else if ( new_widget_error.length ) {
- widget_el.find( '.widget-content:first' ).prepend( new_widget_error );
</del><ins>+ if ( oldWidgetError.length && newWidgetError.length ) {
+ oldWidgetError.replaceWith( newWidgetError );
+ } else if ( oldWidgetError.length ) {
+ oldWidgetError.remove();
+ } else if ( newWidgetError.length ) {
+ widget.find( '.widget-content:first' ).prepend( newWidgetError );
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> /**
</span><del>- * On DOM ready, initialize some meta functionality independent of specific
- * customizer controls.
- */
- self.init = function () {
- this.availableWidgetsPanel.setup();
-
- // Highlight widget control
- this.previewer.bind( 'highlight-widget-control', self.highlightWidgetFormControl );
-
- // Open and focus widget control
- this.previewer.bind( 'focus-widget-control', self.focusWidgetFormControl );
- };
- wp.customize.bind( 'ready', function () {
- self.init();
- } );
-
- /**
- * Sidebar Widgets control
- * Note that 'sidebar_widgets' must match the Sidebar_Widgets_WP_Customize_Control::$type
- */
- customize.controlConstructor.sidebar_widgets = customize.Control.extend( {
-
- /**
- * Set up the control
- */
- ready: function() {
- var control = this;
- control.control_section = control.container.closest( '.control-section' );
- control.section_content = control.container.closest( '.accordion-section-content' );
- control._setupModel();
- control._setupSortable();
- control._setupAddition();
- control._applyCardinalOrderClassNames();
- },
-
- /**
- * Update ordering of widget control forms when the setting is updated
- */
- _setupModel: function() {
- var control = this,
- registered_sidebar = self.registered_sidebars.get( control.params.sidebar_id );
-
- control.setting.bind( function( new_widget_ids, old_widget_ids ) {
- var widget_form_controls,
- sidebar_widgets_add_control,
- final_control_containers,
- 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 ) {
- var parsed_widget_id = parse_widget_id( new_widget_id );
- return !! self.available_widgets.findWhere( { id_base: parsed_widget_id.id_base } );
- } );
-
- widget_form_controls = _( new_widget_ids ).map( function ( widget_id ) {
- var widget_form_control = self.getWidgetFormControlForWidget( widget_id );
- if ( ! widget_form_control ) {
- widget_form_control = control.addWidget( widget_id );
- }
- return widget_form_control;
- } );
-
- // Sort widget controls to their new positions
- 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 ) {
- return 0;
- }
- return a_index < b_index ? -1 : 1;
- } );
-
- sidebar_widgets_add_control = control.section_content.find( '.customize-control-sidebar_widgets' );
-
- // Append the controls to put them in the right order
- final_control_containers = _( widget_form_controls ).map( function( widget_form_controls ) {
- return widget_form_controls.container[0];
- } );
-
- // Re-sort widget form controls (including widgets form other sidebars newly moved here)
- sidebar_widgets_add_control.before( final_control_containers );
- 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_control.params.sidebar_id = control.params.sidebar_id;
- } );
-
- // Cleanup after widget removal
- _( 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 () {
- var is_present_in_another_sidebar = false,
- removed_control,
- was_dragged_to_another_sidebar,
- inactive_widgets,
- removed_id_base,
- widget;
-
- // Check if the widget is in another sidebar
- wp.customize.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;
- }
- var other_sidebar_widgets = other_setting(), i;
-
- i = _.indexOf( other_sidebar_widgets, removed_widget_id );
- if ( -1 !== i ) {
- is_present_in_another_sidebar = true;
- }
- } );
-
- // If the widget is present in another sidebar, abort!
- if ( is_present_in_another_sidebar ) {
- return;
- }
-
- removed_control = self.getWidgetFormControlForWidget( removed_widget_id );
-
- // Detect if widget control was dragged to another sidebar
- was_dragged_to_another_sidebar = (
- removed_control &&
- $.contains( document, removed_control.container[0] ) &&
- ! $.contains( control.section_content[0], removed_control.container[0] )
- );
-
- // Delete any widget form controls for removed widgets
- if ( removed_control && ! was_dragged_to_another_sidebar ) {
- wp.customize.control.remove( removed_control.id );
- removed_control.container.remove();
- }
-
- // Move widget to inactive widgets sidebar (move it to trash) if has been previously saved
- // This prevents the inactive widgets sidebar from overflowing with throwaway widgets
- if ( self.saved_widget_ids[removed_widget_id] ) {
- inactive_widgets = wp.customize.value( 'sidebars_widgets[wp_inactive_widgets]' )().slice();
- inactive_widgets.push( removed_widget_id );
- wp.customize.value( 'sidebars_widgets[wp_inactive_widgets]' )( _( inactive_widgets ).unique() );
- }
-
- // Make old single widget available for adding again
- removed_id_base = parse_widget_id( removed_widget_id ).id_base;
- widget = self.available_widgets.findWhere( { id_base: removed_id_base } );
- if ( widget && ! widget.get( 'is_multi' ) ) {
- widget.set( 'is_disabled', false );
- }
- } );
-
- } );
- } );
-
- // Update the model with whether or not the sidebar is rendered
- self.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 ( ) {
- var section_selector = '#accordion-section-sidebar-widgets-' + this.get( 'id' ), section;
- section = $( section_selector );
- if ( this.get( 'is_rendered' ) ) {
- section.stop().slideDown( function () {
- $( this ).css( 'height', 'auto' ); // so that the .accordion-section-content won't overflow
- } );
- } else {
- // Make sure that hidden sections get closed first
- if ( section.hasClass( 'open' ) ) {
- // it would be nice if accordionSwitch() in accordion.js was public
- section.find( '.accordion-section-title' ).trigger( 'click' );
- }
- section.stop().slideUp();
- }
- } );
- },
-
- /**
- * Allow widgets in sidebar to be re-ordered, and for the order to be previewed
- */
- _setupSortable: function () {
- var control = this;
- control.is_reordering = false;
-
- /**
- * Update widget order setting when controls are re-ordered
- */
- control.section_content.sortable( {
- items: '> .customize-control-widget_form',
- handle: '.widget-top',
- axis: 'y',
- 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 ) {
- return $( '#' + widget_container_id ).find( ':input[name=widget-id]' ).val();
- } );
- control.setting( widget_ids );
- }
- } );
-
- /**
- * Expand other customizer sidebar section when dragging a control widget over it,
- * allowing the control to be dropped into another section
- */
- control.control_section.find( '.accordion-section-title' ).droppable( {
- accept: '.customize-control-widget_form',
- over: function () {
- if ( ! control.control_section.hasClass( 'open' ) ) {
- control.control_section.addClass( 'open' );
- control.section_content.toggle( false ).slideToggle( 150, function () {
- control.section_content.sortable( 'refreshPositions' );
- } );
- }
- }
- } );
-
- /**
- * Keyboard-accessible reordering
- */
- control.container.find( '.reorder-toggle' ).on( 'click keydown', function( event ) {
- if ( event.type === 'keydown' && ! ( event.which === 13 || event.which === 32 ) ) { // Enter or Spacebar
- return;
- }
-
- control.toggleReordering( ! control.is_reordering );
- } );
- },
-
- /**
- * Set up UI for adding a new widget
- */
- _setupAddition: function () {
- var control = this;
-
- control.container.find( '.add-new-widget' ).on( 'click keydown', function( event ) {
- if ( event.type === 'keydown' && ! ( event.which === 13 || event.which === 32 ) ) { // Enter or Spacebar
- return;
- }
-
- if ( control.section_content.hasClass( 'reordering' ) ) {
- return;
- }
-
- // @todo Use an control.is_adding state
- if ( ! $( 'body' ).hasClass( 'adding-widget' ) ) {
- self.availableWidgetsPanel.open( control );
- } else {
- self.availableWidgetsPanel.close();
- }
- } );
- },
-
- /**
- * Add classes to the widget_form controls to assist with styling
- */
- _applyCardinalOrderClassNames: function () {
- var control = this;
- control.section_content.find( '.customize-control-widget_form' )
- .removeClass( 'first-widget' )
- .removeClass( 'last-widget' )
- .find( '.move-widget-down, .move-widget-up' ).prop( 'tabIndex', 0 );
-
- control.section_content.find( '.customize-control-widget_form:first' )
- .addClass( 'first-widget' )
- .find( '.move-widget-up' ).prop( 'tabIndex', -1 );
- control.section_content.find( '.customize-control-widget_form:last' )
- .addClass( 'last-widget' )
- .find( '.move-widget-down' ).prop( 'tabIndex', -1 );
- },
-
-
- /***********************************************************************
- * Begin public API methods
- **********************************************************************/
-
- /**
- * Enable/disable the reordering UI
- *
- * @param {Boolean} toggle to enable/disable reordering
- */
- toggleReordering: function ( toggle ) {
- var control = this;
- toggle = Boolean( toggle );
- if ( toggle === control.section_content.hasClass( 'reordering' ) ) {
- return;
- }
-
- control.is_reordering = toggle;
- control.section_content.toggleClass( 'reordering', toggle );
-
- if ( toggle ) {
- _( control.getWidgetFormControls() ).each( function ( form_control ) {
- form_control.collapseForm();
- } );
- }
- },
-
- /**
- * @return {wp.customize.controlConstructor.widget_form[]}
- */
- getWidgetFormControls: function () {
- var control = this, form_controls;
-
- form_controls = _( control.setting() ).map( function ( widget_id ) {
- var setting_id = widget_id_to_setting_id( widget_id ),
- form_control = customize.control( setting_id );
-
- if ( ! form_control ) {
- throw new Error( 'Unable to find widget_form control for ' + widget_id );
- }
- return form_control;
- } );
- return form_controls;
- },
-
- /**
- * @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 ) {
- var control = this,
- control_html,
- widget_el,
- customize_control_type = 'widget_form',
- customize_control,
- parsed_widget_id = parse_widget_id( widget_id ),
- widget_number = parsed_widget_id.number,
- widget_id_base = parsed_widget_id.id_base,
- widget = self.available_widgets.findWhere( {id_base: widget_id_base} ),
- setting_id,
- is_existing_widget,
- Constructor,
- widget_form_control,
- sidebar_widgets,
- setting_args;
-
- if ( ! widget ) {
- throw new Error( 'Widget unexpectedly not found.' );
- }
- if ( widget_number && ! widget.get( 'is_multi' ) ) {
- throw new Error( 'Did not expect a widget number to be supplied for a non-multi widget' );
- }
-
- // Set up new multi widget
- if ( widget.get( 'is_multi' ) && ! widget_number ) {
- widget.set( 'multi_number', widget.get( 'multi_number' ) + 1 );
- widget_number = widget.get( 'multi_number' );
- }
-
- control_html = $( '#widget-tpl-' + widget.get( 'id' ) ).html();
- if ( widget.get( 'is_multi' ) ) {
- control_html = control_html.replace( /<[^<>]+>/g, function ( m ) {
- return m.replace( /__i__|%i%/g, widget_number );
- } );
- } else {
- widget.set( 'is_disabled', true ); // Prevent single widget from being added again now
- }
- widget_el = $( control_html );
-
- customize_control = $( '<li></li>' );
- customize_control.addClass( 'customize-control' );
- customize_control.addClass( 'customize-control-' + customize_control_type );
- customize_control.append( widget_el );
- customize_control.find( '> .widget-icon' ).remove();
- if ( widget.get( 'is_multi' ) ) {
- customize_control.find( 'input[name="widget_number"]' ).val( widget_number );
- customize_control.find( 'input[name="multi_number"]' ).val( widget_number );
- }
- widget_id = customize_control.find( '[name="widget-id"]' ).val();
- customize_control.hide(); // to be slid-down below
-
- setting_id = 'widget_' + widget.get( 'id_base' );
- if ( widget.get( 'is_multi' ) ) {
- setting_id += '[' + widget_number + ']';
- }
- customize_control.attr( 'id', 'customize-control-' + setting_id.replace( /\]/g, '' ).replace( /\[/g, '-' ) );
-
- control.container.after( customize_control );
-
- // Only create setting if it doesn't already exist (if we're adding a pre-existing inactive widget)
- is_existing_widget = wp.customize.has( setting_id );
- if ( ! is_existing_widget ) {
- setting_args = {
- transport: 'refresh',
- previewer: control.setting.previewer
- };
- wp.customize.create( setting_id, setting_id, {}, setting_args );
- }
-
- Constructor = wp.customize.controlConstructor[customize_control_type];
- widget_form_control = new Constructor( setting_id, {
- params: {
- settings: {
- 'default': setting_id
- },
- sidebar_id: control.params.sidebar_id,
- widget_id: widget_id,
- widget_id_base: widget.get( 'id_base' ),
- type: customize_control_type,
- is_new: ! is_existing_widget,
- width: widget.get( 'width' ),
- height: widget.get( 'height' ),
- is_wide: widget.get( 'is_wide' )
- },
- previewer: control.setting.previewer
- } );
- wp.customize.control.add( setting_id, widget_form_control );
-
- // Make sure widget is removed from the other sidebars
- wp.customize.each( function ( other_setting ) {
- if ( other_setting.id === control.setting.id ) {
- return;
- }
- if ( 0 !== other_setting.id.indexOf( 'sidebars_widgets[' ) ) {
- return;
- }
- var other_sidebar_widgets = other_setting().slice(), i;
- i = _.indexOf( other_sidebar_widgets, widget_id );
- if ( -1 !== i ) {
- other_sidebar_widgets.splice( i );
- other_setting( other_sidebar_widgets );
- }
- } );
-
- // Add widget to this sidebar
- sidebar_widgets = control.setting().slice();
- if ( -1 === _.indexOf( sidebar_widgets, widget_id ) ) {
- sidebar_widgets.push( widget_id );
- control.setting( sidebar_widgets );
- }
-
- customize_control.slideDown( function () {
- if ( is_existing_widget ) {
- widget_form_control.expandForm();
- widget_form_control.updateWidget( {
- instance: widget_form_control.setting(),
- complete: function ( error ) {
- if ( error ) {
- throw error;
- }
- widget_form_control.focus();
- }
- } );
- } else {
- widget_form_control.focus();
- }
- } );
-
- $( document ).trigger( 'widget-added', [ widget_el ] );
-
- return widget_form_control;
- }
-
- } );
-
- /**
</del><span class="cx"> * Widget Form control
</span><del>- * Note that 'widget_form' must match the Widget_Form_WP_Customize_Control::$type
</del><ins>+ * Note that 'widget_form' must match the WP_Widget_Form_Customize_Control::$type
</ins><span class="cx"> */
</span><del>- customize.controlConstructor.widget_form = customize.Control.extend( {
-
</del><ins>+ api.Widgets.WidgetControl = api.Control.extend({
</ins><span class="cx"> /**
</span><span class="cx"> * Set up the control
</span><span class="cx"> */
</span><span class="lines">@@ -638,15 +158,17 @@
</span><span class="cx"> /**
</span><span class="cx"> * Handle changes to the setting
</span><span class="cx"> */
</span><del>- _setupModel: function () {
</del><ins>+ _setupModel: function() {
</ins><span class="cx"> var control = this, remember_saved_widget_id;
</span><span class="cx">
</span><ins>+ api.Widgets.savedWidgetIds = api.Widgets.savedWidgetIds || [];
+
</ins><span class="cx"> // Remember saved widgets so we know which to trash (move to inactive widgets sidebar)
</span><del>- remember_saved_widget_id = function () {
- self.saved_widget_ids[control.params.widget_id] = true;
</del><ins>+ remember_saved_widget_id = function() {
+ api.Widgets.savedWidgetIds[control.params.widget_id] = true;
</ins><span class="cx"> };
</span><del>- wp.customize.bind( 'ready', remember_saved_widget_id );
- wp.customize.bind( 'saved', remember_saved_widget_id );
</del><ins>+ api.bind( 'ready', remember_saved_widget_id );
+ api.bind( 'saved', remember_saved_widget_id );
</ins><span class="cx">
</span><span class="cx"> control._update_count = 0;
</span><span class="cx"> control.is_widget_updating = false;
</span><span class="lines">@@ -663,7 +185,7 @@
</span><span class="cx"> /**
</span><span class="cx"> * Add special behaviors for wide widget controls
</span><span class="cx"> */
</span><del>- _setupWideWidget: function () {
</del><ins>+ _setupWideWidget: function() {
</ins><span class="cx"> var control = this,
</span><span class="cx"> widget_inside,
</span><span class="cx"> widget_form,
</span><span class="lines">@@ -694,7 +216,7 @@
</span><span class="cx"> * exceed the window height so that the contents of the widget control
</span><span class="cx"> * will become scrollable (overflow:auto).
</span><span class="cx"> */
</span><del>- position_widget = function () {
</del><ins>+ position_widget = function() {
</ins><span class="cx"> var offset_top = control.container.offset().top,
</span><span class="cx"> window_height = $( window ).height(),
</span><span class="cx"> form_height = widget_form.outerHeight(),
</span><span class="lines">@@ -711,22 +233,22 @@
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> theme_controls_container = $( '#customize-theme-controls' );
</span><del>- control.container.on( 'expand', function () {
</del><ins>+ control.container.on( 'expand', function() {
</ins><span class="cx"> position_widget();
</span><span class="cx"> customize_sidebar.on( 'scroll', position_widget );
</span><span class="cx"> $( window ).on( 'resize', position_widget );
</span><span class="cx"> theme_controls_container.on( 'expanded collapsed', position_widget );
</span><span class="cx"> } );
</span><del>- control.container.on( 'collapsed', function () {
</del><ins>+ control.container.on( 'collapsed', function() {
</ins><span class="cx"> customize_sidebar.off( 'scroll', position_widget );
</span><span class="cx"> $( window ).off( 'resize', position_widget );
</span><span class="cx"> theme_controls_container.off( 'expanded collapsed', position_widget );
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="cx"> // Reposition whenever a sidebar's widgets are changed
</span><del>- wp.customize.each( function ( setting ) {
</del><ins>+ api.each( function ( setting ) {
</ins><span class="cx"> if ( 0 === setting.id.indexOf( 'sidebars_widgets[' ) ) {
</span><del>- setting.bind( function () {
</del><ins>+ setting.bind( function() {
</ins><span class="cx"> if ( control.container.hasClass( 'expanded' ) ) {
</span><span class="cx"> position_widget();
</span><span class="cx"> }
</span><span class="lines">@@ -763,10 +285,10 @@
</span><span class="cx"> /**
</span><span class="cx"> * Update the title of the form if a title field is entered
</span><span class="cx"> */
</span><del>- _setupWidgetTitle: function () {
</del><ins>+ _setupWidgetTitle: function() {
</ins><span class="cx"> var control = this, update_title;
</span><span class="cx">
</span><del>- update_title = function () {
</del><ins>+ update_title = function() {
</ins><span class="cx"> var title = control.setting().title,
</span><span class="cx"> in_widget_title = control.container.find( '.in-widget-title' );
</span><span class="cx">
</span><span class="lines">@@ -783,7 +305,7 @@
</span><span class="cx"> /**
</span><span class="cx"> * Set up the widget-reorder-nav
</span><span class="cx"> */
</span><del>- _setupReorderUI: function () {
</del><ins>+ _setupReorderUI: function() {
</ins><span class="cx"> var control = this,
</span><span class="cx"> select_sidebar_item,
</span><span class="cx"> move_widget_area,
</span><span class="lines">@@ -805,10 +327,10 @@
</span><span class="cx"> /**
</span><span class="cx"> * Add the widget reordering elements to the widget control
</span><span class="cx"> */
</span><del>- control.container.find( '.widget-title-action' ).after( $( self.tpl.widget_reorder_nav ) );
</del><ins>+ control.container.find( '.widget-title-action' ).after( $( api.Widgets.data.tpl.widgetReorderNav ) );
</ins><span class="cx"> move_widget_area = $(
</span><del>- _.template( self.tpl.move_widget_area, {
- sidebars: _( self.registered_sidebars.toArray() ).pluck( 'attributes' )
</del><ins>+ _.template( api.Widgets.data.tpl.moveWidgetArea, {
+ sidebars: _( api.Widgets.registeredSidebars.toArray() ).pluck( 'attributes' )
</ins><span class="cx"> } )
</span><span class="cx"> );
</span><span class="cx"> control.container.find( '.widget-top' ).after( move_widget_area );
</span><span class="lines">@@ -816,18 +338,18 @@
</span><span class="cx"> /**
</span><span class="cx"> * Update available sidebars when their rendered state changes
</span><span class="cx"> */
</span><del>- update_available_sidebars = function () {
</del><ins>+ update_available_sidebars = function() {
</ins><span class="cx"> var sidebar_items = move_widget_area.find( 'li' ), self_sidebar_item;
</span><span class="cx"> self_sidebar_item = sidebar_items.filter( function(){
</span><span class="cx"> return $( this ).data( 'id' ) === control.params.sidebar_id;
</span><span class="cx"> } );
</span><del>- sidebar_items.each( function () {
</del><ins>+ sidebar_items.each( function() {
</ins><span class="cx"> var li = $( this ),
</span><span class="cx"> sidebar_id,
</span><span class="cx"> sidebar_model;
</span><span class="cx">
</span><span class="cx"> sidebar_id = li.data( 'id' );
</span><del>- sidebar_model = self.registered_sidebars.get( sidebar_id );
</del><ins>+ sidebar_model = api.Widgets.registeredSidebars.get( sidebar_id );
</ins><span class="cx"> li.toggle( sidebar_model.get( 'is_rendered' ) );
</span><span class="cx"> if ( li.hasClass( 'selected' ) && ! sidebar_model.get( 'is_rendered' ) ) {
</span><span class="cx"> select_sidebar_item( self_sidebar_item );
</span><span class="lines">@@ -835,7 +357,7 @@
</span><span class="cx"> } );
</span><span class="cx"> };
</span><span class="cx"> update_available_sidebars();
</span><del>- self.registered_sidebars.on( 'change:is_rendered', update_available_sidebars );
</del><ins>+ api.Widgets.registeredSidebars.on( 'change:is_rendered', update_available_sidebars );
</ins><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * Handle clicks for up/down/move on the reorder nav
</span><span class="lines">@@ -882,7 +404,7 @@
</span><span class="cx"> /**
</span><span class="cx"> * Move widget to another sidebar
</span><span class="cx"> */
</span><del>- control.container.find( '.move-widget-btn' ).click( function () {
</del><ins>+ control.container.find( '.move-widget-btn' ).click( function() {
</ins><span class="cx"> control.getSidebarWidgetsControl().toggleReordering( false );
</span><span class="cx">
</span><span class="cx"> var old_sidebar_id = control.params.sidebar_id,
</span><span class="lines">@@ -893,8 +415,8 @@
</span><span class="cx"> new_sidebar_widget_ids,
</span><span class="cx"> i;
</span><span class="cx">
</span><del>- old_sidebar_widgets_setting = customize( 'sidebars_widgets[' + old_sidebar_id + ']' );
- new_sidebar_widgets_setting = customize( 'sidebars_widgets[' + new_sidebar_id + ']' );
</del><ins>+ old_sidebar_widgets_setting = api( 'sidebars_widgets[' + old_sidebar_id + ']' );
+ new_sidebar_widgets_setting = api( 'sidebars_widgets[' + new_sidebar_id + ']' );
</ins><span class="cx"> old_sidebar_widget_ids = Array.prototype.slice.call( old_sidebar_widgets_setting() );
</span><span class="cx"> new_sidebar_widget_ids = Array.prototype.slice.call( new_sidebar_widgets_setting() );
</span><span class="cx">
</span><span class="lines">@@ -916,17 +438,17 @@
</span><span class="cx"> var control = this;
</span><span class="cx">
</span><span class="cx"> // Highlight whenever hovering or clicking over the form
</span><del>- control.container.on( 'mouseenter click', function () {
</del><ins>+ control.container.on( 'mouseenter click', function() {
</ins><span class="cx"> control.setting.previewer.send( 'highlight-widget', control.params.widget_id );
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="cx"> // Highlight when the setting is updated
</span><del>- control.setting.bind( function () {
</del><ins>+ control.setting.bind( function() {
</ins><span class="cx"> control.setting.previewer.send( 'highlight-widget', control.params.widget_id );
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="cx"> // Highlight when the widget form is expanded
</span><del>- control.container.on( 'expand', function () {
</del><ins>+ control.container.on( 'expand', function() {
</ins><span class="cx"> control.scrollPreviewWidgetIntoView();
</span><span class="cx"> } );
</span><span class="cx"> },
</span><span class="lines">@@ -934,7 +456,7 @@
</span><span class="cx"> /**
</span><span class="cx"> * Set up event handlers for widget updating
</span><span class="cx"> */
</span><del>- _setupUpdateUI: function () {
</del><ins>+ _setupUpdateUI: function() {
</ins><span class="cx"> var control = this,
</span><span class="cx"> widget_root,
</span><span class="cx"> widget_content,
</span><span class="lines">@@ -947,15 +469,15 @@
</span><span class="cx">
</span><span class="cx"> // Configure update button
</span><span class="cx"> save_btn = control.container.find( '.widget-control-save' );
</span><del>- save_btn.val( self.i18n.save_btn_label );
- save_btn.attr( 'title', self.i18n.save_btn_tooltip );
</del><ins>+ save_btn.val( l10n.saveBtnLabel );
+ save_btn.attr( 'title', l10n.saveBtnTooltip );
</ins><span class="cx"> save_btn.removeClass( 'button-primary' ).addClass( 'button-secondary' );
</span><span class="cx"> save_btn.on( 'click', function ( e ) {
</span><span class="cx"> e.preventDefault();
</span><span class="cx"> control.updateWidget( { disable_form: true } );
</span><span class="cx"> } );
</span><span class="cx">
</span><del>- update_widget_debounced = _.debounce( function () {
</del><ins>+ update_widget_debounced = _.debounce( function() {
</ins><span class="cx"> // @todo For compatibility with other plugins, should we trigger a click event? What about form submit event?
</span><span class="cx"> control.updateWidget();
</span><span class="cx"> }, 250 );
</span><span class="lines">@@ -980,22 +502,22 @@
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="cx"> // Remove loading indicators when the setting is saved and the preview updates
</span><del>- control.setting.previewer.channel.bind( 'synced', function () {
</del><ins>+ control.setting.previewer.channel.bind( 'synced', function() {
</ins><span class="cx"> control.container.removeClass( 'previewer-loading' );
</span><span class="cx"> } );
</span><del>- self.previewer.bind( 'widget-updated', function ( updated_widget_id ) {
</del><ins>+ api.Widgets.Previewer.bind( 'widget-updated', function ( updated_widget_id ) {
</ins><span class="cx"> if ( updated_widget_id === control.params.widget_id ) {
</span><span class="cx"> control.container.removeClass( 'previewer-loading' );
</span><span class="cx"> }
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="cx"> // Update widget control to indicate whether it is currently rendered (cf. Widget Visibility)
</span><del>- self.previewer.bind( 'rendered-widgets', function ( rendered_widgets ) {
</del><ins>+ api.Widgets.Previewer.bind( 'rendered-widgets', function ( rendered_widgets ) {
</ins><span class="cx"> var is_rendered = !! rendered_widgets[control.params.widget_id];
</span><span class="cx"> control.container.toggleClass( 'widget-rendered', is_rendered );
</span><span class="cx"> } );
</span><span class="cx">
</span><del>- form_update_event_handler = builtin_form_sync_handlers[ control.params.widget_id_base ];
</del><ins>+ form_update_event_handler = api.Widgets.formSyncHandlers[ control.params.widget_id_base ];
</ins><span class="cx"> if ( form_update_event_handler ) {
</span><span class="cx"> $( document ).on( 'widget-synced', function ( e, widget_el ) {
</span><span class="cx"> if ( widget_root.is( widget_el ) ) {
</span><span class="lines">@@ -1008,7 +530,7 @@
</span><span class="cx"> /**
</span><span class="cx"> * Set up event handlers for widget removal
</span><span class="cx"> */
</span><del>- _setupRemoveUI: function () {
</del><ins>+ _setupRemoveUI: function() {
</ins><span class="cx"> var control = this,
</span><span class="cx"> remove_btn,
</span><span class="cx"> replace_delete_with_remove;
</span><span class="lines">@@ -1030,7 +552,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> control.container.slideUp( function() {
</span><del>- var sidebars_widgets_control = self.getSidebarWidgetControlContainingWidget( control.params.widget_id ),
</del><ins>+ var sidebars_widgets_control = api.Widgets.getSidebarWidgetControlContainingWidget( control.params.widget_id ),
</ins><span class="cx"> sidebar_widget_ids,
</span><span class="cx"> i;
</span><span class="cx">
</span><span class="lines">@@ -1048,12 +570,12 @@
</span><span class="cx"> } );
</span><span class="cx"> } );
</span><span class="cx">
</span><del>- replace_delete_with_remove = function () {
- remove_btn.text( self.i18n.remove_btn_label ); // wp_widget_control() outputs the link as "Delete"
- remove_btn.attr( 'title', self.i18n.remove_btn_tooltip );
</del><ins>+ replace_delete_with_remove = function() {
+ remove_btn.text( l10n.removeBtnLabel ); // wp_widget_control() outputs the link as "Delete"
+ remove_btn.attr( 'title', l10n.removeBtnTooltip );
</ins><span class="cx"> };
</span><span class="cx"> if ( control.params.is_new ) {
</span><del>- wp.customize.bind( 'saved', replace_delete_with_remove );
</del><ins>+ api.bind( 'saved', replace_delete_with_remove );
</ins><span class="cx"> } else {
</span><span class="cx"> replace_delete_with_remove();
</span><span class="cx"> }
</span><span class="lines">@@ -1119,11 +641,11 @@
</span><span class="cx"> /**
</span><span class="cx"> * @return {wp.customize.controlConstructor.sidebar_widgets[]}
</span><span class="cx"> */
</span><del>- getSidebarWidgetsControl: function () {
</del><ins>+ getSidebarWidgetsControl: function() {
</ins><span class="cx"> var control = this, setting_id, sidebar_widgets_control;
</span><span class="cx">
</span><span class="cx"> setting_id = 'sidebars_widgets[' + control.params.sidebar_id + ']';
</span><del>- sidebar_widgets_control = customize.control( setting_id );
</del><ins>+ sidebar_widgets_control = api.control( setting_id );
</ins><span class="cx"> if ( ! sidebar_widgets_control ) {
</span><span class="cx"> throw new Error( 'Unable to locate sidebar_widgets control for ' + control.params.sidebar_id );
</span><span class="cx"> }
</span><span class="lines">@@ -1173,7 +695,7 @@
</span><span class="cx">
</span><span class="cx"> control.container.addClass( 'widget-form-loading' );
</span><span class="cx"> control.container.addClass( 'previewer-loading' );
</span><del>- processing = wp.customize.state( 'processing' );
</del><ins>+ processing = api.state( 'processing' );
</ins><span class="cx"> processing( processing() + 1 );
</span><span class="cx">
</span><span class="cx"> if ( ! control.live_update_mode ) {
</span><span class="lines">@@ -1183,7 +705,7 @@
</span><span class="cx"> params = {};
</span><span class="cx"> params.action = 'update-widget';
</span><span class="cx"> params.wp_customize = 'on';
</span><del>- params.nonce = self.nonce;
</del><ins>+ params.nonce = api.Widgets.data.nonce;
</ins><span class="cx">
</span><span class="cx"> data = $.param( params );
</span><span class="cx"> inputs = control._getInputs( widget_content );
</span><span class="lines">@@ -1191,7 +713,7 @@
</span><span class="cx"> // Store the value we're submitting in data so that when the response comes back,
</span><span class="cx"> // we know if it got sanitized; if there is no difference in the sanitized value,
</span><span class="cx"> // then we do not need to touch the UI and mess up the user's ongoing editing.
</span><del>- inputs.each( function () {
</del><ins>+ inputs.each( function() {
</ins><span class="cx"> var input = $( this ),
</span><span class="cx"> property = control._getInputStatePropertyName( this );
</span><span class="cx"> input.data( 'state' + update_number, input.prop( property ) );
</span><span class="lines">@@ -1213,17 +735,17 @@
</span><span class="cx">
</span><span class="cx"> // Check if the user is logged out.
</span><span class="cx"> if ( '0' === r ) {
</span><del>- self.previewer.preview.iframe.hide();
- self.previewer.login().done( function() {
</del><ins>+ api.Widgets.Previewer.preview.iframe.hide();
+ api.Widgets.Previewer.login().done( function() {
</ins><span class="cx"> control.updateWidget( args );
</span><del>- self.previewer.preview.iframe.show();
</del><ins>+ api.Widgets.Previewer.preview.iframe.show();
</ins><span class="cx"> } );
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Check for cheaters.
</span><span class="cx"> if ( '-1' === r ) {
</span><del>- self.previewer.cheatin();
</del><ins>+ api.Widgets.Previewer.cheatin();
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1294,7 +816,7 @@
</span><span class="cx"> complete_callback.call( control, null, { no_change: ! is_changed, ajax_finished: true } );
</span><span class="cx"> }
</span><span class="cx"> } else {
</span><del>- message = self.i18n.error;
</del><ins>+ message = l10n.error;
</ins><span class="cx"> if ( r.data && r.data.message ) {
</span><span class="cx"> message = r.data.message;
</span><span class="cx"> }
</span><span class="lines">@@ -1310,9 +832,9 @@
</span><span class="cx"> complete_callback.call( control, textStatus );
</span><span class="cx"> }
</span><span class="cx"> } );
</span><del>- jqxhr.always( function () {
</del><ins>+ jqxhr.always( function() {
</ins><span class="cx"> control.container.removeClass( 'widget-form-loading' );
</span><del>- inputs.each( function () {
</del><ins>+ inputs.each( function() {
</ins><span class="cx"> $( this ).removeData( 'state' + update_number );
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="lines">@@ -1324,7 +846,7 @@
</span><span class="cx"> * Expand the accordion section containing a control
</span><span class="cx"> * @todo it would be nice if accordion had a proper API instead of having to trigger UI events on its elements
</span><span class="cx"> */
</span><del>- expandControlSection: function () {
</del><ins>+ expandControlSection: function() {
</ins><span class="cx"> var section = this.container.closest( '.accordion-section' );
</span><span class="cx"> if ( ! section.hasClass( 'open' ) ) {
</span><span class="cx"> section.find( '.accordion-section-title:first' ).trigger( 'click' );
</span><span class="lines">@@ -1334,14 +856,14 @@
</span><span class="cx"> /**
</span><span class="cx"> * Expand the widget form control
</span><span class="cx"> */
</span><del>- expandForm: function () {
</del><ins>+ expandForm: function() {
</ins><span class="cx"> this.toggleForm( true );
</span><span class="cx"> },
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * Collapse the widget form control
</span><span class="cx"> */
</span><del>- collapseForm: function () {
</del><ins>+ collapseForm: function() {
</ins><span class="cx"> this.toggleForm( false );
</span><span class="cx"> },
</span><span class="cx">
</span><span class="lines">@@ -1366,13 +888,13 @@
</span><span class="cx">
</span><span class="cx"> if ( do_expand ) {
</span><span class="cx"> // Close all other widget controls before expanding this one
</span><del>- wp.customize.control.each( function ( other_control ) {
</del><ins>+ api.control.each( function ( other_control ) {
</ins><span class="cx"> if ( control.params.type === other_control.params.type && control !== other_control ) {
</span><span class="cx"> other_control.collapseForm();
</span><span class="cx"> }
</span><span class="cx"> } );
</span><span class="cx">
</span><del>- complete = function () {
</del><ins>+ complete = function() {
</ins><span class="cx"> control.container.removeClass( 'expanding' );
</span><span class="cx"> control.container.addClass( 'expanded' );
</span><span class="cx"> control.container.trigger( 'expanded' );
</span><span class="lines">@@ -1387,7 +909,7 @@
</span><span class="cx"> } else {
</span><span class="cx"> control.container.trigger( 'collapse' );
</span><span class="cx"> control.container.addClass( 'collapsing' );
</span><del>- complete = function () {
</del><ins>+ complete = function() {
</ins><span class="cx"> control.container.removeClass( 'collapsing' );
</span><span class="cx"> control.container.removeClass( 'expanded' );
</span><span class="cx"> control.container.trigger( 'collapsed' );
</span><span class="lines">@@ -1407,7 +929,7 @@
</span><span class="cx"> * Expand the containing sidebar section, expand the form, and focus on
</span><span class="cx"> * the first input in the control
</span><span class="cx"> */
</span><del>- focus: function () {
</del><ins>+ focus: function() {
</ins><span class="cx"> var control = this;
</span><span class="cx"> control.expandControlSection();
</span><span class="cx"> control.expandForm();
</span><span class="lines">@@ -1420,7 +942,7 @@
</span><span class="cx"> * @throws Error
</span><span class="cx"> * @returns {Number}
</span><span class="cx"> */
</span><del>- getWidgetSidebarPosition: function () {
</del><ins>+ getWidgetSidebarPosition: function() {
</ins><span class="cx"> var control = this,
</span><span class="cx"> sidebar_widget_ids,
</span><span class="cx"> position;
</span><span class="lines">@@ -1436,14 +958,14 @@
</span><span class="cx"> /**
</span><span class="cx"> * Move widget up one in the sidebar
</span><span class="cx"> */
</span><del>- moveUp: function () {
</del><ins>+ moveUp: function() {
</ins><span class="cx"> this._moveWidgetByOne( -1 );
</span><span class="cx"> },
</span><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * Move widget up one in the sidebar
</span><span class="cx"> */
</span><del>- moveDown: function () {
</del><ins>+ moveDown: function() {
</ins><span class="cx"> this._moveWidgetByOne( 1 );
</span><span class="cx"> },
</span><span class="cx">
</span><span class="lines">@@ -1484,7 +1006,7 @@
</span><span class="cx"> if ( toggle ) {
</span><span class="cx"> // reset the selected sidebar
</span><span class="cx"> move_widget_area.find( '.selected' ).removeClass( 'selected' );
</span><del>- move_widget_area.find( 'li' ).filter( function () {
</del><ins>+ move_widget_area.find( 'li' ).filter( function() {
</ins><span class="cx"> return $( this ).data( 'id' ) === control.params.sidebar_id;
</span><span class="cx"> } ).addClass( 'selected' );
</span><span class="cx"> control.container.find( '.move-widget-btn' ).prop( 'disabled', true );
</span><span class="lines">@@ -1495,7 +1017,7 @@
</span><span class="cx"> /**
</span><span class="cx"> * Inside of the customizer preview, scroll the widget into view
</span><span class="cx"> */
</span><del>- scrollPreviewWidgetIntoView: function () {
</del><ins>+ scrollPreviewWidgetIntoView: function() {
</ins><span class="cx"> // @todo scrollIntoView() provides a robust but very poor experience. Animation is needed. See https://github.com/x-team/wp-widget-customizer/issues/16
</span><span class="cx"> },
</span><span class="cx">
</span><span class="lines">@@ -1513,7 +1035,7 @@
</span><span class="cx">
</span><span class="cx"> $( '.widget-customizer-highlighted' ).removeClass( 'widget-customizer-highlighted' );
</span><span class="cx"> target_element.addClass( 'widget-customizer-highlighted' );
</span><del>- setTimeout( function () {
</del><ins>+ setTimeout( function() {
</ins><span class="cx"> target_element.removeClass( 'widget-customizer-highlighted' );
</span><span class="cx"> }, 500 );
</span><span class="cx"> }
</span><span class="lines">@@ -1521,12 +1043,467 @@
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="cx"> /**
</span><ins>+ * Sidebar Widgets control
+ * Note that 'sidebar_widgets' must match the WP_Widget_Area_Customize_Control::$type
+ */
+ api.Widgets.SidebarControl = api.Control.extend({
+ /**
+ * Set up the control
+ */
+ ready: function() {
+ var control = this;
+ control.control_section = control.container.closest( '.control-section' );
+ control.section_content = control.container.closest( '.accordion-section-content' );
+ control._setupModel();
+ control._setupSortable();
+ control._setupAddition();
+ control._applyCardinalOrderClassNames();
+ },
+
+ /**
+ * Update ordering of widget control forms when the setting is updated
+ */
+ _setupModel: function() {
+ var control = this,
+ registered_sidebar = api.Widgets.registeredSidebars.get( control.params.sidebar_id );
+
+ control.setting.bind( function( new_widget_ids, old_widget_ids ) {
+ var widget_form_controls,
+ sidebar_widgets_add_control,
+ final_control_containers,
+ 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 ) {
+ 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 ) {
+ var widget_form_control = api.Widgets.getWidgetFormControlForWidget( widget_id );
+ if ( ! widget_form_control ) {
+ widget_form_control = control.addWidget( widget_id );
+ }
+ return widget_form_control;
+ } );
+
+ // Sort widget controls to their new positions
+ 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 ) {
+ return 0;
+ }
+ return a_index < b_index ? -1 : 1;
+ } );
+
+ sidebar_widgets_add_control = control.section_content.find( '.customize-control-sidebar_widgets' );
+
+ // Append the controls to put them in the right order
+ final_control_containers = _( widget_form_controls ).map( function( widget_form_controls ) {
+ return widget_form_controls.container[0];
+ } );
+
+ // Re-sort widget form controls (including widgets form other sidebars newly moved here)
+ sidebar_widgets_add_control.before( final_control_containers );
+ 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_control.params.sidebar_id = control.params.sidebar_id;
+ } );
+
+ // Cleanup after widget removal
+ _( 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() {
+ var is_present_in_another_sidebar = false,
+ removed_control,
+ was_dragged_to_another_sidebar,
+ inactive_widgets,
+ removed_id_base,
+ widget;
+
+ // Check if the widget is in another sidebar
+ 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;
+ }
+ var other_sidebar_widgets = other_setting(), i;
+
+ i = _.indexOf( other_sidebar_widgets, removed_widget_id );
+ if ( -1 !== i ) {
+ is_present_in_another_sidebar = true;
+ }
+ } );
+
+ // If the widget is present in another sidebar, abort!
+ if ( is_present_in_another_sidebar ) {
+ return;
+ }
+
+ removed_control = api.Widgets.getWidgetFormControlForWidget( removed_widget_id );
+
+ // Detect if widget control was dragged to another sidebar
+ was_dragged_to_another_sidebar = (
+ removed_control &&
+ $.contains( document, removed_control.container[0] ) &&
+ ! $.contains( control.section_content[0], removed_control.container[0] )
+ );
+
+ // Delete any widget form controls for removed widgets
+ if ( removed_control && ! was_dragged_to_another_sidebar ) {
+ api.control.remove( removed_control.id );
+ removed_control.container.remove();
+ }
+
+ // Move widget to inactive widgets sidebar (move it to trash) if has been previously saved
+ // This prevents the inactive widgets sidebar from overflowing with throwaway widgets
+ if ( api.Widgets.savedWidgetIds[removed_widget_id] ) {
+ inactive_widgets = api.value( 'sidebars_widgets[wp_inactive_widgets]' )().slice();
+ inactive_widgets.push( removed_widget_id );
+ api.value( 'sidebars_widgets[wp_inactive_widgets]' )( _( inactive_widgets ).unique() );
+ }
+
+ // Make old single widget available for adding again
+ removed_id_base = parse_widget_id( removed_widget_id ).id_base;
+ widget = api.Widgets.availableWidgets.findWhere( { id_base: removed_id_base } );
+ if ( widget && ! widget.get( 'is_multi' ) ) {
+ widget.set( 'is_disabled', false );
+ }
+ } );
+
+ } );
+ } );
+
+ // Update the model with whether or not the sidebar is rendered
+ 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 ( ) {
+ var section_selector = '#accordion-section-sidebar-widgets-' + this.get( 'id' ), section;
+ section = $( section_selector );
+ if ( this.get( 'is_rendered' ) ) {
+ section.stop().slideDown( function() {
+ $( this ).css( 'height', 'auto' ); // so that the .accordion-section-content won't overflow
+ } );
+ } else {
+ // Make sure that hidden sections get closed first
+ if ( section.hasClass( 'open' ) ) {
+ // it would be nice if accordionSwitch() in accordion.js was public
+ section.find( '.accordion-section-title' ).trigger( 'click' );
+ }
+ section.stop().slideUp();
+ }
+ } );
+ },
+
+ /**
+ * Allow widgets in sidebar to be re-ordered, and for the order to be previewed
+ */
+ _setupSortable: function() {
+ var control = this;
+ control.is_reordering = false;
+
+ /**
+ * Update widget order setting when controls are re-ordered
+ */
+ control.section_content.sortable( {
+ items: '> .customize-control-widget_form',
+ handle: '.widget-top',
+ axis: 'y',
+ 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 ) {
+ return $( '#' + widget_container_id ).find( ':input[name=widget-id]' ).val();
+ } );
+ control.setting( widget_ids );
+ }
+ } );
+
+ /**
+ * Expand other customizer sidebar section when dragging a control widget over it,
+ * allowing the control to be dropped into another section
+ */
+ control.control_section.find( '.accordion-section-title' ).droppable( {
+ accept: '.customize-control-widget_form',
+ over: function() {
+ if ( ! control.control_section.hasClass( 'open' ) ) {
+ control.control_section.addClass( 'open' );
+ control.section_content.toggle( false ).slideToggle( 150, function() {
+ control.section_content.sortable( 'refreshPositions' );
+ } );
+ }
+ }
+ } );
+
+ /**
+ * Keyboard-accessible reordering
+ */
+ control.container.find( '.reorder-toggle' ).on( 'click keydown', function( event ) {
+ if ( event.type === 'keydown' && ! ( event.which === 13 || event.which === 32 ) ) { // Enter or Spacebar
+ return;
+ }
+
+ control.toggleReordering( ! control.is_reordering );
+ } );
+ },
+
+ /**
+ * Set up UI for adding a new widget
+ */
+ _setupAddition: function() {
+ var control = this;
+
+ control.container.find( '.add-new-widget' ).on( 'click keydown', function( event ) {
+ if ( event.type === 'keydown' && ! ( event.which === 13 || event.which === 32 ) ) { // Enter or Spacebar
+ return;
+ }
+
+ if ( control.section_content.hasClass( 'reordering' ) ) {
+ return;
+ }
+
+ // @todo Use an control.is_adding state
+ if ( ! $( 'body' ).hasClass( 'adding-widget' ) ) {
+ api.Widgets.availableWidgetsPanel.open( control );
+ } else {
+ api.Widgets.availableWidgetsPanel.close();
+ }
+ } );
+ },
+
+ /**
+ * Add classes to the widget_form controls to assist with styling
+ */
+ _applyCardinalOrderClassNames: function() {
+ var control = this;
+ control.section_content.find( '.customize-control-widget_form' )
+ .removeClass( 'first-widget' )
+ .removeClass( 'last-widget' )
+ .find( '.move-widget-down, .move-widget-up' ).prop( 'tabIndex', 0 );
+
+ control.section_content.find( '.customize-control-widget_form:first' )
+ .addClass( 'first-widget' )
+ .find( '.move-widget-up' ).prop( 'tabIndex', -1 );
+ control.section_content.find( '.customize-control-widget_form:last' )
+ .addClass( 'last-widget' )
+ .find( '.move-widget-down' ).prop( 'tabIndex', -1 );
+ },
+
+
+ /***********************************************************************
+ * Begin public API methods
+ **********************************************************************/
+
+ /**
+ * Enable/disable the reordering UI
+ *
+ * @param {Boolean} toggle to enable/disable reordering
+ */
+ toggleReordering: function ( toggle ) {
+ var control = this;
+ toggle = Boolean( toggle );
+ if ( toggle === control.section_content.hasClass( 'reordering' ) ) {
+ return;
+ }
+
+ control.is_reordering = toggle;
+ control.section_content.toggleClass( 'reordering', toggle );
+
+ if ( toggle ) {
+ _( control.getWidgetFormControls() ).each( function ( form_control ) {
+ form_control.collapseForm();
+ } );
+ }
+ },
+
+ /**
+ * @return {wp.customize.controlConstructor.widget_form[]}
+ */
+ getWidgetFormControls: function() {
+ var control = this, form_controls;
+
+ form_controls = _( control.setting() ).map( function ( widget_id ) {
+ var setting_id = widget_id_to_setting_id( widget_id ),
+ form_control = api.control( setting_id );
+
+ if ( ! form_control ) {
+ throw new Error( 'Unable to find widget_form control for ' + widget_id );
+ }
+ return form_control;
+ } );
+ return form_controls;
+ },
+
+ /**
+ * @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 ) {
+ var control = this,
+ control_html,
+ widget_el,
+ customize_control_type = 'widget_form',
+ customize_control,
+ parsed_widget_id = parse_widget_id( widget_id ),
+ widget_number = parsed_widget_id.number,
+ widget_id_base = parsed_widget_id.id_base,
+ widget = api.Widgets.availableWidgets.findWhere( {id_base: widget_id_base} ),
+ setting_id,
+ is_existing_widget,
+ Constructor,
+ widget_form_control,
+ sidebar_widgets,
+ setting_args;
+
+ if ( ! widget ) {
+ throw new Error( 'Widget unexpectedly not found.' );
+ }
+ if ( widget_number && ! widget.get( 'is_multi' ) ) {
+ throw new Error( 'Did not expect a widget number to be supplied for a non-multi widget' );
+ }
+
+ // Set up new multi widget
+ if ( widget.get( 'is_multi' ) && ! widget_number ) {
+ widget.set( 'multi_number', widget.get( 'multi_number' ) + 1 );
+ widget_number = widget.get( 'multi_number' );
+ }
+
+ control_html = $( '#widget-tpl-' + widget.get( 'id' ) ).html();
+ if ( widget.get( 'is_multi' ) ) {
+ control_html = control_html.replace( /<[^<>]+>/g, function ( m ) {
+ return m.replace( /__i__|%i%/g, widget_number );
+ } );
+ } else {
+ widget.set( 'is_disabled', true ); // Prevent single widget from being added again now
+ }
+ widget_el = $( control_html );
+
+ customize_control = $( '<li></li>' );
+ customize_control.addClass( 'customize-control' );
+ customize_control.addClass( 'customize-control-' + customize_control_type );
+ customize_control.append( widget_el );
+ customize_control.find( '> .widget-icon' ).remove();
+ if ( widget.get( 'is_multi' ) ) {
+ customize_control.find( 'input[name="widget_number"]' ).val( widget_number );
+ customize_control.find( 'input[name="multi_number"]' ).val( widget_number );
+ }
+ widget_id = customize_control.find( '[name="widget-id"]' ).val();
+ customize_control.hide(); // to be slid-down below
+
+ setting_id = 'widget_' + widget.get( 'id_base' );
+ if ( widget.get( 'is_multi' ) ) {
+ setting_id += '[' + widget_number + ']';
+ }
+ customize_control.attr( 'id', 'customize-control-' + setting_id.replace( /\]/g, '' ).replace( /\[/g, '-' ) );
+
+ control.container.after( customize_control );
+
+ // Only create setting if it doesn't already exist (if we're adding a pre-existing inactive widget)
+ is_existing_widget = api.has( setting_id );
+ if ( ! is_existing_widget ) {
+ setting_args = {
+ transport: 'refresh',
+ previewer: control.setting.previewer
+ };
+ api.create( setting_id, setting_id, {}, setting_args );
+ }
+
+ Constructor = api.controlConstructor[customize_control_type];
+ widget_form_control = new Constructor( setting_id, {
+ params: {
+ settings: {
+ 'default': setting_id
+ },
+ sidebar_id: control.params.sidebar_id,
+ widget_id: widget_id,
+ widget_id_base: widget.get( 'id_base' ),
+ type: customize_control_type,
+ is_new: ! is_existing_widget,
+ width: widget.get( 'width' ),
+ height: widget.get( 'height' ),
+ is_wide: widget.get( 'is_wide' )
+ },
+ previewer: control.setting.previewer
+ } );
+ api.control.add( setting_id, widget_form_control );
+
+ // Make sure widget is removed from the other sidebars
+ api.each( function ( other_setting ) {
+ if ( other_setting.id === control.setting.id ) {
+ return;
+ }
+ if ( 0 !== other_setting.id.indexOf( 'sidebars_widgets[' ) ) {
+ return;
+ }
+ var other_sidebar_widgets = other_setting().slice(), i;
+ i = _.indexOf( other_sidebar_widgets, widget_id );
+ if ( -1 !== i ) {
+ other_sidebar_widgets.splice( i );
+ other_setting( other_sidebar_widgets );
+ }
+ } );
+
+ // Add widget to this sidebar
+ sidebar_widgets = control.setting().slice();
+ if ( -1 === _.indexOf( sidebar_widgets, widget_id ) ) {
+ sidebar_widgets.push( widget_id );
+ control.setting( sidebar_widgets );
+ }
+
+ customize_control.slideDown( function() {
+ if ( is_existing_widget ) {
+ widget_form_control.expandForm();
+ widget_form_control.updateWidget( {
+ instance: widget_form_control.setting(),
+ complete: function ( error ) {
+ if ( error ) {
+ throw error;
+ }
+ widget_form_control.focus();
+ }
+ } );
+ } else {
+ widget_form_control.focus();
+ }
+ } );
+
+ $( document ).trigger( 'widget-added', [ widget_el ] );
+
+ return widget_form_control;
+ }
+
+ } );
+
+ $.extend( api.controlConstructor, {
+ widget_form: api.Widgets.WidgetControl,
+ sidebar_widgets: api.Widgets.SidebarControl
+ });
+
+ api.bind( 'ready', function() {
+ // Set up the widgets panel
+ api.Widgets.availableWidgetsPanel.setup();
+
+ // Highlight widget control
+ api.Widgets.Previewer.bind( 'highlight-widget-control', api.Widgets.highlightWidgetFormControl );
+
+ // Open and focus widget control
+ api.Widgets.Previewer.bind( 'focus-widget-control', api.Widgets.focusWidgetFormControl );
+ } );
+
+ /**
</ins><span class="cx"> * Capture the instance of the Previewer since it is private
</span><span class="cx"> */
</span><del>- OldPreviewer = wp.customize.Previewer;
- wp.customize.Previewer = OldPreviewer.extend( {
</del><ins>+ OldPreviewer = api.Previewer;
+ api.Previewer = OldPreviewer.extend({
</ins><span class="cx"> initialize: function( params, options ) {
</span><del>- self.previewer = this;
</del><ins>+ api.Widgets.Previewer = this;
</ins><span class="cx"> OldPreviewer.prototype.initialize.call( this, params, options );
</span><span class="cx"> this.bind( 'refresh', this.refresh );
</span><span class="cx"> }
</span><span class="lines">@@ -1537,8 +1514,8 @@
</span><span class="cx"> *
</span><span class="cx"> * @param {string} widgetId
</span><span class="cx"> */
</span><del>- self.highlightWidgetFormControl = function( widgetId ) {
- var control = self.getWidgetFormControlForWidget( widgetId );
</del><ins>+ api.Widgets.highlightWidgetFormControl = function( widgetId ) {
+ var control = api.Widgets.getWidgetFormControlForWidget( widgetId );
</ins><span class="cx">
</span><span class="cx"> if ( control ) {
</span><span class="cx"> control.highlightSectionAndControl();
</span><span class="lines">@@ -1550,8 +1527,8 @@
</span><span class="cx"> *
</span><span class="cx"> * @param {string} widgetId
</span><span class="cx"> */
</span><del>- self.focusWidgetFormControl = function( widgetId ) {
- var control = self.getWidgetFormControlForWidget( widgetId );
</del><ins>+ api.Widgets.focusWidgetFormControl = function( widgetId ) {
+ var control = api.Widgets.getWidgetFormControlForWidget( widgetId );
</ins><span class="cx">
</span><span class="cx"> if ( control ) {
</span><span class="cx"> control.focus();
</span><span class="lines">@@ -1563,14 +1540,15 @@
</span><span class="cx"> * @param {string} widget_id
</span><span class="cx"> * @return {object|null}
</span><span class="cx"> */
</span><del>- self.getSidebarWidgetControlContainingWidget = function ( widget_id ) {
</del><ins>+ api.Widgets.getSidebarWidgetControlContainingWidget = function ( widget_id ) {
</ins><span class="cx"> var found_control = null;
</span><span class="cx"> // @todo this can use widget_id_to_setting_id(), then pass into wp.customize.control( x ).getSidebarWidgetsControl()
</span><del>- wp.customize.control.each( function ( control ) {
</del><ins>+ api.control.each( function ( control ) {
</ins><span class="cx"> if ( control.params.type === 'sidebar_widgets' && -1 !== _.indexOf( control.setting(), widget_id ) ) {
</span><span class="cx"> found_control = control;
</span><span class="cx"> }
</span><span class="cx"> } );
</span><ins>+
</ins><span class="cx"> return found_control;
</span><span class="cx"> };
</span><span class="cx">
</span><span class="lines">@@ -1579,28 +1557,22 @@
</span><span class="cx"> * @param {string} widget_id
</span><span class="cx"> * @return {object|null}
</span><span class="cx"> */
</span><del>- self.getWidgetFormControlForWidget = function ( widget_id ) {
</del><ins>+ api.Widgets.getWidgetFormControlForWidget = function ( widget_id ) {
</ins><span class="cx"> var found_control = null;
</span><span class="cx"> // @todo We can just use widget_id_to_setting_id() here
</span><del>- wp.customize.control.each( function ( control ) {
</del><ins>+ api.control.each( function ( control ) {
</ins><span class="cx"> if ( control.params.type === 'widget_form' && control.params.widget_id === widget_id ) {
</span><span class="cx"> found_control = control;
</span><span class="cx"> }
</span><span class="cx"> } );
</span><ins>+
</ins><span class="cx"> return found_control;
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> /**
</span><del>- * @returns {Window}
- */
- self.getPreviewWindow = function (){
- return $( '#customize-preview' ).find( 'iframe' ).prop( 'contentWindow' );
- };
-
- /**
</del><span class="cx"> * Available Widgets Panel
</span><span class="cx"> */
</span><del>- self.availableWidgetsPanel = {
</del><ins>+ api.Widgets.availableWidgetsPanel = {
</ins><span class="cx"> active_sidebar_widgets_control: null,
</span><span class="cx"> selected_widget_tpl: null,
</span><span class="cx"> container: null,
</span><span class="lines">@@ -1609,13 +1581,13 @@
</span><span class="cx"> /**
</span><span class="cx"> * Set up event listeners
</span><span class="cx"> */
</span><del>- setup: function () {
</del><ins>+ setup: function() {
</ins><span class="cx"> var panel = this;
</span><span class="cx">
</span><span class="cx"> panel.container = $( '#available-widgets' );
</span><span class="cx"> panel.filter_input = $( '#available-widgets-filter' ).find( 'input' );
</span><span class="cx">
</span><del>- self.available_widgets.on( 'change update', panel.update_available_widgets_list );
</del><ins>+ api.Widgets.availableWidgets.on( 'change update', panel.update_available_widgets_list );
</ins><span class="cx"> panel.update_available_widgets_list();
</span><span class="cx">
</span><span class="cx"> // If the available widgets panel is open and the customize controls are
</span><span class="lines">@@ -1629,7 +1601,7 @@
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="cx"> // Close the panel if the URL in the preview changes
</span><del>- self.previewer.bind( 'url', function () {
</del><ins>+ api.Widgets.Previewer.bind( 'url', function() {
</ins><span class="cx"> panel.close();
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="lines">@@ -1647,7 +1619,7 @@
</span><span class="cx"> panel.filter_input.on( 'input keyup change', function( event ) {
</span><span class="cx"> var first_visible_widget;
</span><span class="cx">
</span><del>- self.available_widgets.doSearch( event.target.value );
</del><ins>+ api.Widgets.availableWidgets.doSearch( event.target.value );
</ins><span class="cx">
</span><span class="cx"> // Remove a widget from being selected if it is no longer visible
</span><span class="cx"> if ( panel.selected_widget_tpl && ! panel.selected_widget_tpl.is( ':visible' ) ) {
</span><span class="lines">@@ -1671,7 +1643,7 @@
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="cx"> // Select a widget when it is focused on
</span><del>- panel.container.find( ' > .widget-tpl' ).on( 'focus', function () {
</del><ins>+ panel.container.find( ' > .widget-tpl' ).on( 'focus', function() {
</ins><span class="cx"> panel.select( this );
</span><span class="cx"> } );
</span><span class="cx">
</span><span class="lines">@@ -1725,13 +1697,13 @@
</span><span class="cx"> * Updates widgets list.
</span><span class="cx"> */
</span><span class="cx"> update_available_widgets_list: function() {
</span><del>- var panel = self.availableWidgetsPanel;
</del><ins>+ var panel = api.Widgets.availableWidgetsPanel;
</ins><span class="cx">
</span><span class="cx"> // First hide all widgets...
</span><span class="cx"> panel.container.find( '.widget-tpl' ).hide();
</span><span class="cx">
</span><span class="cx"> // ..and then show only available widgets which could be filtered
</span><del>- self.available_widgets.each( function ( widget ) {
</del><ins>+ api.Widgets.availableWidgets.each( function ( widget ) {
</ins><span class="cx"> var widget_tpl = $( '#widget-tpl-' + widget.id );
</span><span class="cx"> widget_tpl.toggle( ! widget.get( 'is_disabled' ) );
</span><span class="cx"> if ( widget.get( 'is_disabled' ) && widget_tpl.is( panel.selected_widget_tpl ) ) {
</span><span class="lines">@@ -1761,7 +1733,7 @@
</span><span class="cx"> panel.select( widget_tpl );
</span><span class="cx">
</span><span class="cx"> widget_id = $( panel.selected_widget_tpl ).data( 'widget-id' );
</span><del>- widget = self.available_widgets.findWhere( {id: widget_id} );
</del><ins>+ widget = api.Widgets.availableWidgets.findWhere( {id: widget_id} );
</ins><span class="cx"> if ( ! widget ) {
</span><span class="cx"> throw new Error( 'Widget unexpectedly not found.' );
</span><span class="cx"> }
</span><span class="lines">@@ -1785,7 +1757,7 @@
</span><span class="cx">
</span><span class="cx"> $( 'body' ).addClass( 'adding-widget' );
</span><span class="cx"> panel.container.find( '.widget-tpl' ).removeClass( 'selected' );
</span><del>- self.available_widgets.doSearch( '' );
</del><ins>+ api.Widgets.availableWidgets.doSearch( '' );
</ins><span class="cx"> panel.filter_input.focus();
</span><span class="cx"> },
</span><span class="cx">
</span><span class="lines">@@ -1839,5 +1811,4 @@
</span><span class="cx"> return setting_id;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- return self;
-}( jQuery ));
</del><ins>+})( window.wp, jQuery );
</ins></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizecontrolphp"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-includes/class-wp-customize-control.php (27984 => 27985)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-includes/class-wp-customize-control.php 2014-04-07 09:02:06 UTC (rev 27984)
+++ trunk/src/wp-includes/class-wp-customize-control.php 2014-04-07 09:03:18 UTC (rev 27985)
</span><span class="lines">@@ -917,12 +917,12 @@
</span><span class="cx"> public function render_content() {
</span><span class="cx"> ?>
</span><span class="cx"> <span class="button-secondary add-new-widget" tabindex="0">
</span><del>- <?php esc_html_e( 'Add a Widget' ); ?>
</del><ins>+ <?php _e( 'Add a Widget' ); ?>
</ins><span class="cx"> </span>
</span><span class="cx">
</span><span class="cx"> <span class="reorder-toggle" tabindex="0">
</span><del>- <span class="reorder"><?php esc_html_e( 'Reorder' ); ?></span>
- <span class="reorder-done"><?php esc_html_e( 'Done' ); ?></span>
</del><ins>+ <span class="reorder"><?php _ex( 'Reorder', 'Reorder widgets in Customizer' ); ?></span>
+ <span class="reorder-done"><?php _ex( 'Done', 'Cancel reordering widgets in Customizer' ); ?></span>
</ins><span class="cx"> </span>
</span><span class="cx"> <?php
</span><span class="cx"> }
</span><span class="lines">@@ -940,11 +940,10 @@
</span><span class="cx"> public $width;
</span><span class="cx"> public $height;
</span><span class="cx"> public $is_wide = false;
</span><del>- public $is_live_previewable = false;
</del><span class="cx">
</span><span class="cx"> public function to_json() {
</span><span class="cx"> parent::to_json();
</span><del>- $exported_properties = array( 'widget_id', 'widget_id_base', 'sidebar_id', 'width', 'height', 'is_wide', 'is_live_previewable' );
</del><ins>+ $exported_properties = array( 'widget_id', 'widget_id_base', 'sidebar_id', 'width', 'height', 'is_wide' );
</ins><span class="cx"> foreach ( $exported_properties as $key ) {
</span><span class="cx"> $this->json[ $key ] = $this->$key;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizewidgetsphp"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-includes/class-wp-customize-widgets.php (27984 => 27985)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-includes/class-wp-customize-widgets.php 2014-04-07 09:02:06 UTC (rev 27984)
+++ trunk/src/wp-includes/class-wp-customize-widgets.php 2014-04-07 09:03:18 UTC (rev 27985)
</span><span class="lines">@@ -406,8 +406,6 @@
</span><span class="cx"> $setting_id = $this->get_setting_id( $widget_id );
</span><span class="cx"> $id_base = $GLOBALS['wp_registered_widget_controls'][$widget_id]['id_base'];
</span><span class="cx">
</span><del>- assert( false !== is_active_widget( $registered_widget['callback'], $registered_widget['id'], false, false ) );
-
</del><span class="cx"> $control = new WP_Widget_Form_Customize_Control( $this->manager, $setting_id, array(
</span><span class="cx"> 'label' => $registered_widget['name'],
</span><span class="cx"> 'section' => $section_id,
</span><span class="lines">@@ -599,8 +597,8 @@
</span><span class="cx"> $move_widget_area_tpl = str_replace(
</span><span class="cx"> array( '{description}', '{btn}' ),
</span><span class="cx"> array(
</span><del>- ( 'Select an area to move this widget into:' ), // @todo translate
- esc_html_x( 'Move', 'move widget' ),
</del><ins>+ __( 'Select an area to move this widget into:' ),
+ _x( 'Move', 'Move widget' ),
</ins><span class="cx"> ),
</span><span class="cx"> '<div class="move-widget-area">
</span><span class="cx"> <p class="description">{description}</p>
</span><span class="lines">@@ -615,39 +613,34 @@
</span><span class="cx"> </div>'
</span><span class="cx"> );
</span><span class="cx">
</span><del>- /*
- * Why not wp_localize_script? Because we're not localizing,
- * and it forces values into strings.
- */
</del><span class="cx"> global $wp_scripts;
</span><span class="cx">
</span><del>- $exports = array(
- 'nonce' => wp_create_nonce( 'update-widget' ),
- 'registered_sidebars' => array_values( $GLOBALS['wp_registered_sidebars'] ),
- 'registered_widgets' => $GLOBALS['wp_registered_widgets'],
- 'available_widgets' => $available_widgets, // @todo Merge this with registered_widgets
- 'i18n' => array(
- 'save_btn_label' => __( 'Apply' ),
- // @todo translate? do we want these tooltips?
- 'save_btn_tooltip' => ( 'Save and preview changes before publishing them.' ),
- 'remove_btn_label' => __( 'Remove' ),
- 'remove_btn_tooltip' => ( 'Trash widget by moving it to the inactive widgets sidebar.' ),
- 'error' => __( 'An error has occurred. Please reload the page and try again.' ),
</del><ins>+ $settings = array(
+ 'nonce' => wp_create_nonce( 'update-widget' ),
+ 'registeredSidebars' => array_values( $GLOBALS['wp_registered_sidebars'] ),
+ 'registeredWidgets' => $GLOBALS['wp_registered_widgets'],
+ 'availableWidgets' => $available_widgets, // @todo Merge this with registered_widgets
+ 'l10n' => array(
+ 'saveBtnLabel' => __( 'Apply' ),
+ 'saveBtnTooltip' => __( 'Save and preview changes before publishing them.' ),
+ 'removeBtnLabel' => __( 'Remove' ),
+ 'removeBtnTooltip' => __( 'Trash widget by moving it to the inactive widgets sidebar.' ),
+ 'error' => __( 'An error has occurred. Please reload the page and try again.' ),
</ins><span class="cx"> ),
</span><del>- 'tpl' => array(
- 'widget_reorder_nav' => $widget_reorder_nav_tpl,
- 'move_widget_area' => $move_widget_area_tpl,
</del><ins>+ 'tpl' => array(
+ 'widgetReorderNav' => $widget_reorder_nav_tpl,
+ 'moveWidgetArea' => $move_widget_area_tpl,
</ins><span class="cx"> ),
</span><span class="cx"> );
</span><span class="cx">
</span><del>- foreach ( $exports['registered_widgets'] as &$registered_widget ) {
</del><ins>+ foreach ( $settings['registeredWidgets'] as &$registered_widget ) {
</ins><span class="cx"> unset( $registered_widget['callback'] ); // may not be JSON-serializeable
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> $wp_scripts->add_data(
</span><span class="cx"> 'customize-widgets',
</span><span class="cx"> 'data',
</span><del>- sprintf( 'var WidgetCustomizer_exports = %s;', json_encode( $exports ) )
</del><ins>+ sprintf( 'var _wpCustomizeWidgetsSettings = %s;', json_encode( $settings ) )
</ins><span class="cx"> );
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -662,12 +655,12 @@
</span><span class="cx"> <div id="widgets-left"><!-- compatibility with JS which looks for widget templates here -->
</span><span class="cx"> <div id="available-widgets">
</span><span class="cx"> <div id="available-widgets-filter">
</span><del>- <label class="screen-reader-text" for="widgets-search"><?php _e( 'Find Widgets' ); ?></label>
- <input type="search" id="widgets-search" placeholder="<?php esc_attr_e( 'Find widgets…' ) ?>" />
</del><ins>+ <label class="screen-reader-text" for="widgets-search"><?php _e( 'Search Widgets' ); ?></label>
+ <input type="search" id="widgets-search" placeholder="<?php esc_attr_e( 'Search widgets…' ) ?>" />
</ins><span class="cx"> </div>
</span><span class="cx"> <?php foreach ( $this->get_available_widgets() as $available_widget ): ?>
</span><span class="cx"> <div id="widget-tpl-<?php echo esc_attr( $available_widget['id'] ) ?>" data-widget-id="<?php echo esc_attr( $available_widget['id'] ) ?>" class="widget-tpl <?php echo esc_attr( $available_widget['id'] ) ?>" tabindex="0">
</span><del>- <?php echo $available_widget['control_tpl']; // xss ok ?>
</del><ins>+ <?php echo $available_widget['control_tpl']; ?>
</ins><span class="cx"> </div>
</span><span class="cx"> <?php endforeach; ?>
</span><span class="cx"> </div><!-- #available-widgets -->
</span><span class="lines">@@ -826,6 +819,7 @@
</span><span class="cx">
</span><span class="cx"> $available_widgets[] = $available_widget;
</span><span class="cx"> }
</span><ins>+
</ins><span class="cx"> return $available_widgets;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunksrcwpincludesjscustomizepreviewwidgetsjs"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-includes/js/customize-preview-widgets.js (27984 => 27985)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-includes/js/customize-preview-widgets.js 2014-04-07 09:02:06 UTC (rev 27984)
+++ trunk/src/wp-includes/js/customize-preview-widgets.js 2014-04-07 09:03:18 UTC (rev 27985)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-(function( $, wp ){
</del><ins>+(function( wp, $ ){
</ins><span class="cx">
</span><span class="cx"> if ( ! wp || ! wp.customize ) { return; }
</span><span class="cx">
</span><span class="lines">@@ -124,4 +124,4 @@
</span><span class="cx"> api.WidgetCustomizerPreview.init();
</span><span class="cx"> });
</span><span class="cx">
</span><del>-})( jQuery, window.wp );
</del><ins>+})( window.wp, jQuery );
</ins></span></pre>
</div>
</div>
</body>
</html>