WordPress.org

Make WordPress Core

Tagged: menu-customizer Toggle Comment Threads | Keyboard Shortcuts

  • Konstantin Obenland 8:51 pm on May 4, 2015 Permalink |
    Tags: , , menu-customizer   

    Customizer Chat Summary 

    Priorities for Customizer development in 4.3:
    1) Customizer Concurrency (aka Control Locking)
    2) Partial Refresh
    3) Menu Customizer
    4) Theme Installation
    5) UI/UX changes

    Customizer Concurrency doesn’t need much Core changes to implement (except for temp hooks maybe), so it makes sense to remain as a plugin, living here: https://github.com/xwp/wp-customize-widgets-plus
    @westonruter aims to have beta ready by end of this week.

    Partial Refresh is available as a feature plugin and can be tried out now: https://wordpress.org/plugins/customize-partial-refresh/
    There are a couple issues still needed for that one and feedback on the API for opt-in.

    Menu Customizer will be picked back up to have that ready ASAP for merge review (probably needs about a month). @voldemortensen, @valendesigns, @westonruter, and @celloexpressions will all work on dev, as well as anyone else who wants to jump in. @sheri will get started with design review, possibly with help from others (@folletto). The plugin currently works with WordPress 4.1 or 4.2. We can push lots of testing to start happening now since it’s pretty much functionally complete. It just needs a lot of back-end improvements.

    Theme Installation and UI/UX changes were not discussed in more detail and will be worked on as time allows after completing the first three items.

    Slack logs.

     
  • Nick Halsey 7:07 pm on December 19, 2014 Permalink
    Tags: menu-customizer,   

    Menu Customizer: Call for Contributors 

    After a few months off from working on the Menu Customizer to focus on improving the Customizer API in core, I’m starting to pick up development on the feature-plugin. Now that it’s approaching a reasonably usable state, and is compatible with the latest major release of WordPress (4.1), I’d like to begin efforts to see if we can propose merging it into core for WordPress 4.2.

    But there is a lot of work to be done. When Menu Customizer was my GSoC project, it was closed to contributors per GSoC rules. But development is now open to everyone, and I could use a lot of help with both development and non-development tasks. Here’s a list of items that need work:

    •  Development
      • Build-out the core API for adding Customizer sections and controls entirely with JavaScript, #30741 and its related tickets (PHP, JS)
      • Drag & Drop menu item reordering needs to do sub-menus (code imported from nav-menus.php is commented out in menu-customizer.js currently) (JS)
      • Fix problems with previewing updates to menu items, and with previewing newly-added menus once items are added (JS)
      • Eliminate the PHP closure that currently facilitates menu previewing, for PHP 5.2 compatibility (PHP)
      • Redo the add-menu-items “panel” to lazy-load its contents & utilize Backbone sub-views (PHP, JS)
      • Improve the core Customizer on mobile, then make Menu Customizer work on mobile (CSS)
      • Think about an API or otherwise action hooks to allow plugins to add menu item fields, #27066, #21898, #18584, etc. (PHP)
      • Inline docs audit, once we’re mostly done (PHP, JS)
      • Comprehensive code review by people like @westonruter, @ocean90, or @nacin, once we’re mostly “done”, preferably before a core merge proposal. Initial code review/cleanup from anyone can start now
    • Design
      • Overall UI audit/review, propose changes
      • Consider things like #29158 in relation to how the menus UI looks
      • Discuss approach to screen options (currently an icon in the Menus panel header)
      • UX audit, propose changes
      • Evaluate user flows & menus use-cases
      • Conduct user tests
    • Other
      • General user feedback – getting the word out about the plugin and collecting feedback (reviews & support forms on the .org repo would be a good place for feedback). Anyone reading this can try the plugin and provide feedback too :)
      • Accessibility audit
      • Backwards-compatibility audit; in particular, assessing whether Menu Customizer could replace the Menus admin screen, and what further features or use-cases would need to be addressed to do so
      • Research the history of the Menus UI in core and document how Menu Customizer addresses ongoing concerns; also consider open tickets in the Menus component (for merge proposal)

    Development is happening on the WordPress.org plugins repo the a GitHub repo. Some helpful links: create a ticket, Menu Customizer tickets, development log. It’ll probably also be possible to contribute via Github if that’s your preference – talk to @westonruter about how he does it.

    This project will primarily take place over the next month, when core development is largely on hold for the holidays and between releases, and when I’m in between semesters at school. The goal is to be merge-ready before the 4.2 feature-plugin merge consideration happens in January. If you’re interested in helping out, please comment on this post or ping me in WordPress Slack in #core (@celloexpressions).

    Due to the timing of this project around the holidays, we’ll probably do mostly asynchronous communication, but I would like to try a kick-off meeting in #core Slack on Monday, December 22, 2014 18:00 UTC; please come by if you’re interested!

     
    • diddledan 9:11 pm on December 19, 2014 Permalink | Log in to Reply

      Hi Nick,

      you may find my plugin https://wordpress.org/plugins/custom-menu-fields/ useful as it provides an api for menu fields to be added by plugins. I’ve not updated it in a while, but you’re welcome to have a look and reuse anything you like the look of (we are all GPL afterall :-p) – I might be able to have a look at your code over the weekend or holiday period and see if I can develop and send you any patches I think you might find useful.

    • Nick Halsey 7:51 pm on December 22, 2014 Permalink | Log in to Reply

      Had our first meeting today. Ongoing discussion will happen in the new #core-customize channel on Slack, so stop by if you have any feedback or want to help out!

  • Nick Halsey 3:48 pm on November 17, 2014 Permalink
    Tags: , , menu-customizer   

    JS/Underscore-template-rendered Custom Customizer Controls in WordPress 4.1 

    The Customizer is a JavaScript-driven feature of WordPress core, but until recently, most of the APIs for extending it in themes and plugins were PHP-oriented. In WordPress 4.1, we’re introducing more complete JS models for the different UI objects that comprise the Customizer. In the process, all controls are now placed into the DOM with JavaScript, rather than being output directly in PHP.

    At the same time, we’ve been working on issues of scalability and performance. In particular, bringing the navigation menu management experience into the Customizer has highlighted several areas with room for improvement. With menus, each menu item is a Customizer control with several fields, so a site with hundreds of menu items across different menus will end up sending a lot of repetitive HTML down from PHP, and we currently have to send the full markup for a menu item control down from the server when adding menu items in an Ajax call.

    #29572 offered a solution to these challenges: an optional API that allows Customizer controls to be written as JavaScript templates. Rather than populating a control’s container with markup rendered on the server and obtained via an Ajax call, we can now use JS templates to render these controls on the client without any server-side call. In the future, new controls could be added dynamically (lazy-loaded, #28580) by leveraging the control-type templates already loaded in the Customizer.

    In the remainder of this post, I’ll walk through how to use this API, its benefits, and example use-cases that are already benefiting WordPress core in 4.1.

    Registered Control Types

    In order to introduce a concept of having one template for multiple Customizer controls of the same type, we needed to introduce a way to register a type of control with the Customize Manager. Previously, custom control objects were only encountered when custom controls were added using WP_Customize_Manager::add_control(). But detecting added control types to render one template per type wouldn’t allow new controls to be created dynamically if no other instances of that type were loaded. So we’ve introduced WP_Customize_Manager::register_control_type(). Usage is simple:

    add_action( 'customize_register', '29527_customize_register' );
    function 29527_customize_register( $wp_customize ) {
    	// Define a custom control class, WP_Customize_Custom_Control.
    	// Register the class so that it's JS template is available in the Customizer.
    	$wp_customize->register_control_type( 'WP_Customize_Custom_Control' );
    }
    

    All registered control types will have their templates printed to the Customizer by WP_Customize_Manager::print_control_templates().

    Sending PHP Control Data to JavaScript

    While Customizer control data has always been passed to the control JS models, and this has always been able to be extended, you’re much more likely to need to send data down when working with JS templates. Anything that you would want access to in render_content() in PHP will need to be exported to JavaScript to be accessible in your control template. WP_Customize_Control exports the following control class variables by default:

    • type
    • label
    • description
    • active (boolean state)

    You can add additional parameters specific to your custom control by overriding WP_Customize_Control::to_json() in your custom control subclass. In most cases, you’ll want to call the parent class’ to_json method also, to ensure that all core variables are exported as well. Here’s an example from the core color control:

    public function to_json() {
    	parent::to_json();
    	$this->json['statuses'] = $this->statuses;
    	$this->json['defaultValue'] = $this->setting->default;
    }
    

    JS/Underscore Templating, + examples

    Once you’ve registered your custom control class as a control type and exported any custom class variables, you can create the template that will render the control UI. You’ll override WP_Customize_Control::content_template() (empty by default) as a replacement for WP_Customize_Control::render_content(). Render content is still called, so be sure to override it with an empty function in your subclass as well.

    Underscore-style custom control templates are very similar to PHP. As more and more of WordPress core becomes JavaScript-driven, these templates are becoming increasingly more common. Some sample template code in core can be found in media, revisions, the theme browser, and even in the Twenty Fifteen theme, where a JS template is used to both save the color scheme data and instantly preview color scheme changes in the Customizer. The best way to learn how these templates work is to study similar code in core and, accordingly, I’ll briefly explain an example here now.

    class WP_Customize_Color_Control extends WP_Customize_Control {
    	public $type = 'color';
    // ...
    	/**
    	 * Render a JS template for the content of the color picker control.
    	 */
    	public function content_template() {
    		?>
    		<# var defaultValue = '';
    		if ( data.defaultValue ) {
    			if ( '#' !== data.defaultValue.substring( 0, 1 ) ) {
    				defaultValue = '#' + data.defaultValue;
    			} else {
    				defaultValue = data.defaultValue;
    			}
    			defaultValue = ' data-default-color=' + defaultValue; // Quotes added automatically.
    		} #>
    		<label>
    			<# if ( data.label ) { #>
    				<span class="customize-control-title">{{{ data.label }}}</span>
    			<# } #>
    			<# if ( data.description ) { #>
    				<span class="description customize-control-description">{{{ data.description }}}</span>
    			<# } #>
    			<div class="customize-control-content">
    				<input class="color-picker-hex" type="text" maxlength="7" placeholder="<?php esc_attr_e( 'Hex Value' ); ?>" {{ defaultValue }} />
    			</div>
    		</label>
    		<?php
    	}
    }
    

    In the above template for the core custom color control, you can see that after the closing PHP tag, we have a JS template. <# #> notation is used around statements to be evaluated – in most cases, this is used for conditionals. All of the control instance data that we exported to JS is stored in the `data` object, and we can print a variable using double or triple brace notation {{ }}. As I said before, the best way to get the hang of writing controls like this is to read through existing examples. WP_Customize_Upload_Control was recently updated to leverage this API as well, integrating nicely with the way the media manager is implemented, and squeezing a ton of functionality out of a minimal amount of code. If you want some really good practice, try converting some of the other core controls to use this API – and submit patches to core too, of course!

    Working with Controls in JavaScript

    The Customizer has always had an API for working with controls in JavaScript. Now that the Customizer supports JS-rendered controls, this API will be even more useful, as you can do things like re-rendering the entire control if its data changes significantly (think media attachment previewing, for example), rather than doing direct DOM manipulation. Again, the core code is the best place to start getting a feel for this API, but it essentially works like subclasses do in PHP. See @westonruter‘s post for details on how this side of the API has evolved in 4.1, and take a look at the control-related models in wp-admin/js/customize-controls.js.

    Putting the pieces together

    Here’s a summary of what’s needed to leverage the new API in a custom Customizer control subclass:

    1. Make your render_content() function empty (but it does need to exist to override the default one).
    2. Create a new function, content_template(), and put the old contents of render_content() there.
    3. Add any custom class variables that are needed for the control to be exported to the JavaScript in the browser (the JSON data) by modifying the to_json() function (see WP_Customize_Color_Control for an example).
    4. Convert the PHP from render_content() into a JS template, using <# #> around JS statements to evaluate and {{ }} around variables to print. PHP class variables are available in the data object; for example, the label can be printed with {{ data.label }}.
    5. Register the custom control class/type. This critical step tells the Customizer to print the template for this control. This is distinct from just printing templates for all controls that were added because the ideas are that many instances of this control type could be rendered from one template, and that any registered control types would be available for dynamic control-creation in the future. Just do something like $wp_customize->register_control_type( 'WP_Customize_Color_Control' );.

    The PHP-only parts of the API are still fully supported and perfectly fine to use. But, with WordPress 4.0’s decreased need for custom controls, and given our long term goals for making the Customizer more flexible for doing things like switching themes in the Customizer without a pageload, I strongly encourage using this new API for all custom Customizer controls where feasible.

     
    • Jon Brown 10:51 am on November 18, 2014 Permalink | Log in to Reply

      Nick – Thank you! Seriously impressed by the work you’re doing to the customizer. Please keep it up!

    • Fabien Quatravaux 4:24 pm on December 15, 2014 Permalink | Log in to Reply

      Thanks for your hard work on this topic Nick.

      I’m currently trying to implement a custom control with the new API on 4.1-RC1, and I hit some roadblock : if I use the `$wp_customize->register_control_type` method, the input inside my Control becomes inhert. When I change the value of this control, the “Save” button on the top stays disabed showing that my changes are not taken into account.

      I’m missing the link, that was done automatically in the previous API version, between the actual HTML control and the setting that it is bound to. I thought this link was done thanks to the `data-customize-setting-link` attribute, but I had no luck using it. Any suggestions ?

      • bduclos 6:11 pm on February 6, 2015 Permalink | Log in to Reply

        Hi Fabien,

        Did you manage to do it?
        I’m triing to implement in in WP 4.1 but I have the same issue that you’ve described.

  • Weston Ruter 4:46 am on October 27, 2014 Permalink
    Tags: , , menu-customizer, widget-customizer   

    Toward a Complete JavaScript API for the Customizer 

    The Customizer is the first true JS-driven feature in core. That’s awesome, especially coming out of WCSF where JavaScript has been highlighted so prominently between Backbone.js, the WP REST API, Node.js, and socket.io. The Customizer has a great architecture with models for settings, controls, watchable-values, collections, events, and asynchronous callbacks. Nevertheless, the JavaScript API in the Customizer is incomplete.

    Existing Challenges

    When widgets were added to the Customizer in 3.9, adding widget controls to sidebar sections required direct DOM manipulation. For controls there is at least a Control model to manage state For sections and panels, however, there are no JS models at all, and so adding them dynamically is even more of a challenge. And this is the exact challenge that Nick Halsey’s Menu Customizer plugin currently has to struggle through.

    When Customizer panels were added in 4.0 to group all widget area sections into a “Widgets” panel, a bug was introduced whereby shift-clicking a widget in the preview no longer revealed the widget control in the Customizer pane because the sections were inside of the collapsed Widgets panel: there were no models to represent the state for whether or not a panel or section were currently expanded. Without models, a fix of this would require more messy DOM traversal to check if parent accordion sections were expanded or not. Storing data in the DOM is bad.

    In 4.0 the concept of contextual controls were added to the Customizer. This allowed controls to be registered with an active_callback, such as is_front_page, which the preview would execute and pass back up to the Customizer pane to then show/hide the control based on which URL was being previewed. This worked well, except when all controls in a section were inactive: then the result was a Customizer section without any visible controls. Instead, the expected behavior would be for the section to automatically collapse as well when all controls inside become inactive. Again, this problem stems from the fact that there is no JS model to represent a section and to list out the controls associated with it.

    For the past three weeks I’ve been focused on fleshing out the Customizer API to address these challenges, and to facilitate doing new dynamic things in the Customizer. The parent ticket for this is #28709: Improve/introduce Customizer JS models for Controls, Sections, and Panels.

    Models for Panels and Sections

    As noted above, there is a wp.customize.Control model, and then there is a wp.customize.control collection (yes, it is singular) to store all control instances. So to follow the pattern established by controls, in the patch there is a wp.customize.Panel and wp.customize.Section, along with wp.customize.panel and wp.customize.section collections (both singular again). So just as with controls, you can iterate over panels and sections via:

    wp.customize.panel.each( function ( panel ) { /* ... */ } );
    wp.customize.section.each( function ( section ) { /* ... */ } );
    

    Relating Controls, Sections, and Panels together

    When registering a new control in PHP, you pass in the parent section ID:

    $wp_customize->add_control( 'blogname', array(
    	'label' => __( 'Site Title' ),
    	'section' => 'title_tagline',
    ) );

    In the proposed JavaScript API, a control’s section can be obtained predictably:

    id = wp.customize.control( 'blogname' ).section(); // => title_tagline

    To get the section object from the ID, you just look up the section by the ID as normal: wp.customize.section( id ).

    You can move a control to another section using this section state as well, here moving it to the Navigation section:

    wp.customize.control( 'blogname' ).section( 'nav' );

    Likewise, you can get a section’s panel ID in the same way:

    id = wp.customize.section( 'sidebar-widgets-sidebar-1' ).panel(); // => widgets

    You can go the other way as well, to get the children of panels and sections:

    sections = wp.customize.panel( 'widgets' ).sections();
    controls = wp.customize.section( 'title_tagline' ).controls();
    

    You can use these to move all controls from one section to another:

    _.each( wp.customize.section( 'title_tagline' ).controls(), function ( control ) {
    	control.section( 'nav' );
    });
    

    Contextual Panels and Sections

    Also just as with controls, when you invoke $wp_customize->add_section() you can pass an active_callback param to indicate whether the section is relevant to the currently-previewed URL; the same goes for panels. A good example of a contextual section is only showing the “Static Front Page” section if the preview is currently on the front-page:

    function contextual_static_front_page_section( $wp_customize ) {
    	$wp_customize->get_section( 'static_front_page' )->active_callback = 'is_front_page';
    }
    add_action( 'customize_register', 'contextual_static_front_page_section', 11 );

    Nevertheless, this will not usually be needed because a section inherits its active state from its control children (and a panel inherits from its section children), via the new isContextuallyActive() method. If all controls within a section become inactive, then the section will automatically become inactive.

    As with controls, Panel and Section instances have an active state (a wp.customize.Value instance). When the active state changes, the panel, section, and control instances invoke their respective onChangeActive method, which by default slides the container element up and down, if false and true respectively. There are also activate() and deactivate() methods now for manipulating this active state, for panels, sections, and controls:

    wp.customize.section( 'nav' ).deactivate(); // slide up
    wp.customize.section( 'nav' ).activate({ duration: 1000 }); // slide down slowly
    wp.customize.section( 'colors' ).deactivate({ duration: 0 }); // hide immediately
    wp.customize.section( 'nav' ).deactivate({ completeCallback: function () {
    	wp.customize.section( 'colors' ).activate(); // show after nav hides completely
    } });
    

    Note that manually changing the active state would only stick until the preview refreshes or loads another URL. The activate()/deactivate() methods are designed to follow the pattern of the new expanded state.

    Expanded State

    As noted above, in 4.0 when panels were introduced, a bug was introduced whereby shift-clicking a widget in the preview fails to show the widget control if the Widgets panel is not already open. With the proposed changes, panels, sections, and (widget) controls have an expanded state (another wp.customize.Value instance). When the state changes, the onChangeExpanded method is called which by will handle Panels sliding in and out, and sections sliding up and down (and widget controls up and down, as they are like sections). So now when a widget control needs to be shown, the control’s section and panel can simply have their expanded state to true in order to reveal the control. Expanding a section automatically expands its parent panel. Expanding a widget control, automatically expands its containing section and that section’s panel.

    As with activate()/deactivate() to manage the active state, there are expand() and collapse() methods to manage the expanded state. These methods also take a similar params object, including duration and completeCallback. The params object for Section.expand() accepts an additional parameter “allowMultiple” to facilitate dragging widget controls between sidebar sections. By default expanding one section will automatically collapse all other open sections, and so this param overrides that. You can use this, for instance, to expand all sections at once so you can see all controls without having to click to reveal each accordion section one by one:

    wp.customize.section.each(function ( section ) {
    	if ( ! section.panel() ) {
    		section.expand({ allowMultiple: true });
    	}
    });

    Focusing

    Building upon the expand()/collapse() methods for panels, sections, and controls, these models also support a focus() method which not only expands all of the necessary element, but also scrolls the target container into view and puts the browser focus on the first focusable element in the container. For instance, to expand the “Static Front Page” section and focus on select dropdown for the “Front page”:

    wp.customize.control( 'page_on_front' ).focus()

    This naturally fixes the #29529, mentioned above.

    The focus functionality is used to implement autofocus: deep-linking to panels, sections, and controls inside of the customizer. Consider these URLs:

    • …/wp-admin/customize.php?autofocus[panel]=widgets
    • …/wp-admin/customize.php?autofocus[section]=colors
    • …/wp-admin/customize.php?autofocus[control]=blogname

    This can be used to add a link on the widgets admin page to link directly to the widgets panel within the Customizer.

    Priorities

    When registering a panel, section, or control in PHP, you can supply a priority parameter. This value is now stored in a wp.customize.Value instance for each respective Panel, Section, and Control instance. For example, you can obtain the priority for the widgets panel via:

    priority = wp.customize.panel( 'widgets' ).priority(); // => 110

    You can then dynamically change the priority and the Customizer panel will automatically re-arrange to reflect the new priorities:

    wp.customize.panel( 'widgets' ).priority( 1 ); // move Widgets to the top

    Custom types for Panels and Sections

    Just as Customizer controls can have custom types (ColorControlImageControlHeaderControl…) which have custom behaviors in JS:

    wp.customize.controlConstructor.FooControl = wp.customize.Control.extend({ /*...*/ });

    So too can Panels and Sections have custom behaviors in the proposed changes. A type parameter can be passed when creating a Panel or Section, and then in JavaScript a constructor corresponding to that type can be registered. For instance:

    PHP:

    add_action( 'customize_register', function ( $wp_customize ) {
    	class WP_Customize_Harlem_Shake_Section extends WP_Customize_Section {
    		public $type = 'HarlemShake';
    	}
    	$section = new WP_Customize_Harlem_Shake_Section(
    		$wp_customize,
    		'harlem_shake',
    		array( 'title' => __( 'Harlem Shake' ) )
    	);
    	$wp_customize->add_section( $section );
    	$wp_customize->add_setting( 'harlem_shake_countdown', array(
    		'default' => 15,
    	));
    	$wp_customize->add_control( 'harlem_shake_countdown', array(
    		'label' => __( 'Countdown' ),
    		'section' => 'harlem_shake',
    		'setting' => 'harlem_shake_countdown',
    		'type' => 'number',
    	));
    });
    

    JS:

    wp.customize.sectionConstructor.HarlemShake = wp.customize.Section.extend({
    	shake: function () {
    		// This can be invoked via wp.customize.section( 'harlem_shake' ).shake();
    		console.info( 'SHAKE!!' );
    	}
    });

    Next Steps

    • Continue discussion on parent ticket #28709: Improve/introduce Customizer JS models for Controls, Sections, and Panels.
    • Review JavaScript changes in pull request. Anyone is free to open a PR to onto the existing branch on GitHub to make changes. Props to Ryan Kienstra (@ryankienstra) and Nick Halsey (@celloexpressions) for their contributions.
    • Update logic for adding widget controls to use new API (adding widgets is using the old pseudo-API and it is currently broken); allow controls to be added manually.
    • Work with Nick Halsey to make sure that dynamically-created sections and controls suit the needs of Menu Customizer, and make sure that it works for other plugins like Customize Posts.
    • Build upon the initial QUnit tests to add coverage for existing JS API and newly added API (#28579).
    • Harden the logic for animating the Customizer panel into view.
    • Get feedback from other Core devs and get initial patch committed.

    Thanks to Nick Halsey (@celloexpressions) for his proofreading and feedback on the drafts of this blog post.

     
    • nikeo 6:38 am on October 27, 2014 Permalink | Log in to Reply

      Really awesome improvements! This customizer JS API is sooo currently missing in core!
      Thanks

    • Fab1en 9:09 am on October 27, 2014 Permalink | Log in to Reply

      This new API sounds great ! Thanks a lot for this great work.

      I’m wondering if it will be sufficient for my use case : I’m currently using the customizer to customize each posts that appear on the front page. In the same way widgets can be selected on the preview side by a simple click, clicking on a post on my theme preview will reveal the editing panel on the customizer side.

      I’m facing two issues to implement this properly :

      1 During the control creation JS callback, I have to wait until the preview loading is complete to bind the events. There is no event that tells me the preview is loaded and the iframe DOM is ready. Here is my implementation :

      (function( exports, $ ){
      	var api = wp.customize;
      
      	api.controlConstructor.myCustomControl = api.Control.extend({
      		ready: function() {
      			var control = this;
      
      			// wait for the preview iframe to be ready
      			var timer = setInterval(function(){
      				if(control.previewer.preview && control.previewer.preview.iframe && control.previewer.preview.iframe[0].contentDocument) {
      					clearInterval(timer);
      
      					// get iframe document
      					var doc = control.previewer.preview.iframe[0].contentDocument;
      
      					// bind events using doc
      				}
      			}, 200);
      
      		}
      	});
      
      })( wp, jQuery );

      Am I missing something ?

      2 To open the correct customizer section, I need to parse the customiser panel DOM :

      var $section = control.container.closest('.accordion-section');
      if(!$section.hasClass('open')){
      	$section.find('h3').click();
      }

      For this one, I think your API can solve my issue :

      wp.customize.section(control.section()).expand()

      But would not it be simpler to get the section model directly from the control ?

      control.section.expand()

    • Ryan Kienstra 5:18 am on October 28, 2014 Permalink | Log in to Reply

      Dear Fab1en,
      Regarding your second question, you only need to call .expand() on the control instance.

      This will expand the control and its containing section.

      For example, to expand the header image:

      var headerImageControl = wp.customize.control.instance( 'header_image' );
      headerImageControl.expand();

      You could also use .focus() instead of .expand() This will expand it and scroll it to the top.

    • Weston Ruter 11:15 pm on October 31, 2014 Permalink | Log in to Reply

      FYI: The proposed patch was committed: https://core.trac.wordpress.org/changeset/30102

    • brianfeister 5:38 pm on November 1, 2014 Permalink | Log in to Reply

      It’s really great to see this make it into Core! I’ve implemented my owns pseudo version of this functionality a while ago and it’ll be good to clean up that code. The one thing I am wondering about is the customizable widget areas in the Customizer. I have written a custom plugin that manages widget areas dynamically on the fly and also manages layout. As such, the widget area management in the theme customizer is showing widget area controls for dynamically named (e.g. random hash’s) widget areas and it looks bad from a presentational perspective. Is there a way to de-register these widgets from the customize preview sidebar?

      • Weston Ruter 5:25 pm on November 2, 2014 Permalink | Log in to Reply

        @brianfeister: Yes, I believe so. What you can do is add customize_section_active filter, and use it to force the $active to be false if the $section argument is for one of your dynamically-generated widget areas.

        See:
        https://core.trac.wordpress.org/ticket/29758
        https://core.trac.wordpress.org/attachment/ticket/29758/29758.2.diff

        So in theory this should be all you need:

        /**
         * Prevent the second widget area (sidebar) from being displayed in the Customizer.
         *
         * @param bool $active
         * @param WP_Customize_Section $section
         *
         * @return bool
         */
        function force_hide_second_widget_area_customize_section( $active, $section ) {
        	if ( 'sidebar-widgets-sidebar-2' === $section->id ) {
        		$active = false;
        	}
        	return $active;
        }
        add_filter( 'customize_section_active', 'force_hide_second_widget_area_customize_section', 10, 2 );

        However, in practice this is not working as expected because the SidebarControl Customizer control is manually updating its parent section when its active state changes. So this needs to be fixed.

        Let me know if this would address your use case, and I’ll proceed with a patch to fix.

      • Weston Ruter 5:33 pm on November 2, 2014 Permalink | Log in to Reply

        You actually can force a widget area section to be hidden if you take the above filter and then also add this one:

        
        /**
         * Prevent the second widget area (sidebar) from being displayed in the Customizer.
         *
         * @param bool $active
         * @param WP_Customize_Control $control
         *
         * @return bool
         */
        function force_hide_second_widget_area_customize_control( $active, $control ) {
        	if ( 'sidebars_widgets[sidebar-2]' === $control->id ) {
        		$active = false;
        	}
        	return $active;
        }
        add_filter( 'customize_control_active', 'force_hide_second_widget_area_customize_control', 10, 2 );

        However, there should not be a need for two separate filters. So this should be fixed in Core.

        • brianfeister 6:28 pm on November 2, 2014 Permalink | Log in to Reply

          @westonruter, sounds great to me! The `customize_section_active` filter hasn’t landed in core just yet, is that correct? Your proposed solution sounds good to me and I agree that two filters shouldn’t be necessary. Thanks so much!

          • Weston Ruter 6:33 pm on November 2, 2014 Permalink | Log in to Reply

            @brianfeister: correct. This will be in the 4.1 release.

            How are you hiding your dynamic widget areas on the widgets admin page?

            • brianfeister 7:27 pm on November 2, 2014 Permalink

              @westonruter – I’ve made some very deep system level changes (without altering core) because I’m doing this with a Multisite network. So, really I’m changing the way all users on the network interact with these dynamic areas and layouts. I’ve removed all links that point to the widgets admin page and replaced that area with my own system. The code isn’t perfect, I wish I had time to improve it, but it works. I could show you some time, but it’s more complex than just throwing a link to a gist on here. DM @brianfeister on Twitter if you want to set up a time to have a look. I’d be curious to hear your thoughts on it.

        • Weston Ruter 12:02 am on November 3, 2014 Permalink | Log in to Reply

          @brianfeister: I just filed a new ticket for this, please star it to follow updates: https://core.trac.wordpress.org/ticket/30235

  • Nick Halsey 12:20 am on August 8, 2014 Permalink
    Tags: , menu-customizer,   

    GSoC Menu Customizer Update: Live-previewing Menus 

    I’ve finished implementing menu-previewing in the Menu Customizer plugin, building on the scalable approach to saving menus that I discussed in my last update. The entire Menus experience is now consolidated into a Menus panel in the Customizer, where you can preview your menus as you make changes. It’s really nice to have Menus easily accessible alongside the rest of the site-appearance-management tools in the Customizer.

    I only have about a week and a half left in my GSoC project, and I’m hoping to focus on improving the add-new-menu-item panel in my remaining time, making it scale and implementing the search functionality. I’m also planning on cleaning up the codebase and implementing the ability to manage menu hierarchy (submenus).

    If you’re interested in testing the Menu Customizer, and live-previewing changes to your menus, you can get the plugin here. Please note that it currently requires PHP 5.3+, but it’s getting less and less alpha by the day.

    Post-GSoC Plans

    After the GSoC coding period is over, I’m planning on transitioning Menu Customizer development to the feature-plugin format, gathering a group of interested contributors and holding weekly meetings to coordinate our efforts. While it won’t be ready for core consideration by 4.1, and requires some more core Customizer infrastructure to really work well, we’ll continue working on the plugin until menus in the Customizer really shine, and are ready for core.

     
  • Nick Halsey 3:15 pm on July 15, 2014 Permalink
    Tags: , menu-customizer,   

    GSoC Menu Customizer Update: Scalable Menus 

    Since my last GSoC update, I’ve spent a fair amount of time helping prepare the Customizer for 4.0 beta 1. But I’ve also continued working on the Menu Customizer and have a lot of progress to report.

    Add & Delete Menus

    You can now add new menus, via the “+ New Menu” section. Added menus currently have some issues, though; you’ll probably need to reload the page before adding items works. The problems stem from the lack of a proper JS API for adding, deleting, and managing Sections and Settings (and Panels), and the incompleteness of the existing Control JS API. This will probably need to be resolved in core before the Menu Customizer can be considered for core integration, see #28709.

    I’ve also implemented a menu-deletion mode, which can be toggled from the add-menu section. It’s too easy to delete menus otherwise, even with an AYS confirming the delete, because deleted menus cannot be restored, and are not “previewed” before being published to the db (added menus aren’t either). It’s probably worth augmenting the AYS to state the menu name being deleted, and to add an extra warning if it’s active in a theme location or a widget.

    Saving Menus and Menu Item Data in a Scalable Way

    In core, menus do not scale well at all. You don’t have to look very deep into the code to see why – massive amounts of data for each item are hidden on the admin screens (much of which never changes) and then must be updated every time a change is made.

    Since one of the goals of this project is to experiment with new approaches, I’ve begun implementing a new approach for saving menu data, which is currently in use in the plugin. Thanks to my mentors @ethitter and @obenland for guiding me on the best approach to take here, and @westonruter for the way he implemented the Widget Customizer UI, which inspired this exact approach. Here’s how it works:

    • Each menu has a nav_menu Customizer control that contains an ordered array of numerical menu item ids (known throughout the core menus codebase as their db ids).
    • When an item is added, it is created as an orphaned draft via ajax, and its id is added to the nav_menu setting’s array.
    • When an item is deleted, its id is removed from the nav_menu setting’s array.
    • When menu items are reordered, the order of ids in the nav_menu id is updated to match.
    • When menu items are moved into and out of sub-menus, the parent menu item id is updated in the individual item’s data (not yet implemented).
    • When a menu item field is changed (by default, this would mean changing the label or, for custom items, url fileds; there are screen options for several others), the original item is cloned and the copy is updated with the new data, using a wrapper for wp_update_nav_menu_item() that doesn’t require passing all existing (unchanged) menu item data. The cloned item’s id is returned and replaces the original id in the nav_menu setting (thereby marking the original item for deletion). Additional changes are saved to the cloned item until the settings are saved, at which point all items are marked for a new clone to be created if changes are made (not yet implemented).
    • When the user saves their changes from the Customizer (via the customize_update_nav_menu action), the array of ids is compared to the currently-published menu’s items. If there are items that are no longer present, those are marked for deletion. For each of the new ids, the corresponding menu item (which already exists) is updated to be published, assigned to the corresponding menu (for the new items created as orphaned drafts), and the item’s menu_order is set to the id’s position in the nav_menus setting array. Finally, all of the removed items are deleted.

    While menu previewing in the customizer is not yet implemented, it will also be able to use the nav_menu setting’s array of ids to display an augmented set of menu items. I’m also still working on ensuring that menu item data is not posted during the customize-save ajax, but the data isn’t needed so we’re most of the way there already.

    UI Aside

    customize-header-bigflat-buttons-close

    Quick aside: @DrewAPicture pointed out in IRC that the new Customizer close and panel-back icons don’t really match the save button. I’ve done some rough explorations of potential alternatives; if anyone’s interested in discussing them and possibly implementing a change here, feel free to ping me in IRC (@celloexpressions) and/or create a ticket and/or comment here.

    Finally, I’m hoping to finish implementing menu previewing by the end of this week, fully utilizing the Customizer. Once this is done, I’ll essentially be at feature-complete stage (other than some little details and several known bugs) and ready to iterate (I’m already planning on working on the add-menu-items backend, as it currently doesn’t scale).

     
    • michalzuber 5:30 pm on July 17, 2014 Permalink | Log in to Reply

      I’m figuring out why is `@todo: Remove choices` in the `wp-includes/class-wp-customize-control.php` ? Couldn’t get it.

      • Nick Halsey 5:43 pm on July 17, 2014 Permalink | Log in to Reply

        That’s more related to the Customizer post, but I think that’s leftover from the initial customizer development in 3.4. We can remove the todo, since removing $choices is no longer an option due to back-compat.

    • Weston Ruter 8:26 pm on July 22, 2014 Permalink | Log in to Reply

      When an item is added, it is created as an orphaned draft via ajax, and its id is added to the nav_menu setting’s array.

      Something that I’ve been exploring with Customize Posts is the addition and deletion of postmeta. Instead of actually mutating the database, when creating new meta I’m creating faux post meta IDs and then referring to them in the preview filter. When saving the Customizer settings, these posts meta are then inserted at that time. It’s not quite done yet, as I need to now gather the post meta IDs that were inserted at the time of saving, and update the setting to refer to them.

      Generating a virtual post meta ID: https://github.com/x-team/wp-customize-posts/blob/85dc4e562ea806c17480899f5d94f93d42297de1/js/customize-posts.js#L611-L618

      Sanitizing a setting that includes virtual post meta ID: https://github.com/x-team/wp-customize-posts/blob/develop/php/class-wp-customize-posts.php#L303-L310

      It would be ideal if Menu Customizer could add new menu items virtually without touching the DB.

      • Nick Halsey 10:12 pm on July 22, 2014 Permalink | Log in to Reply

        I’m not sure if it would be possible to add items without touching the DB in a scalable way. The primary reason for doing that is so that menu item data doesn’t need to be sent to the server all at once when saving, which causes scaling problems currently (for example, imagine if 100+ menu items were added to several different menus upon initial setup of a site – that data would all go up together).

        In the existing menus system, items are similarly added to the db via ajax before being made available for manipulation in the UI. So, the concept of orphaned draft menu item posts is existing and currently being leveraged here.

  • Nick Halsey 2:44 am on June 28, 2014 Permalink
    Tags: , menu-customizer   

    GSoC Menu Customizer Update 

    Since this is my first post here, a quick introduction. I’m a student at the University of Southern California studying Civil Engineering, Architecture, and Music Composition. I’ve been contributing to WordPress Core for just over a year and this summer I’m pleased to be working on WordPress full-time for my Google Summer of Code project.

    Overview

    The goal of the Menu Customizer project is to add Custom Menu management to the Customizer. Ideally, the project should be able to replace the existing Menus screen, with full feature parity, but that’s obviously a bigger discussion that would take place later. For more details, check out my initial proposal.

    Current Status

    I started six weeks ago and have built out most of the plugin’s UI and structure. However, I still need to build the menu-item previewing and saving components of the project. The UI closely resembles the Widgets-in-customizer UI, with sections for each menu and controls for each item. New menu items are added via a slide-out panel, where they’re currently grouped by post type/taxonomy, custom links, and a global search feature. The existing “Navigation” Customizer section has been re-branded to “Theme Locations,” and emphasizes the ability to add menus to widgets. Development is being done on the plugin repo, and you can download and play with it from there, but note that adding items creates orphaned draft menu items that are never published currently. Here’s a demo of the current plugin:

    (If the embedded video doesn’t play for you, try this link: https://cloudup.com/cVJbk3u32QV)

    The add-menu-item UI and implementation will be getting a lot of attention throughout the rest of my project. Items are added immediately, rather than the existing two-step checkboxes and adding several at once process, and menu items can now be deleted without having to open their settings, making deletion and addition more streamlined.

    When editing menu items, changing the navigation label of an item instantly updates its drag-and-drop handle, and updating a menu name updates the corresponding Customizer section. Items can be reordered or moved into sub-menus via either drag-and-drop or a reordering mode similar to that of the Widget Customizer.

    To minimalize the UI, given the limited space in the customizer, the “Title Attribute” field has been turned off by default, and all of the existing menu-item-field screen options are available, syncing with the existing Menus screen. I might look into building a core API for customizer screen options now that #27406 is in trunk, time permitting.

    A good amount of my time in the past couple weeks has been dedicated to #27406, which is a prerequisite for the Menu Customizer to be realistic given the need to allow users to create new menus (and in turn, new Customizer sections). Committed to trunk yesterday, it introduces a “Panels” API to the Customizer. Panels are a way to group sections, adding a new layer of hierarchy to the Customizer. In the Widget Customizer, all widget areas are added to the Widgets panel, allowing widgets to take over the entire Customizer as needed. The Menu Customizer plugin does the same thing with Menus, and requires trunk accordingly.

    Upcoming Work

    My next steps are to implement menu-adding and deleting, to implement reorderability/sortability, and then to spend quite a bit of time developing a saving/previewing system that scales well (see #14134  and related). This will most likely involve creating clones of changed menu items (posts) and menus (taxonomy terms). Once all of that’s finished, the plugin should be feature-complete, and ready for iteration.

    Core Patches

    I’ve also taken the opportunity to spend a fair amount of time working on core patches related to either Menus or the Customizer, as this project is widely expanding my knowledge of both areas. A couple of examples that have made it into core include #27406 – Customizer Panels, and #23076 – which adds live menu-item label-updating to the existing Menu screen. I’m planning on continuing to work on Menus and the Customizer via tickets/patches throughout my project as time allows.

     
    • helgatheviking 3:00 am on June 28, 2014 Permalink | Log in to Reply

      The video is pretty sweet!, great work! I’m definitely interested in seeing #14134 get fixed because it has been holding up the addition of an [18584: action hook for custom menu item meta](https://core.trac.wordpress.org/ticket/18584), which is causing all menu modifying plugins (and themes) to not be compatible with each other.

      • Nick Halsey 3:21 am on June 28, 2014 Permalink | Log in to Reply

        Thanks! I’m hoping to both fix the scaling issues and add some hooks in the new interface. The addition of a hook would really open up the possibilities for what menus can do, as your plugin and others already demonstrate.

        That being said I’m thinking that an API for custom menu fields might be even better than a hook, as that would make it easier to work with and match other core patterns for this type of structure. We’re essentially looking at custom post fields here given the way menus work. I’ll definitely look into this more once I get to the initial feature-completion stage. The ongoing Metadata UI API project might be able to be integrated here in some form, too.

    • nikeo 8:28 am on June 28, 2014 Permalink | Log in to Reply

      Great work! The plugin’s code is really clean and well commented.
      Thanks for sharing

    • Rami Yushuvaev 5:05 pm on June 28, 2014 Permalink | Log in to Reply

      Have you tested this in RTL mode?

      • Nick Halsey 5:54 pm on June 29, 2014 Permalink | Log in to Reply

        Not yet, that’ll come once we’re ready to test on different devices & environments after the basic functionality is complete. That being said, I’m guessing that the core build process will handle most of it automatically.

    • Graham Armfield 10:24 am on July 8, 2014 Permalink | Log in to Reply

      I think some accessibility testing needs to be done on this to ensure that anyone not using a mouse, and screen reader users are catered for here.

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel
Skip to toolbar