<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[41726] trunk: Customize: Improve usability of Customize JS API.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/41726">41726</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/41726","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>westonruter</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2017-10-04 06:47:37 +0000 (Wed, 04 Oct 2017)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Customize: Improve usability of Customize JS API.

* Eliminate need to pass both ID and instance in calls to `Values#add()` for panels, sections, controls, settings, partials, and notifications.
* Eliminate need to supply `content` param when constructing a `Control`.
* Unwrap the `options.params` object passed in constructors to just pass a flat `options`. (Back-compat is maintained.)
* Add support for `templateId` param for `Control` to override which template is used for the content.
* Remove unused `previewer` being supplied in `Control` instances.
* Rename `classes` to `containerClasses` on `Notification`.
* Automatically supply `instanceNumber` to improve stable sorting.
* Use `api.Notifications` for notifications in settings instead of `api.Value`.

See <a href="https://core.trac.wordpress.org/ticket/30741">#30741</a>.
Fixes <a href="https://core.trac.wordpress.org/ticket/42083">#42083</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadminjscustomizecontrolsjs">trunk/src/wp-admin/js/customize-controls.js</a></li>
<li><a href="#trunksrcwpadminjscustomizenavmenusjs">trunk/src/wp-admin/js/customize-nav-menus.js</a></li>
<li><a href="#trunksrcwpadminjscustomizewidgetsjs">trunk/src/wp-admin/js/customize-widgets.js</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizemanagerphp">trunk/src/wp-includes/class-wp-customize-manager.php</a></li>
<li><a href="#trunksrcwpincludesjscustomizebasejs">trunk/src/wp-includes/js/customize-base.js</a></li>
<li><a href="#trunksrcwpincludesjscustomizepreviewwidgetsjs">trunk/src/wp-includes/js/customize-preview-widgets.js</a></li>
<li><a href="#trunksrcwpincludesjscustomizeselectiverefreshjs">trunk/src/wp-includes/js/customize-selective-refresh.js</a></li>
<li><a href="#trunktestsqunitwpadminjscustomizecontrolsjs">trunk/tests/qunit/wp-admin/js/customize-controls.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadminjscustomizecontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/js/customize-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/customize-controls.js       2017-10-04 04:10:47 UTC (rev 41725)
+++ trunk/src/wp-admin/js/customize-controls.js 2017-10-04 06:47:37 UTC (rev 41726)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30,9 +30,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                initialize: function( code, params ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        var notification = this;
</span><span class="cx" style="display: block; padding: 0 10px">                        api.Notification.prototype.initialize.call( notification, code, params );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        notification.classes += ' notification-overlay';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 notification.containerClasses += ' notification-overlay';
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ( notification.loading ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                notification.classes += ' notification-loading';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         notification.containerClasses += ' notification-loading';
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        });
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -105,17 +105,25 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 * Add notification to the collection.
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @since 4.9.0
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param {string} code - Notification code.
-                * @param {object} params - Notification params.
-                * @return {api.Notification} Added instance (or existing instance if it was already added).
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          *
+                * @param {string|wp.customize.Notification} - Notification object to add. Alternatively code may be supplied, and in that case the second notificationObject argument must be supplied.
+                * @param {wp.customize.Notification} [notificationObject] - Notification to add when first argument is the code string.
+                * @returns {wp.customize.Notification} Added notification (or existing instance if it was already added).
</ins><span class="cx" style="display: block; padding: 0 10px">                  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                add: function( code, params ) {
-                       var collection = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         add: function( notification, notificationObject ) {
+                       var collection = this, code, instance;
+                       if ( 'string' === typeof notification ) {
+                               code = notification;
+                               instance = notificationObject;
+                       } else {
+                               code = notification.code;
+                               instance = notification;
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ( ! collection.has( code ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                collection._addedIncrement += 1;
</span><span class="cx" style="display: block; padding: 0 10px">                                collection._addedOrder[ code ] = collection._addedIncrement;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        return api.Values.prototype.add.call( this, code, params );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 return api.Values.prototype.add.call( collection, code, instance );
</ins><span class="cx" style="display: block; padding: 0 10px">                 },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -269,7 +277,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        setting.id = id;
</span><span class="cx" style="display: block; padding: 0 10px">                        setting.transport = setting.transport || 'refresh';
</span><span class="cx" style="display: block; padding: 0 10px">                        setting._dirty = options.dirty || false;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        setting.notifications = new api.Values({ defaultConstructor: api.Notification });
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 setting.notifications = new api.Notifications();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Whenever the setting's value changes, refresh the preview.
</span><span class="cx" style="display: block; padding: 0 10px">                        setting.bind( setting.preview );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -745,27 +753,35 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param {string}         id - The ID for the container.
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param {object}         options - Object containing one property: params.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param {object}         options.params - Object containing the following properties.
-                * @param {string}         options.params.title - Title shown when panel is collapsed and expanded.
-                * @param {string=}        [options.params.description] - Description shown at the top of the panel.
-                * @param {number=100}     [options.params.priority] - The sort priority for the panel.
-                * @param {string=default} [options.params.type] - The type of the panel. See wp.customize.panelConstructor.
-                * @param {string=}        [options.params.content] - The markup to be used for the panel container. If empty, a JS template is used.
-                * @param {boolean=true}   [options.params.active] - Whether the panel is active or not.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param {string}         options.title - Title shown when panel is collapsed and expanded.
+                * @param {string=}        [options.description] - Description shown at the top of the panel.
+                * @param {number=100}     [options.priority] - The sort priority for the panel.
+                * @param {string}         [options.templateId] - Template selector for container.
+                * @param {string=default} [options.type] - The type of the panel. See wp.customize.panelConstructor.
+                * @param {string=}        [options.content] - The markup to be used for the panel container. If empty, a JS template is used.
+                * @param {boolean=true}   [options.active] - Whether the panel is active or not.
+                * @param {object}         [options.params] - Deprecated wrapper for the above properties.
</ins><span class="cx" style="display: block; padding: 0 10px">                  */
</span><span class="cx" style="display: block; padding: 0 10px">                initialize: function ( id, options ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        var container = this;
</span><span class="cx" style="display: block; padding: 0 10px">                        container.id = id;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        options = options || {};
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        options.params = _.defaults(
-                               options.params || {},
-                               container.defaults
-                       );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( ! Container.instanceCounter ) {
+                               Container.instanceCounter = 0;
+                       }
+                       Container.instanceCounter++;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $.extend( container, options );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $.extend( container, {
+                               params: _.defaults(
+                                       options.params || options, // Passing the params is deprecated.
+                                       container.defaults
+                               )
+                       } );
+                       if ( ! container.params.instanceNumber ) {
+                               container.params.instanceNumber = Container.instanceCounter;
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                         container.notifications = new api.Notifications();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        container.templateSelector = 'customize-' + container.containerType + '-' + container.params.type;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 container.templateSelector = container.params.templateId || 'customize-' + container.containerType + '-' + container.params.type;
</ins><span class="cx" style="display: block; padding: 0 10px">                         container.container = $( container.params.content );
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( 0 === container.container.length ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                container.container = $( container.getContainer() );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1206,16 +1222,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 * @since 4.1.0
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param {string}         id - The ID for the section.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param {object}         options - Object containing one property: params.
-                * @param {object}         options.params - Object containing the following properties.
-                * @param {string}         options.params.title - Title shown when section is collapsed and expanded.
-                * @param {string=}        [options.params.description] - Description shown at the top of the section.
-                * @param {number=100}     [options.params.priority] - The sort priority for the section.
-                * @param {string=default} [options.params.type] - The type of the section. See wp.customize.sectionConstructor.
-                * @param {string=}        [options.params.content] - The markup to be used for the section container. If empty, a JS template is used.
-                * @param {boolean=true}   [options.params.active] - Whether the section is active or not.
-                * @param {string}         options.params.panel - The ID for the panel this section is associated with.
-                * @param {string=}        [options.params.customizeAction] - Additional context information shown before the section title when expanded.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param {object}         options - Options.
+                * @param {string}         options.title - Title shown when section is collapsed and expanded.
+                * @param {string=}        [options.description] - Description shown at the top of the section.
+                * @param {number=100}     [options.priority] - The sort priority for the section.
+                * @param {string=default} [options.type] - The type of the section. See wp.customize.sectionConstructor.
+                * @param {string=}        [options.content] - The markup to be used for the section container. If empty, a JS template is used.
+                * @param {boolean=true}   [options.active] - Whether the section is active or not.
+                * @param {string}         options.panel - The ID for the panel this section is associated with.
+                * @param {string=}        [options.customizeAction] - Additional context information shown before the section title when expanded.
+                * @param {object}         [options.params] - Deprecated wrapper for the above properties.
</ins><span class="cx" style="display: block; padding: 0 10px">                  */
</span><span class="cx" style="display: block; padding: 0 10px">                initialize: function ( id, options ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        var section = this;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1838,7 +1854,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        section.container.find( '.no-themes' ).hide();
</span><span class="cx" style="display: block; padding: 0 10px">                        request = wp.ajax.post( 'customize_load_themes', params );
</span><span class="cx" style="display: block; padding: 0 10px">                        request.done(function( data ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                var themes = data.themes, themeControl, newThemeControls;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         var themes = data.themes, newThemeControls;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Stop and try again if the term changed while loading.
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( '' !== section.nextTerm || '' !== section.nextTags ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1860,20 +1876,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Add controls for each theme.
</span><span class="cx" style="display: block; padding: 0 10px">                                        _.each( themes, function( theme ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                var customizeId = section.params.action + '_theme_' + theme.id;
-                                               themeControl = new api.controlConstructor.theme( customizeId, {
-                                                       params: {
-                                                               type: 'theme',
-                                                               content: '<li id="customize-control-theme-' + section.params.action + '_' + theme.id + '" class="customize-control customize-control-theme"></li>',
-                                                               section: section.params.id,
-                                                               active: true,
-                                                               theme: theme,
-                                                               priority: section.loaded + 1
-                                                       },
-                                                       previewer: api.previewer
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         var themeControl = new api.controlConstructor.theme( section.params.action + '_theme_' + theme.id, {
+                                                       type: 'theme',
+                                                       section: section.params.id,
+                                                       theme: theme,
+                                                       priority: section.loaded + 1
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                api.control.add( customizeId, themeControl );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         api.control.add( themeControl );
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 newThemeControls.push( themeControl );
</span><span class="cx" style="display: block; padding: 0 10px">                                                section.loaded = section.loaded + 1;
</span><span class="cx" style="display: block; padding: 0 10px">                                        });
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2482,13 +2492,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param {string}         id - The ID for the panel.
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param {object}         options - Object containing one property: params.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param {object}         options.params - Object containing the following properties.
-                * @param {string}         options.params.title - Title shown when panel is collapsed and expanded.
-                * @param {string=}        [options.params.description] - Description shown at the top of the panel.
-                * @param {number=100}     [options.params.priority] - The sort priority for the panel.
-                * @param {string=default} [options.params.type] - The type of the panel. See wp.customize.panelConstructor.
-                * @param {string=}        [options.params.content] - The markup to be used for the panel container. If empty, a JS template is used.
-                * @param {boolean=true}   [options.params.active] - Whether the panel is active or not.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param {string}         options.title - Title shown when panel is collapsed and expanded.
+                * @param {string=}        [options.description] - Description shown at the top of the panel.
+                * @param {number=100}     [options.priority] - The sort priority for the panel.
+                * @param {string=default} [options.type] - The type of the panel. See wp.customize.panelConstructor.
+                * @param {string=}        [options.content] - The markup to be used for the panel container. If empty, a JS template is used.
+                * @param {boolean=true}   [options.active] - Whether the panel is active or not.
+                * @param {object}         [options.params] - Deprecated wrapper for the above properties.
</ins><span class="cx" style="display: block; padding: 0 10px">                  */
</span><span class="cx" style="display: block; padding: 0 10px">                initialize: function ( id, options ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        var panel = this;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2856,7 +2866,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        wp.updates.maybeRequestFilesystemCredentials( event );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $( document ).one( 'wp-theme-install-success', function( event, response ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                var theme = false, customizeId, themeControl;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         var theme = false, themeControl;
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if ( preview ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        api.notifications.remove( 'theme_installing' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2877,21 +2887,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Add theme control to installed section.
</span><span class="cx" style="display: block; padding: 0 10px">                                        theme.type = 'installed';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        customizeId = 'installed_theme_' + theme.id;
-                                       themeControl = new api.controlConstructor.theme( customizeId, {
-                                               params: {
-                                                       type: 'theme',
-                                                       content: $( '<li class="customize-control customize-control-theme"></li>' ).attr( 'id', 'customize-control-theme-installed_' + theme.id ).prop( 'outerHTML' ),
-                                                       section: 'installed_themes',
-                                                       active: true,
-                                                       theme: theme,
-                                                       priority: 0 // Add all newly-installed themes to the top.
-                                               },
-                                               previewer: api.previewer
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 themeControl = new api.controlConstructor.theme( 'installed_theme_' + theme.id, {
+                                               type: 'theme',
+                                               section: 'installed_themes',
+                                               theme: theme,
+                                               priority: 0 // Add all newly-installed themes to the top.
</ins><span class="cx" style="display: block; padding: 0 10px">                                         } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        api.control.add( customizeId, themeControl );
-                                       api.control( customizeId ).container.trigger( 'render-screenshot' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 api.control.add( themeControl );
+                                       api.control( themeControl.id ).container.trigger( 'render-screenshot' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Close the details modal if it's open to the installed theme.
</span><span class="cx" style="display: block; padding: 0 10px">                                        api.section.each( function( section ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2913,7 +2917,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( $( event.target ).hasClass( 'preview' ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                preview = true;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.notifications.add( 'theme_installing', new api.OverlayNotification( 'theme_installing', {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.notifications.add( new api.OverlayNotification( 'theme_installing', {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         message: api.l10n.themeDownloading,
</span><span class="cx" style="display: block; padding: 0 10px">                                        type: 'info',
</span><span class="cx" style="display: block; padding: 0 10px">                                        loading: true
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2950,7 +2954,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        urlParser.search = $.param( queryParams );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Update loading message. Everything else is handled by reloading the page.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        api.notifications.add( 'theme_previewing', new api.OverlayNotification( 'theme_previewing', {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 api.notifications.add( new api.OverlayNotification( 'theme_previewing', {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 message: api.l10n.themePreviewWait,
</span><span class="cx" style="display: block; padding: 0 10px">                                type: 'info',
</span><span class="cx" style="display: block; padding: 0 10px">                                loading: true
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3076,33 +3080,59 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * @class
</span><span class="cx" style="display: block; padding: 0 10px">         * @augments wp.customize.Class
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @param {string} id                              Unique identifier for the control instance.
-        * @param {object} options                         Options hash for the control instance.
-        * @param {object} options.params
-        * @param {object} options.params.type             Type of control (e.g. text, radio, dropdown-pages, etc.)
-        * @param {string} options.params.content          The HTML content for the control.
-        * @param {string} options.params.priority         Order of priority to show the control within the section.
-        * @param {string} options.params.active
-        * @param {string} options.params.section          The ID of the section the control belongs to.
-        * @param {string} options.params.settings.default The ID of the setting the control relates to.
-        * @param {string} options.params.settings.data
-        * @param {string} options.params.label
-        * @param {string} options.params.description
-        * @param {string} options.params.instanceNumber Order in which this instance was created in relation to other instances.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * @param {string} id                       - Unique identifier for the control instance.
+        * @param {object} options                  - Options hash for the control instance.
+        * @param {object} options.type             - Type of control (e.g. text, radio, dropdown-pages, etc.)
+        * @param {string} [options.content]        - The HTML content for the control or at least its container. This should normally be left blank and instead supplying a templateId.
+        * @param {string} [options.templateId]     - Template ID for control's content.
+        * @param {string} [options.priority=10]    - Order of priority to show the control within the section.
+        * @param {string} [options.active=true]    - Whether the control is active.
+        * @param {string} options.section          - The ID of the section the control belongs to.
+        * @param {string} options.settings.default - The ID of the setting the control relates to.
+        * @param {string} options.settings.data
+        * @param {string} options.label            - Label.
+        * @param {string} options.description      - Description.
+        * @param {number} [options.instanceNumber] - Order in which this instance was created in relation to other instances.
+        * @param {object} [options.params]         - Deprecated wrapper for the above properties.
</ins><span class="cx" style="display: block; padding: 0 10px">          */
</span><span class="cx" style="display: block; padding: 0 10px">        api.Control = api.Class.extend({
</span><span class="cx" style="display: block; padding: 0 10px">                defaultActiveArguments: { duration: 'fast', completeCallback: $.noop },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                defaults: {
+                       active: true,
+                       priority: 10
+               },
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 initialize: function( id, options ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        var control = this,
</span><span class="cx" style="display: block; padding: 0 10px">                                nodes, radios, settings;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        control.params = {};
-                       $.extend( control, options || {} );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 control.params = _.extend( {}, control.defaults );
+
+                       if ( ! api.Control.instanceCounter ) {
+                               api.Control.instanceCounter = 0;
+                       }
+                       api.Control.instanceCounter++;
+                       if ( ! control.params.instanceNumber ) {
+                               control.params.instanceNumber = api.Control.instanceCounter;
+                       }
+
+                       _.extend( control.params, options.params || options );
+                       if ( ! control.params.content ) {
+                               control.params.content = $( '<li></li>', {
+                                       id: 'customize-control-' + id.replace( /]/g, '' ).replace( /\[/g, '-' ),
+                                       'class': 'customize-control customize-control-' + control.params.type
+                               } );
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         control.id = id;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        control.selector = '#customize-control-' + id.replace( /\]/g, '' ).replace( /\[/g, '-' );
-                       control.templateSelector = 'customize-control-' + control.params.type + '-content';
-                       control.container = control.params.content ? $( control.params.content ) : $( control.selector );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 control.selector = '#customize-control-' + id.replace( /\]/g, '' ).replace( /\[/g, '-' ); // Deprecated, likely dead code from time before #28709.
+                       control.templateSelector = control.params.templateId || 'customize-control-' + control.params.type + '-content';
+                       if ( control.params.content ) {
+                               control.container = $( control.params.content );
+                       } else {
+                               control.container = $( control.selector ); // Likely dead, per above. See #28709.
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        control.deferred = {
</span><span class="cx" style="display: block; padding: 0 10px">                                embedded: new $.Deferred()
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3180,17 +3210,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Add setting notifications to the control notification.
</span><span class="cx" style="display: block; padding: 0 10px">                                        _.each( control.settings, function( setting ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                setting.notifications.bind( 'add', function( settingNotification ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        var controlNotification, code, params;
-                                                       code = setting.id + ':' + settingNotification.code;
-                                                       params = _.extend(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 var params = _.extend(
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 {},
</span><span class="cx" style="display: block; padding: 0 10px">                                                                settingNotification,
</span><span class="cx" style="display: block; padding: 0 10px">                                                                {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        setting: setting.id
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        controlNotification = new api.Notification( code, params );
-                                                       control.notifications.add( controlNotification.code, controlNotification );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 control.notifications.add( new api.Notification( setting.id + ':' + settingNotification.code, params ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 } );
</span><span class="cx" style="display: block; padding: 0 10px">                                                setting.notifications.bind( 'remove', function( settingNotification ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        control.notifications.remove( setting.id + ':' + settingNotification.code );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3472,16 +3499,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><span class="cx" style="display: block; padding: 0 10px">                _toggleActive: Container.prototype._toggleActive,
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // @todo This function appears to be dead code and can be removed.
</ins><span class="cx" style="display: block; padding: 0 10px">                 dropdownInit: function() {
</span><span class="cx" style="display: block; padding: 0 10px">                        var control      = this,
</span><span class="cx" style="display: block; padding: 0 10px">                                statuses     = this.container.find('.dropdown-status'),
</span><span class="cx" style="display: block; padding: 0 10px">                                params       = this.params,
</span><span class="cx" style="display: block; padding: 0 10px">                                toggleFreeze = false,
</span><span class="cx" style="display: block; padding: 0 10px">                                update       = function( to ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if ( typeof to === 'string' && params.statuses && params.statuses[ to ] )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ( 'string' === typeof to && params.statuses && params.statuses[ to ] ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 statuses.html( params.statuses[ to ] ).show();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        else
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 } else {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 statuses.hide();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        }
</ins><span class="cx" style="display: block; padding: 0 10px">                                 };
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Support the .dropdown class to open/close complex elements
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3492,11 +3521,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                event.preventDefault();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (!toggleFreeze)
-                                       control.container.toggleClass('open');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( ! toggleFreeze ) {
+                                       control.container.toggleClass( 'open' );
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( control.container.hasClass('open') )
-                                       control.container.parent().parent().find('li.library-selected').focus();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( control.container.hasClass( 'open' ) ) {
+                                       control.container.parent().parent().find( 'li.library-selected' ).focus();
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Don't want to fire focus and click at same time
</span><span class="cx" style="display: block; padding: 0 10px">                                toggleFreeze = true;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4869,7 +4900,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                        message = api.l10n.customCssError.plural.replace( '%d', String( errorAnnotations.length ) );
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         control.setting.notifications.add( new api.Notification( 'csslint_error', {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         message: message,
</span><span class="cx" style="display: block; padding: 0 10px">                                        type: 'error'
</span><span class="cx" style="display: block; padding: 0 10px">                                } ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5256,7 +5287,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        type: 'error',
</span><span class="cx" style="display: block; padding: 0 10px">                                        message: api.l10n.futureDateError
</span><span class="cx" style="display: block; padding: 0 10px">                                } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                control.notifications.add( notificationCode, notification );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         control.notifications.add( notification );
</ins><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                control.notifications.remove( notificationCode );
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5275,17 +5306,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        api.PreviewLinkControl = api.Control.extend({
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                /**
-                * Override the templateSelector before embedding the control into the page.
-                *
-                * @since 4.9.0
-                * @return {void}
-                */
-               embed: function() {
-                       var control = this;
-                       control.templateSelector = 'customize-preview-link-control';
-                       return api.Control.prototype.embed.apply( control, arguments );
-               },
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         defaults: _.extend( {}, api.Control.prototype.defaults, {
+                       templateId: 'customize-preview-link-control'
+               } ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><span class="cx" style="display: block; padding: 0 10px">                 * Initialize behaviors.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5386,7 +5409,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        type: 'info',
</span><span class="cx" style="display: block; padding: 0 10px">                                        message: api.l10n.saveBeforeShare
</span><span class="cx" style="display: block; padding: 0 10px">                                } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                control.notifications.add( notificationCode, notification );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         control.notifications.add( notification );
</ins><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                control.notifications.remove( notificationCode );
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6014,8 +6037,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        var previewer = this,
</span><span class="cx" style="display: block; padding: 0 10px">                                deferred, messenger, iframe;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( this._login )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( this._login ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 return this._login;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        deferred = $.Deferred();
</span><span class="cx" style="display: block; padding: 0 10px">                        this._login = deferred.promise();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6141,7 +6165,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ( ! setting.notifications.has( notification.code ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        setting.notifications.add( code, notification );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 setting.notifications.add( notification );
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                invalidSettings.push( setting.id );
</span><span class="cx" style="display: block; padding: 0 10px">                                        } );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6331,47 +6355,28 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        footerActions = $( '#customize-footer-actions' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                api.section( 'publish_settings', function( section ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        var updateButtonsState, previewLinkControl, TrashControl, trashControlInstance, trashControlId = 'trash_changeset', previewLinkControlId = 'changeset_preview_link', updateSectionActive, isSectionActive;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 var updateButtonsState, trashControl, updateSectionActive, isSectionActive;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        TrashControl = api.Control.extend( {
-
-                               // This is a temporary hack while waiting for richer JS templating and dynamic instantiation.
-                               embed: function() {
-                                       var control = this;
-                                       control.templateSelector = 'customize-trash-changeset-control';
-                                       return api.Control.prototype.embed.apply( control, arguments );
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 trashControl = new api.Control( 'trash_changeset', {
+                               type: 'button',
+                               section: section.id,
+                               priority: 30,
+                               templateId: 'customize-trash-changeset-control'
</ins><span class="cx" style="display: block; padding: 0 10px">                         } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-                       trashControlInstance = new TrashControl( trashControlId, {
-                               params: {
-                                       type: 'button',
-                                       section: section.id,
-                                       active: true,
-                                       priority: 30,
-                                       content: '<li id="customize-control-' + trashControlId + '" class="customize-control"></li>'
-                               }
-                       } );
-                       api.control.add( trashControlId, trashControlInstance );
-                       trashControlInstance.deferred.embedded.done( function() {
-                               trashControlInstance.container.find( 'button' ).on( 'click', function() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 api.control.add( trashControl );
+                       trashControl.deferred.embedded.done( function() {
+                               trashControl.container.find( 'button' ).on( 'click', function() {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         if ( confirm( api.l10n.trashConfirm ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                wp.customize.previewer.trash();
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                } );
</span><span class="cx" style="display: block; padding: 0 10px">                        } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        previewLinkControl = new api.PreviewLinkControl( previewLinkControlId, {
-                               params: {
-                                       section: section.id,
-                                       active: true,
-                                       priority: 100,
-                                       content: '<li id="customize-control-' + previewLinkControlId + '" class="customize-control"></li>'
-                               }
-                       } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 api.control.add( new api.PreviewLinkControl( 'changeset_preview_link', {
+                               section: section.id,
+                               priority: 100
+                       } ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        api.control.add( previewLinkControlId, previewLinkControl );
-
</del><span class="cx" style="display: block; padding: 0 10px">                         /**
</span><span class="cx" style="display: block; padding: 0 10px">                         * Return whether the pubish settings section should be active.
</span><span class="cx" style="display: block; padding: 0 10px">                         *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6588,7 +6593,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                api.unbind( 'change', captureSettingModifiedDuringSave );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ( invalidSettings.length ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        api.notifications.add( errorCode, new api.Notification( errorCode, {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 api.notifications.add( new api.Notification( errorCode, {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 message: ( 1 === invalidSettings.length ? api.l10n.saveBlockedError.singular : api.l10n.saveBlockedError.plural ).replace( /%s/g, String( invalidSettings.length ) ),
</span><span class="cx" style="display: block; padding: 0 10px">                                                                type: 'error',
</span><span class="cx" style="display: block; padding: 0 10px">                                                                dismissible: true,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6690,7 +6695,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ( notification ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        api.notifications.add( notification.code, notification );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 api.notifications.add( notification );
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ( response.setting_validities ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6795,7 +6800,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        customize_changeset_uuid: api.settings.changeset.uuid,
</span><span class="cx" style="display: block; padding: 0 10px">                                        nonce: api.settings.nonce.trash
</span><span class="cx" style="display: block; padding: 0 10px">                                } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.notifications.add( 'changeset_trashing', new api.OverlayNotification( 'changeset_trashing', {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.notifications.add( new api.OverlayNotification( 'changeset_trashing', {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         type: 'info',
</span><span class="cx" style="display: block; padding: 0 10px">                                        message: api.l10n.revertingChanges,
</span><span class="cx" style="display: block; padding: 0 10px">                                        loading: true
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6823,7 +6828,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        api.state( 'processing' ).set( api.state( 'processing' ).get() - 1 );
</span><span class="cx" style="display: block; padding: 0 10px">                                        api.state( 'trashing' ).set( false );
</span><span class="cx" style="display: block; padding: 0 10px">                                        api.notifications.remove( 'changeset_trashing' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        api.notifications.add( notificationCode, new api.Notification( notificationCode, {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 api.notifications.add( new api.Notification( notificationCode, {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 message: message || api.l10n.unknownError,
</span><span class="cx" style="display: block; padding: 0 10px">                                                dismissible: true,
</span><span class="cx" style="display: block; padding: 0 10px">                                                type: 'error'
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -6891,49 +6896,30 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Create Settings
</span><span class="cx" style="display: block; padding: 0 10px">                $.each( api.settings.settings, function( id, data ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        var constructor = api.settingConstructor[ data.type ] || api.Setting,
-                               setting;
-
-                       setting = new constructor( id, data.value, {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 var Constructor = api.settingConstructor[ data.type ] || api.Setting;
+                       api.add( new Constructor( id, data.value, {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 transport: data.transport,
</span><span class="cx" style="display: block; padding: 0 10px">                                previewer: api.previewer,
</span><span class="cx" style="display: block; padding: 0 10px">                                dirty: !! data.dirty
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } );
-                       api.add( id, setting );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Create Panels
</span><span class="cx" style="display: block; padding: 0 10px">                $.each( api.settings.panels, function ( id, data ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        var constructor = api.panelConstructor[ data.type ] || api.Panel,
-                               panel;
-
-                       panel = new constructor( id, {
-                               params: data
-                       } );
-                       api.panel.add( id, panel );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 var Constructor = api.panelConstructor[ data.type ] || api.Panel;
+                       api.panel.add( new Constructor( id, data ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Create Sections
</span><span class="cx" style="display: block; padding: 0 10px">                $.each( api.settings.sections, function ( id, data ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        var constructor = api.sectionConstructor[ data.type ] || api.Section,
-                               section;
-
-                       section = new constructor( id, {
-                               params: data
-                       } );
-                       api.section.add( id, section );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 var Constructor = api.sectionConstructor[ data.type ] || api.Section;
+                       api.section.add( new Constructor( id, data ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Create Controls
</span><span class="cx" style="display: block; padding: 0 10px">                $.each( api.settings.controls, function( id, data ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        var constructor = api.controlConstructor[ data.type ] || api.Control,
-                               control;
-
-                       control = new constructor( id, {
-                               params: data,
-                               previewer: api.previewer
-                       } );
-                       api.control.add( id, control );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 var Constructor = api.controlConstructor[ data.type ] || api.Control;
+                       api.control.add( new Constructor( id, data ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Focus the autofocused element
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7240,7 +7226,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                var code = 'autosave_available', onStateChange;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Since there is an autosave revision and the user hasn't loaded with autosaved, add notification to prompt to load autosaved version.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.notifications.add( code, new api.Notification( code, {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.notifications.add( new api.Notification( code, {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         message: api.l10n.autosaveNotice,
</span><span class="cx" style="display: block; padding: 0 10px">                                        type: 'warning',
</span><span class="cx" style="display: block; padding: 0 10px">                                        dismissible: true,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7893,8 +7879,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        control.element.set( 'blank' !== control.setting() );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        control.element.bind( function( to ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( ! to )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( ! to ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         last = api( 'header_textcolor' ).get();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                control.setting.set( to ? last : 'blank' );
</span><span class="cx" style="display: block; padding: 0 10px">                        });
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -7926,7 +7913,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Toggle notification when the homepage and posts page are both set and the same.
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( 'page' === showOnFront() && pageOnFrontId && pageForPostsId && pageOnFrontId === pageForPostsId ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        showOnFront.notifications.add( errorCode, new api.Notification( errorCode, {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 showOnFront.notifications.add( new api.Notification( errorCode, {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 type: 'error',
</span><span class="cx" style="display: block; padding: 0 10px">                                                message: api.l10n.pageOnFrontError
</span><span class="cx" style="display: block; padding: 0 10px">                                        } ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -8077,7 +8064,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ( headerVideoControl.active.get() ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                section.notifications.remove( noticeCode );
</span><span class="cx" style="display: block; padding: 0 10px">                                        } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                section.notifications.add( noticeCode, new api.Notification( noticeCode, {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         section.notifications.add( new api.Notification( noticeCode, {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         type: 'info',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        message: api.l10n.videoHeaderNotice
</span><span class="cx" style="display: block; padding: 0 10px">                                                } ) );
</span></span></pre></div>
<a id="trunksrcwpadminjscustomizenavmenusjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/js/customize-nav-menus.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/customize-nav-menus.js      2017-10-04 04:10:47 UTC (rev 41725)
+++ trunk/src/wp-admin/js/customize-nav-menus.js        2017-10-04 06:47:37 UTC (rev 41726)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -968,19 +968,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        menuNameControl = api.control( menuNameControlId );
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( ! menuNameControl ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                menuNameControl = new api.controlConstructor.nav_menu_name( menuNameControlId, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        params: {
-                                               type: 'nav_menu_name',
-                                               content: '<li id="customize-control-' + section.id.replace( '[', '-' ).replace( ']', '' ) + '-name" class="customize-control customize-control-nav_menu_name"></li>', // @todo core should do this for us; see #30741
-                                               label: api.Menus.data.l10n.menuNameLabel,
-                                               active: true,
-                                               section: section.id,
-                                               priority: 0,
-                                               settings: {
-                                                       'default': section.id
-                                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 type: 'nav_menu_name',
+                                       label: api.Menus.data.l10n.menuNameLabel,
+                                       section: section.id,
+                                       priority: 0,
+                                       settings: {
+                                               'default': section.id
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.control.add( menuNameControl.id, menuNameControl );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.control.add( menuNameControl );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 menuNameControl.active.set( true );
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -988,19 +984,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        menuControl = api.control( section.id );
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( ! menuControl ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                menuControl = new api.controlConstructor.nav_menu( section.id, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        params: {
-                                               type: 'nav_menu',
-                                               content: '<li id="customize-control-' + section.id.replace( '[', '-' ).replace( ']', '' ) + '" class="customize-control customize-control-nav_menu"></li>', // @todo core should do this for us; see #30741
-                                               section: section.id,
-                                               priority: 998,
-                                               active: true,
-                                               settings: {
-                                                       'default': section.id
-                                               },
-                                               menu_id: section.params.menu_id
-                                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 type: 'nav_menu',
+                                       section: section.id,
+                                       priority: 998,
+                                       settings: {
+                                               'default': section.id
+                                       },
+                                       menu_id: section.params.menu_id
</ins><span class="cx" style="display: block; padding: 0 10px">                                 } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.control.add( menuControl.id, menuControl );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.control.add( menuControl );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 menuControl.active.set( true );
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1009,19 +1001,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        menuAutoAddControl = api.control( menuAutoAddControlId );
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( ! menuAutoAddControl ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                menuAutoAddControl = new api.controlConstructor.nav_menu_auto_add( menuAutoAddControlId, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        params: {
-                                               type: 'nav_menu_auto_add',
-                                               content: '<li id="customize-control-' + section.id.replace( '[', '-' ).replace( ']', '' ) + '-auto-add" class="customize-control customize-control-nav_menu_auto_add"></li>', // @todo core should do this for us
-                                               label: '',
-                                               active: true,
-                                               section: section.id,
-                                               priority: 999,
-                                               settings: {
-                                                       'default': section.id
-                                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 type: 'nav_menu_auto_add',
+                                       label: '',
+                                       section: section.id,
+                                       priority: 999,
+                                       settings: {
+                                               'default': section.id
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.control.add( menuAutoAddControl.id, menuAutoAddControl );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.control.add( menuAutoAddControl );
</ins><span class="cx" style="display: block; padding: 0 10px">                                 menuAutoAddControl.active.set( true );
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2677,21 +2665,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Add the menu item control.
</span><span class="cx" style="display: block; padding: 0 10px">                        menuItemControl = new api.controlConstructor.nav_menu_item( customizeId, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                params: {
-                                       type: 'nav_menu_item',
-                                       content: '<li id="customize-control-nav_menu_item-' + String( placeholderId ) + '" class="customize-control customize-control-nav_menu_item"></li>',
-                                       section: menuControl.id,
-                                       priority: priority,
-                                       active: true,
-                                       settings: {
-                                               'default': customizeId
-                                       },
-                                       menu_item_id: placeholderId
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         type: 'nav_menu_item',
+                               section: menuControl.id,
+                               priority: priority,
+                               settings: {
+                                       'default': customizeId
</ins><span class="cx" style="display: block; padding: 0 10px">                                 },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                previewer: api.previewer
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         menu_item_id: placeholderId
</ins><span class="cx" style="display: block; padding: 0 10px">                         } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        api.control.add( customizeId, menuItemControl );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 api.control.add( menuItemControl );
</ins><span class="cx" style="display: block; padding: 0 10px">                         setting.preview();
</span><span class="cx" style="display: block; padding: 0 10px">                        menuControl.debouncedReflowMenuItems();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2775,17 +2758,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                         * inside via the Section's ready method.
</span><span class="cx" style="display: block; padding: 0 10px">                         */
</span><span class="cx" style="display: block; padding: 0 10px">                        menuSection = new api.Menus.MenuSection( customizeId, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                params: {
-                                       id: customizeId,
-                                       panel: 'nav_menus',
-                                       title: displayNavMenuName( name ),
-                                       customizeAction: api.Menus.data.l10n.customizingMenus,
-                                       type: 'nav_menu',
-                                       priority: 10,
-                                       menu_id: placeholderId
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         panel: 'nav_menus',
+                               title: displayNavMenuName( name ),
+                               customizeAction: api.Menus.data.l10n.customizingMenus,
+                               type: 'nav_menu',
+                               priority: 10,
+                               menu_id: placeholderId
</ins><span class="cx" style="display: block; padding: 0 10px">                         } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        api.section.add( customizeId, menuSection );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 api.section.add( menuSection );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Clear name field.
</span><span class="cx" style="display: block; padding: 0 10px">                        nameInput.val( '' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2909,20 +2889,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Add the menu section.
</span><span class="cx" style="display: block; padding: 0 10px">                                newSection = new api.Menus.MenuSection( newCustomizeId, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        params: {
-                                               id: newCustomizeId,
-                                               panel: 'nav_menus',
-                                               title: settingValue.name,
-                                               customizeAction: api.Menus.data.l10n.customizingMenus,
-                                               type: 'nav_menu',
-                                               priority: oldSection.priority.get(),
-                                               active: true,
-                                               menu_id: update.term_id
-                                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 panel: 'nav_menus',
+                                       title: settingValue.name,
+                                       customizeAction: api.Menus.data.l10n.customizingMenus,
+                                       type: 'nav_menu',
+                                       priority: oldSection.priority.get(),
+                                       menu_id: update.term_id
</ins><span class="cx" style="display: block; padding: 0 10px">                                 } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Add new control for the new menu.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.section.add( newCustomizeId, newSection );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.section.add( newSection );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Update the values for nav menus in Custom Menu controls.
</span><span class="cx" style="display: block; padding: 0 10px">                                api.control.each( function( setting ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3052,19 +3028,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Add the menu control.
</span><span class="cx" style="display: block; padding: 0 10px">                                newControl = new api.controlConstructor.nav_menu_item( newCustomizeId, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        params: {
-                                               type: 'nav_menu_item',
-                                               content: '<li id="customize-control-nav_menu_item-' + String( update.post_id ) + '" class="customize-control customize-control-nav_menu_item"></li>',
-                                               menu_id: update.post_id,
-                                               section: 'nav_menu[' + String( settingValue.nav_menu_term_id ) + ']',
-                                               priority: oldControl.priority.get(),
-                                               active: true,
-                                               settings: {
-                                                       'default': newCustomizeId
-                                               },
-                                               menu_item_id: update.post_id
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 type: 'nav_menu_item',
+                                       menu_id: update.post_id,
+                                       section: 'nav_menu[' + String( settingValue.nav_menu_term_id ) + ']',
+                                       priority: oldControl.priority.get(),
+                                       settings: {
+                                               'default': newCustomizeId
</ins><span class="cx" style="display: block; padding: 0 10px">                                         },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        previewer: api.previewer
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 menu_item_id: update.post_id
</ins><span class="cx" style="display: block; padding: 0 10px">                                 } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Remove old control.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3072,7 +3043,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                api.control.remove( oldCustomizeId );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Add new control to take its place.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.control.add( newCustomizeId, newControl );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.control.add( newControl );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // Delete the placeholder and preview the new setting.
</span><span class="cx" style="display: block; padding: 0 10px">                                oldSetting.callbacks.disable(); // Prevent setting triggering Customizer dirty state when set.
</span></span></pre></div>
<a id="trunksrcwpadminjscustomizewidgetsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/js/customize-widgets.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/customize-widgets.js        2017-10-04 04:10:47 UTC (rev 41725)
+++ trunk/src/wp-admin/js/customize-widgets.js  2017-10-04 06:47:37 UTC (rev 41726)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2098,24 +2098,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        controlConstructor = api.controlConstructor[controlType];
</span><span class="cx" style="display: block; padding: 0 10px">                        widgetFormControl = new controlConstructor( settingId, {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                params: {
-                                       settings: {
-                                               'default': settingId
-                                       },
-                                       content: controlContainer,
-                                       sidebar_id: self.params.sidebar_id,
-                                       widget_id: widgetId,
-                                       widget_id_base: widget.get( 'id_base' ),
-                                       type: controlType,
-                                       is_new: ! isExistingWidget,
-                                       width: widget.get( 'width' ),
-                                       height: widget.get( 'height' ),
-                                       is_wide: widget.get( 'is_wide' ),
-                                       active: true
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         settings: {
+                                       'default': settingId
</ins><span class="cx" style="display: block; padding: 0 10px">                                 },
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                previewer: self.setting.previewer
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         content: controlContainer,
+                               sidebar_id: self.params.sidebar_id,
+                               widget_id: widgetId,
+                               widget_id_base: widget.get( 'id_base' ),
+                               type: controlType,
+                               is_new: ! isExistingWidget,
+                               width: widget.get( 'width' ),
+                               height: widget.get( 'height' ),
+                               is_wide: widget.get( 'is_wide' )
</ins><span class="cx" style="display: block; padding: 0 10px">                         } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        api.control.add( settingId, widgetFormControl );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 api.control.add( widgetFormControl );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Make sure widget is removed from the other sidebars
</span><span class="cx" style="display: block; padding: 0 10px">                        api.each( function( otherSetting ) {
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizemanagerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-manager.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-manager.php      2017-10-04 04:10:47 UTC (rev 41725)
+++ trunk/src/wp-includes/class-wp-customize-manager.php        2017-10-04 06:47:37 UTC (rev 41726)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3604,7 +3604,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                ?>
</span><span class="cx" style="display: block; padding: 0 10px">                <script type="text/html" id="tmpl-customize-notification">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        <li class="notice notice-{{ data.type || 'info' }} {{ data.alt ? 'notice-alt' : '' }} {{ data.dismissible ? 'is-dismissible' : '' }} {{ data.classes || '' }}" data-code="{{ data.code }}" data-type="{{ data.type }}">
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 <li class="notice notice-{{ data.type || 'info' }} {{ data.alt ? 'notice-alt' : '' }} {{ data.dismissible ? 'is-dismissible' : '' }} {{ data.containerClasses || '' }}" data-code="{{ data.code }}" data-type="{{ data.type }}">
</ins><span class="cx" style="display: block; padding: 0 10px">                                 <div class="notification-message">{{{ data.message || data.code }}}</div>
</span><span class="cx" style="display: block; padding: 0 10px">                                <# if ( data.dismissible ) { #>
</span><span class="cx" style="display: block; padding: 0 10px">                                        <button type="button" class="notice-dismiss"><span class="screen-reader-text"><?php _e( 'Dismiss' ); ?></span></button>
</span></span></pre></div>
<a id="trunksrcwpincludesjscustomizebasejs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/customize-base.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/customize-base.js        2017-10-04 04:10:47 UTC (rev 41725)
+++ trunk/src/wp-includes/js/customize-base.js  2017-10-04 06:47:37 UTC (rev 41726)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -376,29 +376,44 @@
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><span class="cx" style="display: block; padding: 0 10px">                 * Add an item to the collection.
</span><span class="cx" style="display: block; padding: 0 10px">                 *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param {string} id    The ID of the item.
-                * @param {mixed}  value The item instance.
-                * @return {mixed} The new item's instance.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param {string|wp.customize.Class} item - The item instance to add, or the ID for the instance to add. When an ID string is supplied, then itemObject must be provided.
+                * @param {wp.customize.Class}        [itemObject] - The item instance when the first argument is a ID string.
+                * @return {wp.customize.Class} The new item's instance, or an existing instance if already added.
</ins><span class="cx" style="display: block; padding: 0 10px">                  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                add: function( id, value ) {
-                       if ( this.has( id ) )
-                               return this.value( id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         add: function( item, itemObject ) {
+                       var collection = this, id, instance;
+                       if ( 'string' === typeof item ) {
+                               id = item;
+                               instance = itemObject;
+                       } else {
+                               if ( 'string' !== typeof item.id ) {
+                                       throw new Error( 'Unknown key' );
+                               }
+                               id = item.id;
+                               instance = item;
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        this._value[ id ] = value;
-                       value.parent = this;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( collection.has( id ) ) {
+                               return collection.value( id );
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        collection._value[ id ] = instance;
+                       instance.parent = collection;
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         // Propagate a 'change' event on an item up to the collection.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( value.extended( api.Value ) )
-                               value.bind( this._change );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( instance.extended( api.Value ) ) {
+                               instance.bind( collection._change );
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        this.trigger( 'add', value );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 collection.trigger( 'add', instance );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // If a deferred object exists for this item,
</span><span class="cx" style="display: block; padding: 0 10px">                        // resolve it.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( this._deferreds[ id ] )
-                               this._deferreds[ id ].resolve();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( collection._deferreds[ id ] ) {
+                               collection._deferreds[ id ].resolve();
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        return this._value[ id ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 return collection._value[ id ];
</ins><span class="cx" style="display: block; padding: 0 10px">                 },
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -815,7 +830,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 * @since 4.9.0
</span><span class="cx" style="display: block; padding: 0 10px">                 * @var {string}
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                classes: '',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         containerClasses: '',
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /**
</span><span class="cx" style="display: block; padding: 0 10px">                 * Initialize notification.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -829,7 +844,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param {string}   [params.setting] - Related setting ID.
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param {Function} [params.template] - Function for rendering template. If not provided, this will come from templateId.
</span><span class="cx" style="display: block; padding: 0 10px">                 * @param {string}   [params.templateId] - ID for template to render the notification.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                 * @param {string}   [params.classes] - Additional class names to add to the notification container.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+          * @param {string}   [params.containerClasses] - Additional class names to add to the notification container.
</ins><span class="cx" style="display: block; padding: 0 10px">                  * @param {boolean}  [params.dismissible] - Whether the notification can be dismissed.
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><span class="cx" style="display: block; padding: 0 10px">                initialize: function( code, params ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -844,7 +859,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        setting: null,
</span><span class="cx" style="display: block; padding: 0 10px">                                        template: null,
</span><span class="cx" style="display: block; padding: 0 10px">                                        dismissible: false,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        classes: ''
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 containerClasses: ''
</ins><span class="cx" style="display: block; padding: 0 10px">                                 },
</span><span class="cx" style="display: block; padding: 0 10px">                                params
</span><span class="cx" style="display: block; padding: 0 10px">                        );
</span></span></pre></div>
<a id="trunksrcwpincludesjscustomizepreviewwidgetsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/customize-preview-widgets.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/customize-preview-widgets.js     2017-10-04 04:10:47 UTC (rev 41725)
+++ trunk/src/wp-includes/js/customize-preview-widgets.js       2017-10-04 06:47:37 UTC (rev 41726)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -407,7 +407,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                wasInserted = true;
</span><span class="cx" style="display: block; padding: 0 10px">                        } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        api.selectiveRefresh.partial.add( widgetPartial.id, widgetPartial );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 api.selectiveRefresh.partial.add( widgetPartial );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( wasInserted ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                sidebarPartial.reflowWidgets();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -510,7 +510,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                sidebarArgs: registeredSidebar
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                api.selectiveRefresh.partial.add( partial.id, partial );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         api.selectiveRefresh.partial.add( partial );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                } );
</span><span class="cx" style="display: block; padding: 0 10px">        };
</span></span></pre></div>
<a id="trunksrcwpincludesjscustomizeselectiverefreshjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/js/customize-selective-refresh.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/customize-selective-refresh.js   2017-10-04 04:10:47 UTC (rev 41725)
+++ trunk/src/wp-includes/js/customize-selective-refresh.js     2017-10-04 06:47:37 UTC (rev 41726)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -877,7 +877,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                partialOptions.constructingContainerContext = containerElement.data( 'customize-partial-placement-context' ) || {};
</span><span class="cx" style="display: block; padding: 0 10px">                                Constructor = self.partialConstructor[ containerElement.data( 'customize-partial-type' ) ] || self.Partial;
</span><span class="cx" style="display: block; padding: 0 10px">                                partial = new Constructor( id, partialOptions );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                self.partial.add( partial.id, partial );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         self.partial.add( partial );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        /*
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -918,7 +918,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( ! partial ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                Constructor = self.partialConstructor[ data.type ] || self.Partial;
</span><span class="cx" style="display: block; padding: 0 10px">                                partial = new Constructor( id, { params: data } );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                self.partial.add( id, partial );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         self.partial.add( partial );
</ins><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                _.extend( partial.params, data );
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span></span></pre></div>
<a id="trunktestsqunitwpadminjscustomizecontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/qunit/wp-admin/js/customize-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/qunit/wp-admin/js/customize-controls.js       2017-10-04 04:10:47 UTC (rev 41725)
+++ trunk/tests/qunit/wp-admin/js/customize-controls.js 2017-10-04 06:47:37 UTC (rev 41726)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -306,13 +306,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        type: 'default',
</span><span class="cx" style="display: block; padding: 0 10px">                        content: null,
</span><span class="cx" style="display: block; padding: 0 10px">                        active: true,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        instanceNumber: null,
</del><span class="cx" style="display: block; padding: 0 10px">                         customizeAction: ''
</span><span class="cx" style="display: block; padding: 0 10px">                };
</span><span class="cx" style="display: block; padding: 0 10px">                jQuery.each( defaultParams, function ( key, value ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        ok( 'undefined' !== typeof section.params[ key ] );
</span><span class="cx" style="display: block; padding: 0 10px">                        equal( value, section.params[ key ] );
</span><span class="cx" style="display: block; padding: 0 10px">                } );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                ok( _.isNumber( section.params.instanceNumber ) );
</ins><span class="cx" style="display: block; padding: 0 10px">         } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -417,13 +417,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        priority: 100,
</span><span class="cx" style="display: block; padding: 0 10px">                        type: 'default',
</span><span class="cx" style="display: block; padding: 0 10px">                        content: null,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        active: true,
-                       instanceNumber: null
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 active: true
</ins><span class="cx" style="display: block; padding: 0 10px">                 };
</span><span class="cx" style="display: block; padding: 0 10px">                jQuery.each( defaultParams, function ( key, value ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        ok( 'undefined' !== typeof panel.params[ key ] );
</span><span class="cx" style="display: block; padding: 0 10px">                        equal( value, panel.params[ key ] );
</span><span class="cx" style="display: block; padding: 0 10px">                } );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                ok( _.isNumber( panel.params.instanceNumber ) );
</ins><span class="cx" style="display: block; padding: 0 10px">         } );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        module( 'Dynamically-created Customizer Setting Model' );
</span></span></pre>
</div>
</div>

</body>
</html>