Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
diff --git a/class-sidebar-widgets-wp-customize-control.php b/class-sidebar-widgets-wp-customize-control.php
index 0f231c6..ad0ab12 100644
--- a/class-sidebar-widgets-wp-customize-control.php
+++ b/class-sidebar-widgets-wp-customize-control.php
@@ -17,6 +17,10 @@ class Sidebar_Widgets_WP_Customize_Control extends WP_Customize_Control {
public function render_content() {
?>
+ <span class="reorder-toggle" tabindex="0">
+ <span class="reorder"><?php esc_html_e( 'Reorder', 'widget-customizer' ) ?></span>
+ <span class="reorder-done"><?php esc_html_e( 'Done', 'widget-customizer' ) ?></span>
+ </span>
<span class="add-new-widget" tabindex="0">
<b><?php esc_html_e( 'Add a Widget', 'widget-customizer' ) ?></b>
</span>
diff --git a/widget-customizer-preview.js b/widget-customizer-preview.js
index bdb6951..5ee9d57 100644
--- a/widget-customizer-preview.js
+++ b/widget-customizer-preview.js
@@ -4,12 +4,12 @@ var WidgetCustomizerPreview = (function ($) {
'use strict';
var self = {
- rendered_sidebars: {},
+ rendered_sidebars: {}, // @todo Make rendered a property of the Backbone model
sidebars_eligible_for_post_message: {},
- rendered_widgets: {},
+ rendered_widgets: {}, // @todo Make rendered a property of the Backbone model
widgets_eligible_for_post_message: {},
- registered_sidebars: {},
- registered_widgets: {},
+ registered_sidebars: [], // @todo Make a Backbone collection
+ registered_widgets: {}, // @todo Make array, Backbone collection
widget_selectors: [],
render_widget_ajax_action: null,
render_widget_nonce_value: null,
@@ -23,8 +23,8 @@ var WidgetCustomizerPreview = (function ($) {
this.livePreview();
self.preview.bind( 'active', function() {
- self.preview.send( 'rendered-sidebars', self.rendered_sidebars );
- self.preview.send( 'rendered-widgets', self.rendered_widgets );
+ self.preview.send( 'rendered-sidebars', self.rendered_sidebars ); // @todo Only send array of IDs
+ self.preview.send( 'rendered-widgets', self.rendered_widgets ); // @todo Only send array of IDs
} );
},
@@ -32,7 +32,7 @@ var WidgetCustomizerPreview = (function ($) {
* Calculate the selector for the sidebar's widgets based on the registered sidebar's info
*/
buildWidgetSelectors: function () {
- $.each( self.registered_sidebars, function ( id, sidebar ) {
+ $.each( self.registered_sidebars, function ( i, sidebar ) {
var widget_tpl = [
sidebar.before_widget.replace('%1$s', '').replace('%2$s', ''),
sidebar.before_title,
diff --git a/widget-customizer.css b/widget-customizer.css
index 51bd7a3..bc825d6 100644
--- a/widget-customizer.css
+++ b/widget-customizer.css
@@ -105,6 +105,181 @@
}
+/* @todo Merge into Dashicons */
+@font-face {
+ font-family: 'Genericons';
+ src: url(http://genericons.com/wp-content/themes/a8c/genericons/font/genericons-regular-webfont.eot);
+}
+@font-face {
+ font-family: 'Genericons';
+ src: url(data:application/font-woff;charset=utf-8;base64,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) format('woff'),
+ url(http://genericons.com/wp-content/themes/a8c/genericons/font/genericons-regular-webfont.ttf) format('truetype'),
+ url(http://genericons.com/wp-content/themes/a8c/genericons/font/genericons-regular-webfont.svg#genericonsregular) format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+
+
+#customize-theme-controls .accordion-section-content .customize-control-widget_form.first-widget .move-widget-up {
+ color: #d5d5d5;
+ cursor: default;
+}
+#customize-theme-controls .accordion-section-content .customize-control-widget_form.last-widget .move-widget-down {
+ color: #d5d5d5;
+ cursor: default;
+}
+
+
+#customize-theme-controls .accordion-section-content .reorder-toggle {
+ margin: 12px 10px 15px;
+ float: left;
+ font-weight: 600;
+ cursor: pointer;
+ clear: left;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+#customize-theme-controls .accordion-section-content .reorder-toggle span {
+ text-decoration: none;
+}
+#customize-theme-controls .accordion-section-content .reorder-done {
+ display: none;
+}
+#customize-theme-controls .accordion-section-content .widget-reorder-nav {
+ display: none;
+ float: right;
+ background-color: #FAFAFA;
+}
+#customize-theme-controls .accordion-section-content .widget-reorder-nav span {
+ position: relative;
+ float: left;
+ display: block;
+ width: 30px; /* was 42px for mobile */
+ height: 40px;
+ color: #888;
+ text-indent: -9999px;
+ border-left: 1px dotted #dedede;
+ overflow: hidden;
+ cursor: pointer;
+ outline: none;
+}
+#customize-theme-controls .accordion-section-content .widget-reorder-nav span:before {
+ display: inline-block;
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 30px; /* was 42px for mobile */
+ height: 40px;
+ font-family: 'Genericons';
+ font-size: 24px;
+ line-height: 40px;
+ font-weight: normal;
+ font-style: normal;
+ text-align: center;
+ text-indent: 0;
+ vertical-align: top;
+}
+#customize-theme-controls .accordion-section-content .widget-reorder-nav span:hover,
+#customize-theme-controls .accordion-section-content .widget-reorder-nav span:focus {
+ color: black;
+}
+#customize-theme-controls .accordion-section-content .move-widget:before {
+ content: '\f442';
+}
+#customize-theme-controls .accordion-section-content .move-widget-down:before {
+ content: '\f431';
+}
+#customize-theme-controls .accordion-section-content .move-widget-up:before {
+ content: '\f432';
+}
+#customize-theme-controls .accordion-section-content .move-widget-area {
+ display: none;
+ background: #fff;
+ cursor: auto;
+ border-left: 1px solid #dedede;
+ border-right: 1px solid #dedede;
+ border-bottom: 1px solid #dedede;
+}
+#customize-theme-controls .accordion-section-content .move-widget-area.active {
+ display: block;
+}
+#customize-theme-controls .accordion-section-content .move-widget-area .description {
+ margin: 0;
+ padding: 15px 20px;
+ font-weight: 400;
+}
+
+#customize-theme-controls .accordion-section-content .widget-area-select {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+#customize-theme-controls .accordion-section-content .widget-area-select li {
+ position: relative;
+ color: #555;
+ padding: 15px 15px 15px 42px;
+ border-top: 1px solid #eee;
+ cursor: pointer;
+ margin: 0;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+#customize-theme-controls .accordion-section-content .widget-area-select li:before {
+ display: none;
+ position: absolute;
+ top: 8px;
+ left: 10px;
+ content: '\f418';
+ font-family: 'Genericons';
+ font-size: 24px;
+ line-height: 24px;
+}
+#customize-theme-controls .accordion-section-content .widget-area-select li:last-child {
+ border-bottom: 1px solid #eee;
+}
+#customize-theme-controls .accordion-section-content .widget-area-select .selected {
+ color: #fff;
+ text-shadow: 0 -1px 0 rgba(0,0,0,.4);
+ border-top: 1px solid #207fa1;
+ background: #2ea2cc;
+}
+#customize-theme-controls .accordion-section-content .widget-area-select .selected:before {
+ display: block;
+}
+#customize-theme-controls .accordion-section-content .widget-area-select .selected:last-child {
+ border-bottom: 1px solid #207fa1;
+}
+#customize-theme-controls .accordion-section-content .move-widget-actions {
+ text-align: right;
+ padding: 12px;
+}
+
+#customize-theme-controls .accordion-section-content .widget-area-select + li {
+ border-top: 1px solid #207fa1;
+}
+#customize-theme-controls .accordion-section-content.reordering .widget-title-action {
+ display: none;
+}
+#customize-theme-controls .accordion-section-content.reordering .widget-reorder-nav {
+ display: block;
+}
+#customize-theme-controls .accordion-section-content.reordering .reorder {
+ display: none;
+}
+#customize-theme-controls .accordion-section-content.reordering .reorder-done {
+ display: block;
+ color: #aa0000;
+}
+#customize-theme-controls .accordion-section-content.reordering .add-new-widget {
+ opacity: 0.2;
+ pointer-events: none;
+ cursor: not-allowed;
+}
+
/**
* Styles for new widget addition panel
@@ -117,8 +292,8 @@
.add-new-widget {
cursor: pointer;
- display: block;
- clear: both;
+ float: right;
+ clear: right;
padding: 13px 20px 10px 20px;
margin: 0px -20px -23px -20px;
text-align: right;
diff --git a/widget-customizer.js b/widget-customizer.js
index 5a4ad6e..d5b09f7 100644
--- a/widget-customizer.js
+++ b/widget-customizer.js
@@ -9,13 +9,15 @@ var WidgetCustomizer = (function ($) {
update_widget_nonce_value: null,
update_widget_nonce_post_key: null,
i18n: {},
- available_widgets: [],
+ available_widgets: [], // available widgets for instantiating
+ registered_widgets: [], // all widgets registered
active_sidebar_control: null,
sidebars_eligible_for_post_message: {},
widgets_eligible_for_post_message: {},
current_theme_supports: false,
previewer: null,
- saved_widget_ids: {}
+ saved_widget_ids: {},
+ registered_sidebars: []
};
$.extend(self, WidgetCustomizer_exports);
@@ -45,17 +47,33 @@ var WidgetCustomizer = (function ($) {
transport: 'refresh',
params: []
});
- var WidgetLibrary = self.WidgetLibrary = Backbone.Collection.extend({
+ var WidgetCollection = self.WidgetCollection = Backbone.Collection.extend({
model: Widget
});
- self.available_widgets = new WidgetLibrary(self.available_widgets);
+ self.available_widgets = new WidgetCollection( self.available_widgets );
+
+ var Sidebar = self.Sidebar = Backbone.Model.extend({
+ after_title: null,
+ after_widget: null,
+ before_title: null,
+ before_widget: null,
+ 'class': null,
+ description: null,
+ id: null,
+ name: null,
+ is_rendered: false
+ });
+ var SidebarCollection = self.SidebarCollection = Backbone.Collection.extend({
+ model: Sidebar
+ });
+ self.registered_sidebars = new SidebarCollection( self.registered_sidebars );
/**
* On DOM ready, initialize some meta functionality independent of specific
* customizer controls.
*/
self.init = function () {
- this.setupSectionVisibility();
+ this.showFirstSidebarIfRequested();
this.availableWidgetsPanel.setup();
};
wp.customize.bind( 'ready', function () {
@@ -66,45 +84,25 @@ var WidgetCustomizer = (function ($) {
* Listen for updates to which sidebars are rendered in the preview and toggle
* the customizer sections accordingly.
*/
- self.setupSectionVisibility = function () {
-
- self.previewer.bind( 'rendered-sidebars', function ( rendered_sidebars ) {
- rendered_sidebars = _( rendered_sidebars ).keys();
-
- var active_sidebar_section_selector = $.map( rendered_sidebars, function ( sidebar_id ) {
- return '#accordion-section-sidebar-widgets-' + sidebar_id;
- } ).join( ', ' );
- var active_sidebar_sections = $( active_sidebar_section_selector );
- var inactive_sidebar_sections = $( '.control-section[id^="accordion-section-sidebar-widgets-"]' ).not( active_sidebar_section_selector );
-
- // Hide sections for sidebars no longer active
- inactive_sidebar_sections.stop().each( function () {
- // Make sure that hidden sections get closed first
- if ( $( this ).hasClass( 'open' ) ) {
- // it would be nice if accordionSwitch() in accordion.js was public
- $( this ).find( '.accordion-section-title' ).trigger( 'click' );
- }
- $( this ).slideUp();
- } );
-
- // Show sections for sidebars now active
- active_sidebar_sections.stop().slideDown( function () {
- $( this ).css( 'height', 'auto' ); // so that the .accordion-section-content won't overflow
- } );
+ self.showFirstSidebarIfRequested = function () {
+ if ( ! /widget-customizer=open/.test( location.search ) ) {
+ return;
+ }
- // Open the first visible sidebar section automatically if widget customizer
- // requested from the admin notice on the widgets page
- if ( ! self._visibilitySetup && /widget-customizer=open/.test( location.search ) ) {
- active_sidebar_sections.filter( ':first' ).each( function () {
- if ( ! $( this ).hasClass( 'open' ) ) {
- $( this ).find( '.accordion-section-title' ).trigger( 'click' );
- }
- this.scrollIntoView();
- } );
+ var show_first_visible_sidebar = function () {
+ self.registered_sidebars.off( 'change:is_rendered', show_first_visible_sidebar );
+ var first_rendered_sidebar = self.registered_sidebars.find( function ( sidebar ) { return sidebar.get( 'is_rendered' ) } );
+ if ( ! first_rendered_sidebar ) {
+ return;
}
- self._visibilitySetup = true;
- } );
-
+ var section = $( '#accordion-section-sidebar-widgets-' + first_rendered_sidebar.get( 'id' ) );
+ if ( ! section.hasClass( 'open' ) ) {
+ section.find( '.accordion-section-title' ).trigger( 'click' );
+ }
+ section[0].scrollIntoView();
+ };
+ show_first_visible_sidebar = _.debounce( show_first_visible_sidebar, 100 ); // so only fires when all updated at end
+ self.registered_sidebars.on( 'change:is_rendered', show_first_visible_sidebar );
};
/**
@@ -120,9 +118,11 @@ var WidgetCustomizer = (function ($) {
var control = this;
control.control_section = control.container.closest( '.control-section' );
control.section_content = control.container.closest( '.accordion-section-content' );
+ control.is_reordering = false;
control.setupModel();
control.setupSortable();
control.setupAddition();
+ control.applyCardinalOrderClassNames();
},
/**
@@ -130,6 +130,8 @@ var WidgetCustomizer = (function ($) {
*/
setupModel: function() {
var control = this;
+ var registered_sidebar = self.registered_sidebars.get( control.params.sidebar_id );
+
control.setting.bind( function( new_widget_ids, old_widget_ids ) {
var removed_widget_ids = _( old_widget_ids ).difference( new_widget_ids );
@@ -166,6 +168,7 @@ var WidgetCustomizer = (function ($) {
// Re-sort widget form controls
sidebar_widgets_add_control.before( final_control_containers );
+ control.applyCardinalOrderClassNames();
var must_refresh_preview = false;
@@ -210,6 +213,48 @@ var WidgetCustomizer = (function ($) {
self.previewer.refresh();
}
});
+
+ // 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' );
+ var 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();
+ }
+ } );
+ },
+
+ /**
+ * 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 );
},
/**
@@ -250,6 +295,56 @@ var WidgetCustomizer = (function ($) {
}
}
});
+
+ /**
+ * 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 );
+ } );
+ },
+
+
+ /**
+ * 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 {Array(wp.customize.controlConstructor.widget_form)}
+ */
+ getWidgetFormControls: function () {
+ var control = this;
+ var form_controls = _( control.setting() ).map( function ( widget_id ) {
+ var setting_id = widget_id_to_setting_id( widget_id );
+ var 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;
},
/**
@@ -263,6 +358,11 @@ var WidgetCustomizer = (function ($) {
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 {
@@ -436,6 +536,15 @@ var WidgetCustomizer = (function ($) {
}
});
+ // Add the widget reordering elements to the widget control
+ control.container.find( '.widget-title-action' ).after( $( self.tpl.widget_reorder_nav ) );
+ var move_widget_area = $(
+ _.template( self.tpl.move_widget_area, {
+ sidebars: _( self.registered_sidebars.toArray() ).pluck( 'attributes' )
+ } )
+ );
+ control.container.find( '.widget-top' ).after( move_widget_area );
+
var save_btn = control.container.find( '.widget-control-save' );
save_btn.val( self.i18n.save_btn_label );
save_btn.attr( 'title', self.i18n.save_btn_tooltip );
@@ -520,10 +629,24 @@ var WidgetCustomizer = (function ($) {
control.setupControlToggle();
control.setupWidgetTitle();
+ control.setupReordering();
control.editingEffects();
},
/**
+ * @return {Array(wp.customize.controlConstructor.sidebar_widgets)}
+ */
+ getSidebarWidgetsControl: function () {
+ var control = this;
+ var setting_id = 'sidebars_widgets[' + control.params.sidebar_id + ']';
+ var sidebar_widgets_control = customize.control( setting_id );
+ if ( ! sidebar_widgets_control ) {
+ throw new Error( 'Unable to locate sidebar_widgets control for ' + control.params.sidebar_id );
+ }
+ return sidebar_widgets_control;
+ },
+
+ /**
* Submit the widget form via Ajax and get back the updated instance,
* along with the new widget control form to render.
*
@@ -606,8 +729,12 @@ var WidgetCustomizer = (function ($) {
setupControlToggle: function() {
var control = this;
control.container.find('.widget-top').on( 'click', function (e) {
- control.toggleForm();
e.preventDefault();
+ var sidebar_widgets_control = control.getSidebarWidgetsControl();
+ if ( sidebar_widgets_control.is_reordering ) {
+ return;
+ }
+ control.toggleForm();
} );
},
@@ -686,6 +813,68 @@ var WidgetCustomizer = (function ($) {
},
/**
+ * Set up the widget-reorder-nav
+ */
+ setupReordering: function () {
+ var control = this;
+ var reorder_nav = control.container.find( '.widget-reorder-nav' );
+
+ reorder_nav.find( '.move-widget, .move-widget-down, .move-widget-up' ).on( 'click keypress', function ( event ) {
+ if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
+ return;
+ }
+ $( this ).focus();
+
+ var sidebar_widgets_setting = control.getSidebarWidgetsControl().setting;
+ var widget_id = control.params.widget_id;
+ var sidebar_widget_ids = Array.prototype.slice.call( sidebar_widgets_setting() ); // clone
+
+ if ( $( this ).is( '.move-widget' ) ) {
+ control.toggleWidgetMoveArea();
+ } else {
+ var i = sidebar_widget_ids.indexOf( widget_id );
+ var is_move_down = $( this ).is( '.move-widget-down' );
+ var is_move_up = $( this ).is( '.move-widget-up' );
+ var offset = is_move_down ? 1 : -1;
+ if ( ( is_move_up && i === 0 ) || ( is_move_down && i === sidebar_widget_ids.length - 1 ) ) {
+ return;
+ }
+
+ var adjacent_widget_id = sidebar_widget_ids[i + offset];
+ sidebar_widget_ids[i + offset] = widget_id;
+ sidebar_widget_ids[i] = adjacent_widget_id;
+
+ sidebar_widgets_setting( sidebar_widget_ids );
+ $( this ).focus(); // re-focus after the container was moved
+ }
+ } );
+
+
+ control.container.find( '.widget-area-select' ).on( 'click keypress', 'li', function ( e ) {
+ if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) {
+ return;
+ }
+ e.preventDefault();
+ $( this ).siblings( '.selected' ).removeClass( 'selected' );
+ $( this ).toggleClass( 'selected' );
+ });
+ },
+
+ /**
+ * Toggle visibility of the widget move area
+ *
+ * @param {Boolean} toggle
+ */
+ toggleWidgetMoveArea: function ( toggle ) {
+ var control = this;
+ var move_widget_area = control.container.find( '.move-widget-area' );
+ if ( typeof toggle === 'undefined' ) {
+ toggle = ! move_widget_area.hasClass( 'active' );
+ }
+ move_widget_area.toggleClass( 'active', toggle );
+ },
+
+ /**
* Inverse of WidgetCustomizer.getControlInstanceForWidget
* @return {jQuery}
*/
@@ -780,7 +969,7 @@ var WidgetCustomizer = (function ($) {
*/
self.getSidebarWidgetControlContainingWidget = function ( widget_id ) {
var found_control = null;
- // @todo wp.customize.control needs the _.find method
+ // @todo this can use widget_id_to_setting_id(), then pass into wp.customize.control( x ).getSidebarWidgetsControl()
wp.customize.control.each( function ( control ) {
if ( control.params.type === 'sidebar_widgets' && -1 !== control.setting().indexOf( widget_id ) ) {
found_control = control;
@@ -796,7 +985,7 @@ var WidgetCustomizer = (function ($) {
*/
self.getWidgetFormControlForWidget = function ( widget_id ) {
var found_control = null;
- // @todo wp.customize.control needs the _.find method
+ // @todo We can just use widget_id_to_setting_id() here
wp.customize.control.each( function ( control ) {
if ( control.params.type === 'widget_form' && control.params.widget_id === widget_id ) {
found_control = control;
@@ -1022,5 +1211,18 @@ var WidgetCustomizer = (function ($) {
return parsed;
}
+ /**
+ * @param {String} widget_id
+ * @returns {String} setting_id
+ */
+ function widget_id_to_setting_id( widget_id ) {
+ var parsed = parse_widget_id( widget_id );
+ var setting_id = 'widget_' + parsed.id_base;
+ if ( parsed.number ) {
+ setting_id += '[' + parsed.number + ']';
+ }
+ return setting_id;
+ }
+
return self;
}( jQuery ));
diff --git a/widget-customizer.php b/widget-customizer.php
index dadc08b..8f36546 100644
--- a/widget-customizer.php
+++ b/widget-customizer.php
@@ -585,21 +585,56 @@ class Widget_Customizer {
self::$widgets_eligible_for_post_message[$available_widget['id_base']] = ( 'postMessage' === self::get_widget_setting_transport( $available_widget['id_base'] ) );
}
+ $widget_reorder_nav_tpl = sprintf(
+ '<div class="widget-reorder-nav"><span class="move-widget" tabindex="0" title="%1$s">%2$s</span><span class="move-widget-down" tabindex="0" title="%3$s">%4$s</span><span class="move-widget-up" tabindex="0" title="%5$s">%6$s</span></div>',
+ esc_attr__( 'Move to another area...', 'widget-customizer' ),
+ esc_html__( 'Move to another area...', 'widget-customizer' ),
+ esc_attr__( 'Move down', 'widget-customizer' ),
+ esc_html__( 'Move down', 'widget-customizer' ),
+ esc_attr__( 'Move up', 'widget-customizer' ),
+ esc_html__( 'Move up', 'widget-customizer' )
+ );
+
+ $move_widget_area_tpl = str_replace(
+ array( '{description}', '{btn}' ),
+ array(
+ esc_html__( 'Select an area to move this widget into:', 'widget-customizer' ),
+ esc_html__( 'Move', 'widget-customizer' ),
+ ),
+ '
+ <div class="move-widget-area">
+ <p class="description">{description}</p>
+ <ul class="widget-area-select">
+ <% _.each( sidebars, function ( sidebar ){ %>
+ <li class="" data-id="<%- sidebar.id %>" title="<%- sidebar.description %>" tabindex="0"><%- sidebar.name %></li>
+ <% }); %>
+ </ul>
+ <div class="move-widget-actions">
+ <button class="move-widget-btn button-secondary" type="button">{btn}</button>
+ </div>
+ </div>
+ '
+ );
+
// Why not wp_localize_script? Because we're not localizing, and it forces values into strings
global $wp_scripts;
$exports = array(
'update_widget_ajax_action' => self::UPDATE_WIDGET_AJAX_ACTION,
'update_widget_nonce_value' => wp_create_nonce( self::UPDATE_WIDGET_AJAX_ACTION ),
'update_widget_nonce_post_key' => self::UPDATE_WIDGET_NONCE_POST_KEY,
- 'registered_sidebars' => $GLOBALS['wp_registered_sidebars'],
+ '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' => _x( 'Update', 'button to save changes to a widget', 'widget-customizer' ),
'save_btn_tooltip' => _x( 'Save and preview changes before publishing them.', 'tooltip on the widget save button', 'widget-customizer' ),
'remove_btn_label' => _x( 'Remove', 'link to move a widget to the inactive widgets sidebar', 'widget-customizer' ),
'remove_btn_tooltip' => _x( 'Trash widget by moving it to the inactive widgets sidebar.', 'tooltip on btn a widget to move it to the inactive widgets sidebar', 'widget-customizer' ),
),
- 'available_widgets' => $available_widgets,
+ 'tpl' => array(
+ 'widget_reorder_nav' => $widget_reorder_nav_tpl,
+ 'move_widget_area' => $move_widget_area_tpl,
+ ),
'sidebars_eligible_for_post_message' => self::$sidebars_eligible_for_post_message,
'widgets_eligible_for_post_message' => self::$widgets_eligible_for_post_message,
'current_theme_supports' => current_theme_supports( 'widget-customizer' ),
@@ -930,7 +965,7 @@ class Widget_Customizer {
// Why not wp_localize_script? Because we're not localizing, and it forces values into strings
global $wp_scripts;
$exports = array(
- 'registered_sidebars' => $GLOBALS['wp_registered_sidebars'],
+ 'registered_sidebars' => array_values( $GLOBALS['wp_registered_sidebars'] ),
'registered_widgets' => $GLOBALS['wp_registered_widgets'],
'i18n' => array(
'widget_tooltip' => __( 'Press shift and then click to edit widget in customizer...', 'widget-customizer' ),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.