From b9dfb7d4b0feabce2acd858a3af6b13c1c081c53 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 21 Aug 2016 22:51:29 -0700 Subject: [PATCH 1/6] Fix typo causing discussion control label to be empty --- js/customize-post-section.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/customize-post-section.js b/js/customize-post-section.js index a933b6b..5863843 100644 --- a/js/customize-post-section.js +++ b/js/customize-post-section.js @@ -594,7 +594,7 @@ params: { section: section.id, priority: 60, - label: postTypeObj.labels.discussion_field ? postTypeObj.labels.discussion_field : api.Posts.data.l10n.fieldDiscusionLabel, + label: postTypeObj.labels.discussion_field ? postTypeObj.labels.discussion_field : api.Posts.data.l10n.fieldDiscussionLabel, active: true, settings: { 'default': setting.id From 161bc558d0dc40253f05d074d4077a31cff35270 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 21 Aug 2016 22:51:55 -0700 Subject: [PATCH 2/6] Add explicit priority to post content control --- js/customize-post-section.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/customize-post-section.js b/js/customize-post-section.js index 5863843..c407089 100644 --- a/js/customize-post-section.js +++ b/js/customize-post-section.js @@ -520,6 +520,7 @@ control = new api.controlConstructor.post_editor( section.id + '[post_content]', { params: { section: section.id, + priority: 25, label: postTypeObj.labels.content_field ? postTypeObj.labels.content_field : api.Posts.data.l10n.fieldContentLabel, setting_property: 'post_content', settings: { From 495b1fcb0c2286305b9e38f3c868f6ae3e970c83 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 21 Aug 2016 23:10:34 -0700 Subject: [PATCH 3/6] Add support for content_template param for control --- js/customize-dynamic-control.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/js/customize-dynamic-control.js b/js/customize-dynamic-control.js index 7942523..5292ca7 100644 --- a/js/customize-dynamic-control.js +++ b/js/customize-dynamic-control.js @@ -182,6 +182,28 @@ control.deferred.embedded.resolve(); // This triggers control.ready(). }, + /** + * Render the control from its JS template, if it exists. + * + * @returns {void} + */ + renderContent: function renderContent() { + var control = this, template; + + if ( control.params.content_template ) { + if ( 'function' === typeof control.params.content_template ) { + template = control.params.content_template; + } else { + template = wp.template( control.params.content_template ); + } + if ( control.container ) { + control.container.html( template( control.params ) ); + } + } else { + api.Control.prototype.renderContent.call( control ); + } + }, + /** * This is not working with autofocus. * From 9fd90fa5aec3e88fe4674ba404dd233460f48882 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Sun, 21 Aug 2016 23:11:48 -0700 Subject: [PATCH 4/6] Remove obsolete todos --- js/customize-dynamic-control.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/js/customize-dynamic-control.js b/js/customize-dynamic-control.js index 5292ca7..f186339 100644 --- a/js/customize-dynamic-control.js +++ b/js/customize-dynamic-control.js @@ -131,10 +131,6 @@ control._setUpSettingPropertyLinks(); api.Control.prototype.ready.call( control ); - - // @todo build out the controls for the post when Control is expanded. - // @todo Let the Control title include the post title. - control.deferred.embedded.done(function() {}); }, /** From a0ce51f3e195464cd32e8664959bb10200b48c69 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Mon, 22 Aug 2016 00:39:04 -0700 Subject: [PATCH 5/6] Add sidebar shortcuts control --- js/customize-post-section.js | 32 +++++ js/customize-sidebar-shortcuts-control.js | 165 ++++++++++++++++++++++ php/class-customize-posts-plugin.php | 14 +- php/class-wp-customize-posts.php | 16 +++ 4 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 js/customize-sidebar-shortcuts-control.js diff --git a/js/customize-post-section.js b/js/customize-post-section.js index c407089..4f75b5e 100644 --- a/js/customize-post-section.js +++ b/js/customize-post-section.js @@ -275,6 +275,9 @@ if ( postTypeObj.supports.editor ) { section.addContentControl(); } + if ( 'undefined' === typeof EditPostPreviewCustomize && api.Widgets ) { + section.addPostWidgetAreasControl(); + } if ( postTypeObj.supports.excerpt ) { section.addExcerptControl(); } @@ -545,6 +548,35 @@ return control; }, + /** + * Add widget area shortcuts control. + * + * @returns {wp.customize.Control} Control + */ + addPostWidgetAreasControl: function() { + var section = this, control; + + control = new api.controlConstructor.sidebar_shortcuts( section.id + '[sidebar_shortcuts]', { + params: { + section: section.id, + priority: 26, // After content. + label: api.Posts.data.l10n.fieldWidgetAreasLabel, + settings: [] + } + } ); + + // Override preview trying to de-activate control not present in preview context. See WP Trac #37270. + control.active.validate = function() { + return true; + }; + + // Register. + section.postFieldControls.sidebar_shortcuts = control; + api.control.add( control.id, control ); + + return control; + }, + /** * Add post excerpt control. * diff --git a/js/customize-sidebar-shortcuts-control.js b/js/customize-sidebar-shortcuts-control.js new file mode 100644 index 0000000..a638844 --- /dev/null +++ b/js/customize-sidebar-shortcuts-control.js @@ -0,0 +1,165 @@ +/* global jQuery, wp, _ */ +/* eslint no-magic-numbers: [ "error", { "ignore": [0] } ], consistent-this: [ "error", "control" ] */ + +(function( api, $ ) { + 'use strict'; + + /** + * Sidebar shortcuts control extension of Dynamic Control. + */ + api.controlConstructor.sidebar_shortcuts = api.controlConstructor.dynamic.extend({ + + /** + * Initialize. + * + * @param {string} id Control ID. + * @param {object} options Options. + * @param {object} options.params Params. + * @returns {void} + */ + initialize: function( id, options ) { + var control = this, opt; + + if ( ! api.Widgets ) { + throw new Error( 'The widgets component is not loaded.' ); + } + + opt = {}; + opt.params = _.extend( + { + type: 'sidebar_shortcuts', + content_template: wp.template( 'customize-sidebar-shortcuts-control' ), + label: api.Posts.data.l10n.fieldWidgetAreasLabel, + active: true + }, + options.params || {} + ); + + api.controlConstructor.dynamic.prototype.initialize.call( control, id, opt ); + }, + + /** + * Ready. + * + * @returns {void} + */ + ready: function() { + var control = this; + api.controlConstructor.dynamic.prototype.ready.call( control ); + + control.activeSidebarTemplate = wp.template( 'customize-sidebar-shortcuts-control-active-sidebar' ); + control.widgetAreasContainer = control.container.find( 'ul.active-sidebar-sections' ); + control.noSidebarsRenderedNotice = control.container.find( '.no-sidebars-rendered-notice' ); + + control.widgetAreasContainer.on( 'click', 'button', function() { + var button = $( this ), section, returnPromise; + section = api.section( button.data( 'section-id' ) ); + returnPromise = control.focusConstructWithBreadcrumb( section, control ); + returnPromise.done( function() { + button.focus(); + } ); + + } ); + + _.bindAll( + control, + 'handleSidebarSectionAdd', + 'handleSidebarSectionRemove', + 'renderSidebarButtons' + ); + control.renderSidebarButtons = _.debounce( control.renderSidebarButtons ); + + api.section.each( control.handleSidebarSectionAdd ); + api.section.bind( 'add', control.handleSidebarSectionAdd ); + api.section.bind( 'remove', control.handleSidebarSectionRemove ); + }, + + /** + * Handle sidebar section added. + * + * @param {wp.customize.Section} section Section. + * @returns {void} + */ + handleSidebarSectionAdd: function handleSidebarSectionAdd( section ) { + var control = this; + if ( section.extended( api.Widgets.SidebarSection ) ) { + section.active.bind( control.renderSidebarButtons ); + control.renderSidebarButtons(); + } + }, + + /** + * Handle sidebar section removed. + * + * @param {wp.customize.Section} section Section. + * @returns {void} + */ + handleSidebarSectionRemove: function handleSidebarSectionRemove( section ) { + var control = this; + if ( section.extended( api.Widgets.SidebarSection ) ) { + section.active.unbind( control.renderSidebarButtons ); + control.renderSidebarButtons(); + } + }, + + /** + * Render sidebar buttons. + * + * @returns {void} + */ + renderSidebarButtons: function renderSidebarButtons() { + var control = this, activeSections = []; + + api.section.each( function( section ) { + if ( section.extended( api.Widgets.SidebarSection ) && section.active.get() ) { + activeSections.push( section ); + } + } ); + + activeSections.sort( function( a, b ) { + return a.priority.get() - b.priority.get(); + } ); + + control.widgetAreasContainer.empty(); + _.each( activeSections, function( activeSection ) { + var li = $( $.trim( control.activeSidebarTemplate( { + section_id: activeSection.id, + sidebar_name: activeSection.params.title + } ) ) ); + control.widgetAreasContainer.append( li ); + } ); + + control.widgetAreasContainer.toggle( 0 !== activeSections.length ); + control.noSidebarsRenderedNotice.toggle( 0 === activeSections.length ); + }, + + /** + * Focus (expand) one construct and then focus on another construct after the first is collapsed. + * + * This overrides the back button to serve the purpose of breadcrumb navigation. + * This is modified from WP Core. + * + * @link https://github.com/xwp/wordpress-develop/blob/e7bbb482d6069d9c2d0e33789c7d290ac231f056/src/wp-admin/js/customize-widgets.js#L2143-L2193 + * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} focusConstruct - The object to initially focus. + * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} returnConstruct - The object to return focus. + * @returns {void} + */ + focusConstructWithBreadcrumb: function focusConstructWithBreadcrumb( focusConstruct, returnConstruct ) { + var deferred = $.Deferred(), onceCollapsed; + focusConstruct.focus(); + onceCollapsed = function( isExpanded ) { + if ( ! isExpanded ) { + focusConstruct.expanded.unbind( onceCollapsed ); + returnConstruct.focus( { + completeCallback: function() { + deferred.resolve(); + } + } ); + } + }; + focusConstruct.expanded.bind( onceCollapsed ); + return deferred; + } + }); + +})( wp.customize, jQuery ); diff --git a/php/class-customize-posts-plugin.php b/php/class-customize-posts-plugin.php index c8b30ba..775f54c 100644 --- a/php/class-customize-posts-plugin.php +++ b/php/class-customize-posts-plugin.php @@ -246,9 +246,21 @@ public function register_scripts( WP_Scripts $wp_scripts ) { $in_footer = 1; $wp_scripts->add( $handle, $src, $deps, $this->version, $in_footer ); + $handle = 'customize-sidebar-shortcuts-control'; + $src = plugins_url( 'js/customize-sidebar-shortcuts-control' . $suffix, dirname( __FILE__ ) ); + $deps = array( 'customize-dynamic-control', 'jquery' ); + $in_footer = 1; + $wp_scripts->add( $handle, $src, $deps, $this->version, $in_footer ); + $handle = 'customize-post-section'; $src = plugins_url( 'js/customize-post-section' . $suffix, dirname( __FILE__ ) ); - $deps = array( 'customize-controls', 'customize-post-date-control', 'customize-post-status-control', 'customize-post-editor-control' ); + $deps = array( + 'customize-controls', + 'customize-post-date-control', + 'customize-post-status-control', + 'customize-post-editor-control', + 'customize-sidebar-shortcuts-control', + ); $in_footer = 1; $wp_scripts->add( $handle, $src, $deps, $this->version, $in_footer ); diff --git a/php/class-wp-customize-posts.php b/php/class-wp-customize-posts.php index df2612d..c8e2bb2 100644 --- a/php/class-wp-customize-posts.php +++ b/php/class-wp-customize-posts.php @@ -625,6 +625,7 @@ public function enqueue_scripts() { 'fieldStatusLabel' => __( 'Status', 'customize-posts' ), 'fieldDateLabel' => __( 'Date', 'customize-posts' ), 'fieldContentLabel' => __( 'Content', 'customize-posts' ), + 'fieldWidgetAreasLabel' => __( 'Widget Areas', 'customize-posts' ), 'fieldExcerptLabel' => __( 'Excerpt', 'customize-posts' ), 'fieldDiscussionLabel' => __( 'Discussion', 'customize-posts' ), 'fieldAuthorLabel' => __( 'Author', 'customize-posts' ), @@ -793,6 +794,21 @@ public function render_templates() { + + + +