Customizer: Introduce WP_Customize_Control::active() method to determine whether the control is relevant to the current context (i.e. to the current URL being previewed).

Control can indicate its active state by a subclass overriding the 'active_callback' method, by supplying a callable 'active_callback' argument into the control's constructor, or by filtering 'customize_control_active'.

props westonruter.
see #27993.
Built from https://develop.svn.wordpress.org/trunk@29051


git-svn-id: http://core.svn.wordpress.org/trunk@28839 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Sergey Biryukov 2014-07-09 23:58:16 +00:00
parent 1c55723a16
commit ad7bc20cb1
11 changed files with 190 additions and 43 deletions

View File

@ -37,6 +37,7 @@
this.id = id;
this.selector = '#customize-control-' + id.replace( /\]/g, '' ).replace( /\[/g, '-' );
this.container = $( this.selector );
this.active = new api.Value( this.params.active );
settings = $.map( this.params.settings, function( value ) {
return value;
@ -79,10 +80,30 @@
element.set( setting() );
});
});
control.active.bind( function ( active ) {
control.toggle( active );
} );
control.toggle( control.active() );
},
ready: function() {},
/**
* Callback for change to the control's active state.
*
* Override function for custom behavior for the control being active/inactive.
*
* @param {Boolean} active
*/
toggle: function ( active ) {
if ( active ) {
this.container.slideDown();
} else {
this.container.slideUp();
}
},
dropdownInit: function() {
var control = this,
statuses = this.container.find('.dropdown-status'),
@ -563,6 +584,26 @@
this.bind( 'ready', this._ready );
this.bind( 'ready', function ( data ) {
if ( ! data || ! data.activeControls ) {
return;
}
// Any controls not even registered on the previewed URL are not active either
api.control.each( function ( control ) {
if ( typeof data.activeControls[ control.id ] === 'undefined' ) {
data.activeControls[ control.id ] = false;
}
} );
$.each( data.activeControls, function ( id, active ) {
var control = api.control( id );
if ( control ) {
control.active( active );
}
} );
} );
this.request = $.ajax( this.previewUrl(), {
type: 'POST',
data: this.query,

File diff suppressed because one or more lines are too long

View File

@ -751,13 +751,6 @@
}
} );
// Update widget control to indicate whether it is currently rendered
api.previewer.bind( 'rendered-widgets', function( renderedWidgets ) {
var isRendered = !! renderedWidgets[self.params.widget_id];
self.container.toggleClass( 'widget-rendered', isRendered );
} );
formSyncHandler = api.Widgets.formSyncHandlers[ this.params.widget_id_base ];
if ( formSyncHandler ) {
$( document ).on( 'widget-synced', function( e, widget ) {
@ -768,6 +761,17 @@
}
},
/**
* Update widget control to indicate whether it is currently rendered.
*
* Overrides api.Control.toggle()
*
* @param {Boolean} active
*/
toggle: function ( active ) {
this.container.toggleClass( 'widget-rendered', active );
},
/**
* Set up event handlers for widget removal
*/
@ -1418,32 +1422,38 @@
} );
// Update the model with whether or not the sidebar is rendered
api.previewer.bind( 'rendered-sidebars', function( renderedSidebars ) {
var isRendered = !! renderedSidebars[self.params.sidebar_id];
registeredSidebar.set( 'is_rendered', isRendered );
self.active.bind( function ( active ) {
registeredSidebar.set( 'is_rendered', active );
} );
},
// Show the sidebar section when it becomes visible
registeredSidebar.on( 'change:is_rendered', function( ) {
var sectionSelector = '#accordion-section-sidebar-widgets-' + this.get( 'id' ), $section;
/**
* Show the sidebar section when it becomes visible.
*
* Overrides api.Control.toggle()
*
* @param {Boolean} active
*/
toggle: function ( active ) {
var $section, sectionSelector;
$section = $( sectionSelector );
if ( this.get( 'is_rendered' ) ) {
$section.stop().slideDown( function() {
$( this ).css( 'height', 'auto' ); // so that the .accordion-section-content won't overflow
} );
sectionSelector = '#accordion-section-sidebar-widgets-' + this.params.sidebar_id;
$section = $( sectionSelector );
} 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' );
}
if ( active ) {
$section.stop().slideDown( function() {
$( this ).css( 'height', 'auto' ); // so that the .accordion-section-content won't overflow
} );
$section.stop().slideUp();
} 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();
}
},
/**

File diff suppressed because one or more lines are too long

View File

@ -85,6 +85,19 @@ class WP_Customize_Control {
*/
public $type = 'text';
/**
* Callback
*
* @since 4.0.0
*
* @access public
* @see WP_Customize_Control::active()
* @var callable Callback is called with one argument, the instance of
* WP_Customize_Control, and returns bool to indicate whether
* the control is active (such as it relates to the URL
* currently being previewed).
*/
public $active_callback = '';
/**
* Constructor.
@ -102,16 +115,21 @@ class WP_Customize_Control {
public function __construct( $manager, $id, $args = array() ) {
$keys = array_keys( get_object_vars( $this ) );
foreach ( $keys as $key ) {
if ( isset( $args[ $key ] ) )
if ( isset( $args[ $key ] ) ) {
$this->$key = $args[ $key ];
}
}
$this->manager = $manager;
$this->id = $id;
if ( empty( $this->active_callback ) ) {
$this->active_callback = array( $this, 'active_callback' );
}
// Process settings.
if ( empty( $this->settings ) )
if ( empty( $this->settings ) ) {
$this->settings = $id;
}
$settings = array();
if ( is_array( $this->settings ) ) {
@ -132,6 +150,41 @@ class WP_Customize_Control {
*/
public function enqueue() {}
/**
* Check whether control is active to current customizer preview.
*
* @since 4.0.0
*
* @return bool
*/
public final function active() {
$control = $this;
$active = call_user_func( $this->active_callback, $this );
/**
* Filter response of WP_Customize_Control::active().
*
* @since 4.0.0
*
* @param bool $active
* @param WP_Customize_Control $control
*/
$active = apply_filters( 'customize_control_active', $active, $control );
return $active;
}
/**
* Default callback used when invoking WP_Customize_Control::active().
*
* Subclasses can override this with their specific logic, or they may
* provide an 'active_callback' argument to the constructor.
*
* @return bool
*/
public function active_callback() {
return true;
}
/**
* Fetch a setting's value.
@ -143,8 +196,9 @@ class WP_Customize_Control {
* @return mixed The requested setting's value, if the setting exists.
*/
public final function value( $setting_key = 'default' ) {
if ( isset( $this->settings[ $setting_key ] ) )
if ( isset( $this->settings[ $setting_key ] ) ) {
return $this->settings[ $setting_key ]->value();
}
}
/**
@ -159,6 +213,7 @@ class WP_Customize_Control {
}
$this->json['type'] = $this->type;
$this->json['active'] = $this->active();
}
/**
@ -256,7 +311,7 @@ class WP_Customize_Control {
echo $this->get_link( $setting_key );
}
/**
/**
* Render the custom attributes for the control's input element.
*
* @since 4.0.0
@ -995,6 +1050,13 @@ class WP_Widget_Area_Customize_Control extends WP_Customize_Control {
</span>
<?php
}
/**
* @return bool
*/
function active_callback() {
return $this->manager->widgets->is_sidebar_rendered( $this->sidebar_id );
}
}
/**
@ -1035,5 +1097,12 @@ class WP_Widget_Form_Customize_Control extends WP_Customize_Control {
$args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) );
echo $this->manager->widgets->get_widget_control( $args );
}
/**
* @return bool
*/
function active_callback() {
return $this->manager->widgets->is_widget_rendered( $this->widget_id );
}
}

