Title: Fast previewing changes to Menus in the Customizer
Author: Weston Ruter
Published: July 29, 2015
Last modified: September 5, 2015

---

 [  ](https://profiles.wordpress.org/westonruter/) [Weston Ruter](https://profiles.wordpress.org/westonruter/)
10:45 pm _on_ July 29, 2015     
Tags: [4.3 ( 65 )](https://make.wordpress.org/core/tag/4-3/),
[customize ( 67 )](https://make.wordpress.org/core/tag/customize/), [dev-notes ( 648 )](https://make.wordpress.org/core/tag/dev-notes/),
[feature plugins ( 122 )](https://make.wordpress.org/core/tag/feature-plugins/),
[feature-selective-refresh ( 4 )](https://make.wordpress.org/core/tag/feature-selective-refresh/),
[kickoff ( 4 )](https://make.wordpress.org/core/tag/kickoff/), [menu-customizer ( 11 )](https://make.wordpress.org/core/tag/menu-customizer/),
[menus ( 31 )](https://make.wordpress.org/core/tag/menus/), [partial-refresh ( 2 )](https://make.wordpress.org/core/tag/partial-refresh/),
[proposal ( 40 )](https://make.wordpress.org/core/tag/proposal/)   

# Fast previewing changes to Menus in the Customizer

The foundation of the CustomizerCustomizer Tool built into WordPress core that hooks
into most modern themes. You can use it to preview and modify many of your site’s
appearance settings. is built on the concept of the “setting”, an abstract representation
of anything in WordPress: options, theme mods, posts, terms, and so on. Settings
are linked to controls which are responsible for manipulating them. When a setting
is changed it gets pushed into the preview window so that the modification can be
reviewed before being published live.

There are two ways (transports) for how a setting can be pushed into the preview:`
refresh` and `postMessage`. The `refresh` transport does a full page refresh with
the modified settings applied, and so it relies on PHPPHP The web scripting language
in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher
to apply the setting changes. The `refresh` transport is designed to be compatible
with all themes, but for heavy sites `refresh` can be excruciating slow and taxing
on the server. For this reason, the `postMessage` transport was introduced for previewing
changes. This transport uses JavaScriptJavaScript JavaScript or JS is an object-
oriented computer programming language commonly used to create interactive effects
within web browsers. WordPress makes extensive use of JS for a better user experience.
While PHP is executed on the server, JS executes within a user’s browser. [https://www.javascript.com](https://www.javascript.com/)
to apply the changes instantly in the preview without any Ajax requests or PHP calls.
This is great, but themes have to opt-in to `postMessage` transport for settings
because they must also include JavaScript code which _duplicates_ the logic which
is already being executed on the server by PHP. The `postMessage` transport violates
the DRY principle.

With that background out of the way…

### Partial Refresh of Menus

In WordPress 4.3 menu management is being added to the Customizer, extending the
types of objects that the Customizer can manipulate to include `nav_menu` taxonomyTaxonomy
A taxonomy is a way to group things together. In WordPress, some common taxonomies
are category, link, tag, or post format. [https://codex.wordpress.org/Taxonomies#Default_Taxonomies](https://codex.wordpress.org/Taxonomies#Default_Taxonomies).
terms and `nav_menu_item` posts. We wanted this menu management experience to be
fast so it had to avoid the slow full-page `refresh` transport. Nevertheless, the`
postMessage` transport wasn’t possible to use either since we wouldn’t be able to
duplicate all of the PHP menu walker logic and theme/pluginPlugin A plugin is a 
piece of software containing a group of functions that can be added to a WordPress
website. They can extend functionality or add new features to your WordPress websites.
WordPress plugins are written in the PHP programming language and integrate seamlessly
with WordPress. These can be free in the WordPress.org Plugin Directory [https://wordpress.org/plugins/](https://wordpress.org/plugins/)
or can be cost-based plugin from a third-party. extensions for rendering menus purely
in JavaScript. We also wanted to enable fast previewing of menu changes by default.
So we implemented a `postMessage`/`refresh` hybrid approach which uses `postMessage`
to sync the menus settings to the preview, and then the preview does an Ajax request
to render just the contents of the menu container, and this Ajax response is then
inserted into the DOM to replace the previous menu container. The technical name
for this approach we have been calling “partial refresh”, but you can call it “fast
preview”.

When the Customizer determines it can’t do a partial refresh, it falls back to performing
a full page refresh. Conditions for why a menu change will get a full page refresh
include:

 * if the menu was just assigned to a location for the first time or removed from
   being assigned to a location, since the theme may have some changes to the layout
   that it may need to perform;
 * or if `wp_nav_menu()` is called with with `echo` being `false`, since the theme
   may be doing some string replacement in this case which we can’t replicate in
   the partial-refresh Ajax request;
 * or if `wp_nav_menu()` is called with with a non-JSONJSON JSON, or JavaScript 
   Object Notation, is a minimal, readable format for structuring data. It is used
   primarily to transmit data between a server and web application, as an alternative
   to XML. serializable `fallback_cb`, such as a closure or a object method—this
   arg has to be empty or a string;
 * or if `wp_nav_menu()` is called with with a `walker` object instance, as opposed
   to a class name string;
 * or if `wp_nav_menu()` is called without a `theme_location` arg and the menu arg
   is not an term ID or a menu object;
 * or if the menu selected in a Custom Menu widgetWidget A WordPress Widget is a
   small block that performs a specific function. You can add these widgets in sidebars
   also known as widget-ready areas on your web page. WordPress widgets were originally
   created to provide a simple and easy-to-use way of giving design and structure
   control of the WordPress theme to the user. is changed, since partial refresh
   for widgets is not yet supported (however, see [feature plugin](https://wordpress.org/plugins/customize-partial-refresh/))—
   subsequent changes to the menu will result in fast partial refreshes if the above
   conditions

When a menu is being updated via partial refresh, the menu container will receive
a classname `customize-partial-refreshing`, which by default changes the opacity
to 25%.

### Theme Support

The fast preview for menu changes is being _enabled by default_ so that theme authors
don’t have to opt-in to the functionality like they do for instant preview (`postMessage`
transport). In general this should be fine. However, if the theme includes some 
JavaScript which dynamically manipulates the rendered menu container, such as adding
event handlers for expanding/collapsing submenus, then the theme would need to include
some JSJS JavaScript, a web scripting language typically executed in the browser.
Often used for advanced user interfaces and behaviors. to re-apply the modifications
once the menu is partial-refreshed, as the old DOM for the menu container gets replaced.

The Twenty Fifteen theme actually uses JS to expand/collapse submenu items, so it
needed a patchpatch A special text file that describes changes to code, by identifying
the files and lines which are added, removed, and altered. It may also be referred
to as a **diff**. A patch can be _applied_ to a codebase for testing. in 4.3 to 
re-setup a partial-refreshed main nav menu. In addition to firing the menu container
DOM setup logic once at `jQuery.ready()`, it now invokes the functionality whenever
the menu is partial-refreshed. See the [`initMainNavigation()` JS function](https://core.trac.wordpress.org/browser/trunk/src/wp-content/themes/twentyfifteen/js/functions.js?rev=33491#L14).

So in general, if your theme needs to dynamically initialize menus with JavaScript,
the pattern for the initialization code should be:

    ```notranslate
    jQuery(function($) {
    	function initMainNavigation( container ) {
    		/* set up container... */
    	}
    	initMainNavigation( $( '.main-navigation' ) );

    	$( document ).on( 'customize-preview-menu-refreshed', function( e, params ) {
    		if ( 'primary' === params.wpNavMenuArgs.theme_location ) {
    			initMainNavigation( params.newContainer );
    			/* optionally sync a previous menu state from params.oldContainer... */
    		}
    	});
    });
    ```

The `params` being passed to the event handler consists of the following properties:

 * `newContainer`: jQuery object containing the new menu container element retrieved
   from Ajax; this is what you would manipulate to initialize.
 * `oldContainer`: the previous jQuery object holding the element for the replaced
   menu container; this is useful if there is any state in the old menu that should
   persist in the new menu, such as which submenus are expanded (as in Twenty Fifteen).
 * `wpNavMenuArgs`: The array of arguments passed to `wp_nav_menu()` in the template,
   such as `template_location`.
 * `instanceNumber`: The index for which `wp_nav_menu()` call being updated.

## The Future

Partial refresh is an “experimental transport” introduced here specifically for 
menus. In 4.4 we hope to generalize the framework so that any setting can be setup
for fast preview, starting with widgets (see [#27355](https://core.trac.wordpress.org/ticket/27355)).
There is a [Customize Partial Refresh](https://wordpress.org/plugins/customize-partial-refresh/)
feature pluginFeature Plugin A plugin that was created with the intention of eventually
being proposed for inclusion in WordPress Core. See [Features as Plugins](https://make.wordpress.org/core/handbook/about/release-cycle/features-as-plugins/)
that implements widget partial refresh in a betaBeta A pre-release of software that
is given out to a large group of users to trial under real conditions. Beta versions
have gone through alpha testing in-house and are generally fairly close in look,
feel and function to the final product; however, design changes often occur as part
of the process. state. This partial refresh functionality I’ve also [identified as being critical for Customizer Transactions](https://make.wordpress.org/core/2015/01/26/customizer-transactions-proposal/#partial-refresh).

[#4-3](https://make.wordpress.org/core/tag/4-3/), [#customize](https://make.wordpress.org/core/tag/customize/),
[#dev-notes](https://make.wordpress.org/core/tag/dev-notes/), [#feature-plugins](https://make.wordpress.org/core/tag/feature-plugins/),
[#feature-selective-refresh](https://make.wordpress.org/core/tag/feature-selective-refresh/),
[#kickoff](https://make.wordpress.org/core/tag/kickoff/), [#menu-customizer](https://make.wordpress.org/core/tag/menu-customizer/),
[#menus](https://make.wordpress.org/core/tag/menus/), [#partial-refresh](https://make.wordpress.org/core/tag/partial-refresh/),
[#proposal](https://make.wordpress.org/core/tag/proposal/)

### Share this:

 * [  Threads ](https://make.wordpress.org/core/2015/07/29/fast-previewing-changes-to-menus-in-the-customizer/?share=threads)
 * [  Mastodon ](https://make.wordpress.org/core/2015/07/29/fast-previewing-changes-to-menus-in-the-customizer/?share=mastodon)
 * [  Bluesky ](https://make.wordpress.org/core/2015/07/29/fast-previewing-changes-to-menus-in-the-customizer/?share=bluesky)
 * [  X ](https://make.wordpress.org/core/2015/07/29/fast-previewing-changes-to-menus-in-the-customizer/?share=x)
 * [  Facebook ](https://make.wordpress.org/core/2015/07/29/fast-previewing-changes-to-menus-in-the-customizer/?share=facebook)
 * [  LinkedIn ](https://make.wordpress.org/core/2015/07/29/fast-previewing-changes-to-menus-in-the-customizer/?share=linkedin)

 1. ![](https://secure.gravatar.com/avatar/ba06f3a1d3d97c99abbe9f393acabe4b080e440ed725c39eb1d9f4d8e164a1c1?
    s=32&d=mm&r=g)
 2.  [nicholas_io](https://profiles.wordpress.org/nicholas_io/)  2:53 am _on_ July 
    30, 2015
 3. This is awesome. But what happens if the menu doesn’t have a container (container
    arg set to false)? It will fallback to a full-page refresh?
 4.  * ![](https://secure.gravatar.com/avatar/63b496ec3806485229b4f934b26643dad6e734ca6e6ef7b38c846205b01cd37f?
       s=32&d=mm&r=g)
     *  [Weston Ruter](https://profiles.wordpress.org/westonruter/)  6:16 pm _on_ July
       30, 2015
     * [@nicholas_io](https://profiles.wordpress.org/nicholas_io/): Good question! 
       I wasn’t sure actually, but I tried it out and it works fine. The critical logic
       here is found in [`WP_Customize_Nav_Menus::filter_wp_nav_menu()`](https://core.trac.wordpress.org/browser/trunk/src/wp-includes/class-wp-customize-nav-menus.php?rev=33511#L869).
     * You can see that it attaches the required CSSCSS Cascading Style Sheets. class
       names to the `class` attribute it finds. When the `container` arg is `false`
       then the root `ul` element is used, and it will have a class name if the normal
       walker is used, at least. I tried partial refresh with set to false, and it 
       continued to work as expected. As long as the `items_wrap` continues to have
       the default value of `<ul id="%1$s" class="%2$s">%3$s</ul>` then it will work.
     * We should harden this, however, to not just find the first `class` attribute,
       but look at the first (root) element and amend an existing `class` attribute
       or insert one if it doesn’t exist already.
     * ![](https://secure.gravatar.com/avatar/63b496ec3806485229b4f934b26643dad6e734ca6e6ef7b38c846205b01cd37f?
       s=32&d=mm&r=g)
     *  [Weston Ruter](https://profiles.wordpress.org/westonruter/)  6:40 pm _on_ July
       30, 2015
     * Here’s a patchpatch A special text file that describes changes to code, by identifying
       the files and lines which are added, removed, and altered. It may also be referred
       to as a **diff**. A patch can be _applied_ to a codebase for testing. for what
       I have in mind: [https://github.com/xwp/wordpress-develop/pull/110/files](https://github.com/xwp/wordpress-develop/pull/110/files)
        - ![](https://secure.gravatar.com/avatar/ba06f3a1d3d97c99abbe9f393acabe4b080e440ed725c39eb1d9f4d8e164a1c1?
          s=32&d=mm&r=g)
        -  [nicholas_io](https://profiles.wordpress.org/nicholas_io/)  1:28 am _on_
          July 31, 2015
        - It’s a good patchpatch A special text file that describes changes to code,
          by identifying the files and lines which are added, removed, and altered.
          It may also be referred to as a **diff**. A patch can be _applied_ to a codebase
          for testing. for me, the original approach could lead to problems in some
          edge cases (and from what I understand with this patch we could still have
          partial refresh even if the user alter items_wrap and remove the class attribute.)

Comments are closed.

# Post navigation

[← Old Distraction Free Writing Code Removed in 4.3](https://make.wordpress.org/core/2015/07/29/old-distraction-free-writing-code-removed-in-4-3/)

[Legacy Theme Preview Removed in 4.3 →](https://make.wordpress.org/core/2015/07/30/legacy-theme-preview-removed-in-4-3/)