View File

@ -475,7 +475,8 @@ final class WP_Customize_Manager {
public function customize_preview_settings() {
$settings = array(
'values' => array(),
'channel' => esc_js( $_POST['customize_messenger_channel'] ),
'channel' => wp_unslash( $_POST['customize_messenger_channel'] ),
'activeControls' => array(),
);
if ( 2 == $this->nonce_tick ) {
@ -488,6 +489,9 @@ final class WP_Customize_Manager {
foreach ( $this->settings as $id => $setting ) {
$settings['values'][ $id ] = $setting->js_value();
}
foreach ( $this->controls as $id => $control ) {
$settings['activeControls'][ $id ] = $control->active();
}
?>
<script type="text/javascript">

View File

@ -1068,7 +1068,33 @@ final class WP_Customize_Widgets {
* @param array $widget Rendered widget to tally.
*/
public function tally_rendered_widgets( $widget ) {
$this->rendered_widgets[$widget['id']] = true;
$this->rendered_widgets[ $widget['id'] ] = true;
}
/**
* Determine if a widget is rendered on the page.
*
* @since 4.0.0
* @access public
*
* @param string $widget_id
* @return bool
*/
public function is_widget_rendered( $widget_id ) {
return in_array( $widget_id, $this->rendered_widgets );
}
/**
* Determine if a sidebar is rendered on the page.
*
* @since 4.0.0
* @access public
*
* @param string $sidebar_id
* @return bool
*/
public function is_sidebar_rendered( $sidebar_id ) {
return in_array( $sidebar_id, $this->rendered_sidebars );
}
/**

View File

@ -23,11 +23,6 @@
this.buildWidgetSelectors();
this.highlightControls();
this.preview.bind( 'active', function() {
self.preview.send( 'rendered-sidebars', self.renderedSidebars ); // @todo Only send array of IDs
self.preview.send( 'rendered-widgets', self.renderedWidgets ); // @todo Only send array of IDs
} );
this.preview.bind( 'highlight-widget', self.highlightWidget );
},

View File

@ -1 +1 @@
!function(a,b){if(a&&a.customize){var c,d=a.customize;d.WidgetCustomizerPreview={renderedSidebars:{},renderedWidgets:{},registeredSidebars:[],registeredWidgets:{},widgetSelectors:[],preview:null,l10n:{},init:function(){var a=this;this.buildWidgetSelectors(),this.highlightControls(),this.preview.bind("active",function(){a.preview.send("rendered-sidebars",a.renderedSidebars),a.preview.send("rendered-widgets",a.renderedWidgets)}),this.preview.bind("highlight-widget",a.highlightWidget)},buildWidgetSelectors:function(){var a=this;b.each(this.registeredSidebars,function(c,d){var e,f,g,h=[d.before_widget.replace("%1$s","").replace("%2$s",""),d.before_title,d.after_title,d.after_widget].join("");e=b(h),f=e.prop("tagName"),g=e.prop("className"),g&&(g=g.replace(/^\s+|\s+$/g,""),g&&(f+="."+g.split(/\s+/).join(".")),a.widgetSelectors.push(f))})},highlightWidget:function(a){var c=b(document.body),d=b("#"+a);c.find(".widget-customizer-highlighted-widget").removeClass("widget-customizer-highlighted-widget"),d.addClass("widget-customizer-highlighted-widget"),setTimeout(function(){d.removeClass("widget-customizer-highlighted-widget")},500)},highlightControls:function(){var a=this,c=this.widgetSelectors.join(",");b(c).attr("title",this.l10n.widgetTooltip),b(document).on("mouseenter",c,function(){a.preview.send("highlight-widget-control",b(this).prop("id"))}),b(document).on("click",c,function(c){c.shiftKey&&(c.preventDefault(),a.preview.send("focus-widget-control",b(this).prop("id")))})}},c=d.Preview,d.Preview=c.extend({initialize:function(a,b){d.WidgetCustomizerPreview.preview=this,c.prototype.initialize.call(this,a,b)}}),b(function(){var a=window._wpWidgetCustomizerPreviewSettings;a&&(b.extend(d.WidgetCustomizerPreview,a),d.WidgetCustomizerPreview.init())})}}(window.wp,jQuery);
!function(a,b){if(a&&a.customize){var c,d=a.customize;d.WidgetCustomizerPreview={renderedSidebars:{},renderedWidgets:{},registeredSidebars:[],registeredWidgets:{},widgetSelectors:[],preview:null,l10n:{},init:function(){var a=this;this.buildWidgetSelectors(),this.highlightControls(),this.preview.bind("highlight-widget",a.highlightWidget)},buildWidgetSelectors:function(){var a=this;b.each(this.registeredSidebars,function(c,d){var e,f,g,h=[d.before_widget.replace("%1$s","").replace("%2$s",""),d.before_title,d.after_title,d.after_widget].join("");e=b(h),f=e.prop("tagName"),g=e.prop("className"),g&&(g=g.replace(/^\s+|\s+$/g,""),g&&(f+="."+g.split(/\s+/).join(".")),a.widgetSelectors.push(f))})},highlightWidget:function(a){var c=b(document.body),d=b("#"+a);c.find(".widget-customizer-highlighted-widget").removeClass("widget-customizer-highlighted-widget"),d.addClass("widget-customizer-highlighted-widget"),setTimeout(function(){d.removeClass("widget-customizer-highlighted-widget")},500)},highlightControls:function(){var a=this,c=this.widgetSelectors.join(",");b(c).attr("title",this.l10n.widgetTooltip),b(document).on("mouseenter",c,function(){a.preview.send("highlight-widget-control",b(this).prop("id"))}),b(document).on("click",c,function(c){c.shiftKey&&(c.preventDefault(),a.preview.send("focus-widget-control",b(this).prop("id")))})}},c=d.Preview,d.Preview=c.extend({initialize:function(a,b){d.WidgetCustomizerPreview.preview=this,c.prototype.initialize.call(this,a,b)}}),b(function(){var a=window._wpWidgetCustomizerPreviewSettings;a&&(b.extend(d.WidgetCustomizerPreview,a),d.WidgetCustomizerPreview.init())})}}(window.wp,jQuery);

View File

@ -95,7 +95,9 @@
preview.send( 'nonce', api.settings.nonce );
});
preview.send( 'ready' );
preview.send( 'ready', {
activeControls: api.settings.activeControls
} );
/* Custom Backgrounds */
bg = $.map(['color', 'image', 'position_x', 'repeat', 'attachment'], function( prop ) {

View File

@ -1 +1 @@
!function(a,b){var c,d=wp.customize;c=function(a,b,c){var d;return function(){var e=arguments;c=c||this,clearTimeout(d),d=setTimeout(function(){d=null,a.apply(c,e)},b)}},d.Preview=d.Messenger.extend({initialize:function(a,e){var f=this;d.Messenger.prototype.initialize.call(this,a,e),this.body=b(document.body),this.body.on("click.preview","a",function(a){a.preventDefault(),f.send("scroll",0),f.send("url",b(this).prop("href"))}),this.body.on("submit.preview","form",function(a){a.preventDefault()}),this.window=b(window),this.window.on("scroll.preview",c(function(){f.send("scroll",f.window.scrollTop())},200)),this.bind("scroll",function(a){f.window.scrollTop(a)})}}),b(function(){if(d.settings=window._wpCustomizeSettings,d.settings){var a,c;a=new d.Preview({url:window.location.href,channel:d.settings.channel}),a.bind("settings",function(a){b.each(a,function(a,b){d.has(a)?d(a).set(b):d.create(a,b)})}),a.trigger("settings",d.settings.values),a.bind("setting",function(a){var b;a=a.slice(),(b=d(a.shift()))&&b.set.apply(b,a)}),a.bind("sync",function(c){b.each(c,function(b,c){a.trigger(b,c)}),a.send("synced")}),a.bind("active",function(){d.settings.nonce&&a.send("nonce",d.settings.nonce)}),a.send("ready"),c=b.map(["color","image","position_x","repeat","attachment"],function(a){return"background_"+a}),d.when.apply(d,c).done(function(a,c,d,e,f){var g,h=b(document.body),i=b("head"),j=b("#custom-background-css");g=function(){var g="";h.toggleClass("custom-background",!(!a()&&!c())),a()&&(g+="background-color: "+a()+";"),c()&&(g+='background-image: url("'+c()+'");',g+="background-position: top "+d()+";",g+="background-repeat: "+e()+";",g+="background-attachment: "+f()+";"),j.remove(),j=b('<style type="text/css" id="custom-background-css">body.custom-background { '+g+" }</style>").appendTo(i)},b.each(arguments,function(){this.bind(g)})})}})}(wp,jQuery);
!function(a,b){var c,d=wp.customize;c=function(a,b,c){var d;return function(){var e=arguments;c=c||this,clearTimeout(d),d=setTimeout(function(){d=null,a.apply(c,e)},b)}},d.Preview=d.Messenger.extend({initialize:function(a,e){var f=this;d.Messenger.prototype.initialize.call(this,a,e),this.body=b(document.body),this.body.on("click.preview","a",function(a){a.preventDefault(),f.send("scroll",0),f.send("url",b(this).prop("href"))}),this.body.on("submit.preview","form",function(a){a.preventDefault()}),this.window=b(window),this.window.on("scroll.preview",c(function(){f.send("scroll",f.window.scrollTop())},200)),this.bind("scroll",function(a){f.window.scrollTop(a)})}}),b(function(){if(d.settings=window._wpCustomizeSettings,d.settings){var a,c;a=new d.Preview({url:window.location.href,channel:d.settings.channel}),a.bind("settings",function(a){b.each(a,function(a,b){d.has(a)?d(a).set(b):d.create(a,b)})}),a.trigger("settings",d.settings.values),a.bind("setting",function(a){var b;a=a.slice(),(b=d(a.shift()))&&b.set.apply(b,a)}),a.bind("sync",function(c){b.each(c,function(b,c){a.trigger(b,c)}),a.send("synced")}),a.bind("active",function(){d.settings.nonce&&a.send("nonce",d.settings.nonce)}),a.send("ready",{activeControls:d.settings.activeControls}),c=b.map(["color","image","position_x","repeat","attachment"],function(a){return"background_"+a}),d.when.apply(d,c).done(function(a,c,d,e,f){var g,h=b(document.body),i=b("head"),j=b("#custom-background-css");g=function(){var g="";h.toggleClass("custom-background",!(!a()&&!c())),a()&&(g+="background-color: "+a()+";"),c()&&(g+='background-image: url("'+c()+'");',g+="background-position: top "+d()+";",g+="background-repeat: "+e()+";",g+="background-attachment: "+f()+";"),j.remove(),j=b('<style type="text/css" id="custom-background-css">body.custom-background { '+g+" }</style>").appendTo(i)},b.each(arguments,function(){this.bind(g)})})}})}(wp,jQuery);