Make WordPress Core

Changeset 41768


Ignore:
Timestamp:
10/05/2017 02:21:22 AM (9 years ago)
Author:
westonruter
Message:

Customize: Improve the menu creation flow.

Often, folks run into two issues when they create new menus: they click "Add a Menu" thinking it will add a new page to their menu, or they forget to assign their new menu to a location, and then wonder why it doesn't show up on their site.

This commit rearranges the order of items in the menu panel, and updates the flow for creating a menu by breaking it up into steps. Additionally, more help text has been added to guide people through the process of creating a menu.

Also adds default type lookups for Panel and Section instances. See #30741.

Props bpayton, obenland, westonruter, celloexpessions, afercia, melchoyce, zoonini, michelleweber.
Fixes #40104.

Location:
trunk
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/customize-controls.css

    r41750 r41768  
    558558}
    559559
    560 #customize-theme-controls .control-panel-content .control-section:nth-child(2),
    561 #customize-theme-controls .control-panel-nav_menus .control-section:nth-child(3) {
     560#customize-theme-controls .control-panel-content:not(.control-panel-nav_menus) .control-section:nth-child(2),
     561#customize-theme-controls .control-panel-nav_menus .control-section-nav_menu,
     562#customize-theme-controls .control-section-nav_menu_locations .accordion-section-title {
    562563        border-top: 1px solid #ddd;
     564}
     565
     566#customize-theme-controls .control-panel-nav_menus .control-section-nav_menu + .control-section-nav_menu {
     567        border-top: none;
    563568}
    564569
    … …  
    662667}
    663668
    664 .customize-section-description-container {
     669.customize-section-description-container,
     670.control-section-nav_menu .customize-section-description-container {
    665671        margin-bottom: 15px;
    666672}
  • trunk/src/wp-admin/css/customize-nav-menus.css

    r41711 r41768  
    11#customize-theme-controls #accordion-section-menu_locations {
    22        position: relative;
    3         margin-bottom: 15px;
     3        margin-top: 15px;
    44}
    55
    66#customize-theme-controls #accordion-section-menu_locations > .accordion-section-title {
    77        border-bottom-color: #ddd;
     8        margin-top: 15px;
     9}
     10
     11#customize-theme-controls .customize-section-title-nav_menus-heading,
     12#customize-theme-controls .customize-section-title-menu_locations-heading,
     13#customize-theme-controls .customize-section-title-menu_locations-description {
     14        padding: 0 12px 0 12px;
     15}
     16
     17#customize-theme-controls .customize-control-description.customize-section-title-menu_locations-description {
     18        /* Override the default italic style for control descriptions */
     19        font-style: normal;
    820}
    921
    … …  
    2638        vertical-align: middle;
    2739        line-height: 28px;
     40}
     41
     42#customize-controls .customize-control-nav_menu_name {
     43        margin-bottom: 12px;
     44}
     45
     46.customize-control-nav_menu_name p:last-of-type {
     47        margin-bottom: 0;
     48}
     49
     50#customize-new-menu-submit {
     51        float: right;
     52        min-width: 85px;
     53}
     54
     55#customize-new-menu-submit-description {
     56        margin: 0;
    2857}
    2958
    … …  
    176205}
    177206
    178 .menu-settings .customize-control-checkbox label {
     207.wp-customizer .menu-location-settings {
     208        margin-top: 12px;
     209        border-top: none;
     210}
     211
     212.wp-customizer .control-section-nav_menu .menu-location-settings {
     213        margin-top: 24px;
     214        border-top: 1px solid #ddd;
     215        padding-top: 12px;
     216}
     217
     218.menu-settings .customize-control-checkbox label,
     219.menu-location-settings .customize-control-checkbox label {
    179220        line-height: 1;
    180221}
    181222
    182223/* @todo update selector or potentially remove */
    183 .menu-settings .customize-control.customize-control-checkbox {
     224.menu-settings .customize-control.customize-control-checkbox,
     225.menu-location-settings .customize-control.customize-control-checkbox {
    184226        margin-bottom: 8px; /* Override collapsing at smaller viewports. */
    185227}
    … …  
    739781#accordion-section-add_menu {
    740782        margin: 15px 12px;
    741         overflow: hidden;
    742 }
    743 
    744 .new-menu-section-content {
    745         display: none;
    746         padding: 15px 0 0 0;
    747         clear: both;
    748 }
    749 
    750 /* @todo update selector */
    751 #accordion-section-add_menu .accordion-section-title {
    752         padding-left: 45px;
    753 }
    754 
    755 /* @todo update selector */
    756 #accordion-section-add_menu .accordion-section-title:before {
    757         font: normal 20px/1 dashicons;
    758         position: absolute;
    759         top: 12px;
    760         left: 14px;
    761         content: "\f132";
     783        text-align: right;
     784}
     785
     786#accordion-section-add_menu h3,
     787#accordion-section-add_menu .customize-add-menu-button {
     788        margin: 0;
     789}
     790
     791#accordion-section-add_menu .customize-add-menu-button {
     792        font-weight: normal;
    762793}
    763794
    … …  
    773804}
    774805
     806.assigned-menu-locations-title p {
     807        margin: 0 0 8px 0;
     808}
     809
    775810li.assigned-to-menu-location .menu-delete-item {
    776811        display: none;
    … …  
    809844}
    810845
    811 .customize-control-nav_menu {
     846.customize-control-nav_menu .new-menu-item-invitation {
     847        margin-top: 0;
     848        margin-bottom: 0;
     849}
     850
     851.customize-control-nav_menu .customize-control-nav_menu-buttons {
    812852        margin-top: 12px;
    813853}
  • trunk/src/wp-admin/js/customize-controls.js

    r41750 r41768  
    12351235                 */
    12361236                initialize: function ( id, options ) {
    1237                         var section = this;
    1238                         Container.prototype.initialize.call( section, id, options );
     1237                        var section = this, params;
     1238                        params = options.params || options;
     1239
     1240                        // Look up the type if one was not supplied.
     1241                        if ( ! params.type ) {
     1242                                _.find( api.sectionConstructor, function( Constructor, type ) {
     1243                                        if ( Constructor === section.constructor ) {
     1244                                                params.type = type;
     1245                                                return true;
     1246                                        }
     1247                                        return false;
     1248                                } );
     1249                        }
     1250
     1251                        Container.prototype.initialize.call( section, id, params );
    12391252
    12401253                        section.id = id;
    … …  
    25082521                 */
    25092522                initialize: function ( id, options ) {
    2510                         var panel = this;
    2511                         Container.prototype.initialize.call( panel, id, options );
     2523                        var panel = this, params;
     2524                        params = options.params || options;
     2525
     2526                        // Look up the type if one was not supplied.
     2527                        if ( ! params.type ) {
     2528                                _.find( api.panelConstructor, function( Constructor, type ) {
     2529                                        if ( Constructor === panel.constructor ) {
     2530                                                params.type = type;
     2531                                                return true;
     2532                                        }
     2533                                        return false;
     2534                                } );
     2535                        }
     2536
     2537                        Container.prototype.initialize.call( panel, id, params );
     2538
    25122539                        panel.embed();
    25132540                        panel.deferred.embedded.done( function () {
    … …  
    30963123         * @param {string} options.section          - The ID of the section the control belongs to.
    30973124         * @param {mixed}  [options.setting]        - The ID of the main setting or an instance of this setting.
    3098          * @param {mixed}  options.settings         - An object with keys (e.g. default) that maps to setting IDs or Setting/Value objects, or an array of setting IDs or Setting/Value objects.   
     3125         * @param {mixed}  options.settings         - An object with keys (e.g. default) that maps to setting IDs or Setting/Value objects, or an array of setting IDs or Setting/Value objects.
    30993126         * @param {mixed}  options.settings.default - The ID of the setting the control relates to.
    31003127         * @param {string} options.settings.data    - @todo Is this used?
    … …  
    31083135
    31093136                defaults: {
     3137                        label: '',
     3138                        description: '',
    31103139                        active: true,
    31113140                        priority: 10
  • trunk/src/wp-admin/js/customize-nav-menus.js

    r41726 r41768  
    812812                                panel.saveManageColumnsState();
    813813                        });
     814
     815                        // Wait until after construction to patch the UI
     816                        _.defer( function () {
     817
     818                                panel.contentContainer.find( '#accordion-section-menu_locations' ).prepend(
     819                                        wp.template( 'nav-menu-locations-header' )( api.Menus.data )
     820                                );
     821
     822                                panel.contentContainer.find( '#accordion-section-add_menu .accordion-section-title' ).replaceWith(
     823                                        wp.template( 'nav-menu-create-menu-section-title' )
     824                                );
     825                        } );
    814826                },
    815827
    … …  
    962974
    963975                populateControls: function() {
    964                         var section = this, menuNameControlId, menuAutoAddControlId, menuControl, menuNameControl, menuAutoAddControl;
     976                        var section = this,
     977                                menuNameControlId,
     978                                menuLocationsControlId,
     979                                menuAutoAddControlId,
     980                                menuDeleteControlId,
     981                                menuControl,
     982                                menuNameControl,
     983                                menuLocationsControl,
     984                                menuAutoAddControl,
     985                                menuDeleteControl;
    965986
    966987                        // Add the control for managing the menu name.
    … …  
    9971018                        }
    9981019
     1020                        // Add the menu locations control.
     1021                        menuLocationsControlId = section.id + '[locations]';
     1022                        menuLocationsControl = api.control( menuLocationsControlId );
     1023                        if ( ! menuLocationsControl ) {
     1024                                menuLocationsControl = new api.controlConstructor.nav_menu_locations( menuLocationsControlId, {
     1025                                        section: section.id,
     1026                                        priority: 999,
     1027                                        settings: {
     1028                                                'default': section.id
     1029                                        },
     1030                                        menu_id: section.params.menu_id
     1031                                } );
     1032                                api.control.add( menuLocationsControl.id, menuLocationsControl );
     1033                                menuControl.active.set( true );
     1034                        }
     1035
    9991036                        // Add the control for managing the menu auto_add.
    10001037                        menuAutoAddControlId = section.id + '[auto_add]';
    … …  
    10051042                                        label: '',
    10061043                                        section: section.id,
    1007                                         priority: 999,
     1044                                        priority: 1000,
    10081045                                        settings: {
    10091046                                                'default': section.id
    … …  
    10141051                        }
    10151052
     1053                        // Add the control for deleting the menu
     1054                        menuDeleteControlId = section.id + '[delete]';
     1055                        menuDeleteControl = api.control( menuDeleteControlId );
     1056                        if ( ! menuDeleteControl ) {
     1057                                menuDeleteControl = new api.Control( menuDeleteControlId, {
     1058                                        section: section.id,
     1059                                        priority: 1001,
     1060                                        templateId: 'nav-menu-delete-button'
     1061                                } );
     1062                                api.control.add( menuDeleteControl.id, menuDeleteControl );
     1063                                menuDeleteControl.active.set( true );
     1064                                menuDeleteControl.deferred.embedded.done( function () {
     1065                                        menuDeleteControl.container.find( 'button' ).on( 'click', function() {
     1066                                                var menuId = section.params.menu_id;
     1067                                                var menuControl = api.Menus.getMenuControl( menuId );
     1068                                                menuControl.setting.set( false );
     1069                                        });
     1070                                } );
     1071                        }
    10161072                },
    10171073
    … …  
    10941150         *
    10951151         * Customizer section for new menus.
    1096          * Note that 'new_menu' must match the WP_Customize_New_Menu_Section::$type.
    10971152         *
    10981153         * @constructor
    … …  
    11071162                 */
    11081163                attachEvents: function() {
    1109                         var section = this;
    1110                         this.container.on( 'click', '.add-menu-toggle', function() {
    1111                                 if ( section.expanded() ) {
    1112                                         section.collapse();
    1113                                 } else {
    1114                                         section.expand();
    1115                                 }
    1116                         });
    1117                 },
    1118 
    1119                 /**
    1120                  * Update UI to reflect expanded state.
    1121                  *
    1122                  * @since 4.1.0
    1123                  *
    1124                  * @param {Boolean} expanded
    1125                  */
    1126                 onChangeExpanded: function( expanded ) {
    11271164                        var section = this,
    1128                                 button = section.container.find( '.add-menu-toggle' ),
    1129                                 content = section.contentContainer,
    1130                                 customizer = section.headContainer.closest( '.wp-full-overlay-sidebar-content' );
    1131                         if ( expanded ) {
    1132                                 button.addClass( 'open' );
    1133                                 button.attr( 'aria-expanded', 'true' );
    1134                                 content.slideDown( 'fast', function() {
    1135                                         customizer.scrollTop( customizer.height() );
    1136                                 });
    1137                         } else {
    1138                                 button.removeClass( 'open' );
    1139                                 button.attr( 'aria-expanded', 'false' );
    1140                                 content.slideUp( 'fast' );
    1141                                 content.find( '.menu-name-field' ).removeClass( 'invalid' );
    1142                         }
    1143                 },
    1144 
    1145                 /**
    1146                  * Find the content element.
    1147                  *
    1148                  * @since 4.7.0
    1149                  *
    1150                  * @returns {jQuery} Content UL element.
    1151                  */
    1152                 getContent: function() {
    1153                         return this.container.find( 'ul:first' );
     1165                                container = section.container,
     1166                                contentContainer = section.contentContainer;
     1167
     1168                        /*
     1169                         * We have to manually handle section expanded because we do not
     1170                         * apply the `accordion-section-title` class to this button-driven section.
     1171                         */
     1172                        container.on( 'click', '.customize-add-menu-button', function() {
     1173                                section.expand();
     1174                        });
     1175
     1176                        contentContainer.on( 'keydown', '.menu-name-field', function( event ) {
     1177                                if ( 13 === event.which ) { // Enter.
     1178                                        section.submit();
     1179                                }
     1180                        } );
     1181                        contentContainer.on( 'click', '#customize-new-menu-submit', function( event ) {
     1182                                section.submit();
     1183                                event.stopPropagation();
     1184                                event.preventDefault();
     1185                        } );
     1186
     1187                        api.Section.prototype.attachEvents.apply( this, arguments );
     1188                },
     1189
     1190                /**
     1191                 * Set up the control.
     1192                 *
     1193                 * @since 4.9.0
     1194                 */
     1195                ready: function() {
     1196                        this.populateControls();
     1197                },
     1198
     1199                /**
     1200                 * Create the controls for this section.
     1201                 *
     1202                 * @since 4.9.0
     1203                 */
     1204                populateControls: function() {
     1205                        var section = this,
     1206                                menuNameControlId,
     1207                                menuLocationsControlId,
     1208                                newMenuSubmitControlId,
     1209                                menuNameControl,
     1210                                menuLocationsControl,
     1211                                newMenuSubmitControl;
     1212
     1213                        menuNameControlId = section.id + '[name]';
     1214                        menuNameControl = api.control( menuNameControlId );
     1215                        if ( ! menuNameControl ) {
     1216                                menuNameControl = new api.controlConstructor.nav_menu_name( menuNameControlId, {
     1217                                        label: api.Menus.data.l10n.menuNameLabel,
     1218                                        description: api.Menus.data.l10n.newMenuNameDescription,
     1219                                        section: section.id,
     1220                                        priority: 0
     1221                                } );
     1222                                api.control.add( menuNameControl.id, menuNameControl );
     1223                                menuNameControl.active.set( true );
     1224                        }
     1225
     1226                        menuLocationsControlId = section.id + '[locations]';
     1227                        menuLocationsControl = api.control( menuLocationsControlId );
     1228                        if ( ! menuLocationsControl ) {
     1229                                menuLocationsControl = new api.controlConstructor.nav_menu_locations( menuLocationsControlId, {
     1230                                        section: section.id,
     1231                                        priority: 1,
     1232                                        menu_id: ''
     1233                                } );
     1234                                api.control.add( menuLocationsControlId, menuLocationsControl );
     1235                                menuLocationsControl.active.set( true );
     1236                        }
     1237
     1238                        newMenuSubmitControlId = section.id + '[submit]';
     1239                        newMenuSubmitControl = api.control( newMenuSubmitControlId );
     1240                        if ( !newMenuSubmitControl ) {
     1241                                newMenuSubmitControl = new api.Control( newMenuSubmitControlId, {
     1242                                        section: section.id,
     1243                                        priority: 1,
     1244                                        templateId: 'nav-menu-submit-new-button'
     1245                                } );
     1246                                api.control.add( newMenuSubmitControlId, newMenuSubmitControl );
     1247                                newMenuSubmitControl.active.set( true );
     1248                        }
     1249                },
     1250
     1251                /**
     1252                 * Create the new menu with name and location supplied by the user.
     1253                 *
     1254                 * @since 4.9.0
     1255                 */
     1256                submit: function() {
     1257                        var section = this,
     1258                                contentContainer = section.contentContainer,
     1259                                nameInput = contentContainer.find( '.menu-name-field' ).first(),
     1260                                name = nameInput.val(),
     1261                                menuSection,
     1262                                customizeId,
     1263                                placeholderId = api.Menus.generatePlaceholderAutoIncrementId();
     1264
     1265                        if ( ! name ) {
     1266                                nameInput.addClass( 'invalid' );
     1267                                nameInput.focus();
     1268                                return;
     1269                        }
     1270
     1271                        customizeId = 'nav_menu[' + String( placeholderId ) + ']';
     1272
     1273                        // Register the menu control setting.
     1274                        api.create( customizeId, customizeId, {}, {
     1275                                type: 'nav_menu',
     1276                                transport: api.Menus.data.settingTransport,
     1277                                previewer: api.previewer
     1278                        } );
     1279                        api( customizeId ).set( $.extend(
     1280                                {},
     1281                                api.Menus.data.defaultSettingValues.nav_menu,
     1282                                {
     1283                                        name: name
     1284                                }
     1285                        ) );
     1286
     1287                        /*
     1288                         * Add the menu section (and its controls).
     1289                         * Note that this will automatically create the required controls
     1290                         * inside via the Section's ready method.
     1291                         */
     1292                        menuSection = new api.Menus.MenuSection( customizeId, {
     1293                                panel: 'nav_menus',
     1294                                title: displayNavMenuName( name ),
     1295                                customizeAction: api.Menus.data.l10n.customizingMenus,
     1296                                priority: 10,
     1297                                menu_id: placeholderId
     1298                        } );
     1299                        api.section.add( customizeId, menuSection );
     1300
     1301                        // Clear name field.
     1302                        nameInput.val( '' );
     1303                        nameInput.removeClass( 'invalid' );
     1304
     1305                        contentContainer.find( '.assigned-menu-location input[type=checkbox]' ).each( function() {
     1306                                var checkbox = $( this ),
     1307                                navMenuLocationSetting;
     1308
     1309                                if ( checkbox.prop( 'checked' ) ) {
     1310                                        navMenuLocationSetting = api( 'nav_menu_locations[' + checkbox.data( 'location-id' ) + ']' );
     1311                                        navMenuLocationSetting.set( placeholderId );
     1312
     1313                                        // Reset state for next new menu
     1314                                        checkbox.prop( 'checked', false );
     1315                                }
     1316                        } );
     1317
     1318                        wp.a11y.speak( api.Menus.data.l10n.menuAdded );
     1319
     1320                        // Focus on the new menu section.
     1321                        api.section( customizeId ).focus(); // @todo should we focus on the new menu's control and open the add-items panel? Thinking user flow...
    11541322                }
    11551323        });
    … …  
    15131681                                        $adjacentFocusTarget.focus(); // keyboard accessibility
    15141682                                } );
     1683
     1684                                control.setting.set( false );
    15151685                        } );
    15161686                },
    … …  
    20352205
    20362206                ready: function() {
     2207                        var control = this;
     2208
     2209                        if ( control.setting ) {
     2210                                var settingValue = control.setting();
     2211
     2212                                control.nameElement = new api.Element( control.container.find( '.menu-name-field' ) );
     2213
     2214                                control.nameElement.bind(function( value ) {
     2215                                        var settingValue = control.setting();
     2216                                        if ( settingValue && settingValue.name !== value ) {
     2217                                                settingValue = _.clone( settingValue );
     2218                                                settingValue.name = value;
     2219                                                control.setting.set( settingValue );
     2220                                        }
     2221                                });
     2222                                if ( settingValue ) {
     2223                                        control.nameElement.set( settingValue.name );
     2224                                }
     2225
     2226                                control.setting.bind(function( object ) {
     2227                                        if ( object ) {
     2228                                                control.nameElement.set( object.name );
     2229                                        }
     2230                                });
     2231                        }
     2232                }
     2233        });
     2234
     2235        /**
     2236         * wp.customize.Menus.MenuLocationsControl
     2237         *
     2238         * Customizer control for a nav menu's locations.
     2239         *
     2240         * @since 4.9.0
     2241         * @constructor
     2242         * @augments wp.customize.Control
     2243         */
     2244        api.Menus.MenuLocationsControl = api.Control.extend({
     2245
     2246                /**
     2247                 * Set up the control.
     2248                 *
     2249                 * @since 4.9.0
     2250                 */
     2251                ready: function () {
     2252                        var control = this;
     2253
     2254                        control.container.find( '.assigned-menu-location' ).each(function() {
     2255                                var container = $( this ),
     2256                                        checkbox = container.find( 'input[type=checkbox]' ),
     2257                                        element = new api.Element( checkbox ),
     2258                                        navMenuLocationSetting = api( 'nav_menu_locations[' + checkbox.data( 'location-id' ) + ']' ),
     2259                                        isNewMenu = control.params.menu_id === '',
     2260                                        updateCheckbox = isNewMenu ? _.noop : function( checked ) {
     2261                                                element.set( checked );
     2262                                        },
     2263                                        updateSetting = isNewMenu ? _.noop : function( checked ) {
     2264                                                navMenuLocationSetting.set( checked ? control.params.menu_id : 0 );
     2265                                        },
     2266                                        updateSelectedMenuLabel = function( selectedMenuId ) {
     2267                                                var menuSetting = api( 'nav_menu[' + String( selectedMenuId ) + ']' );
     2268                                                if ( ! selectedMenuId || ! menuSetting || ! menuSetting() ) {
     2269                                                        container.find( '.theme-location-set' ).hide();
     2270                                                } else {
     2271                                                        container.find( '.theme-location-set' ).show().find( 'span' ).text( displayNavMenuName( menuSetting().name ) );
     2272                                                }
     2273                                        };
     2274
     2275                                updateCheckbox( navMenuLocationSetting.get() === control.params.menu_id );
     2276
     2277                                checkbox.on( 'change', function() {
     2278                                        // Note: We can't use element.bind( function( checked ){ ... } ) here because it will trigger a change as well.
     2279                                        updateSetting( this.checked );
     2280                                } );
     2281
     2282                                navMenuLocationSetting.bind( function( selectedMenuId ) {
     2283                                        updateCheckbox( selectedMenuId === control.params.menu_id );
     2284                                        updateSelectedMenuLabel( selectedMenuId );
     2285                                } );
     2286                                updateSelectedMenuLabel( navMenuLocationSetting.get() );
     2287                        });
     2288                }
     2289        });
     2290
     2291        /**
     2292         * wp.customize.Menus.MenuAutoAddControl
     2293         *
     2294         * Customizer control for a nav menu's auto add.
     2295         *
     2296         * @constructor
     2297         * @augments wp.customize.Control
     2298         */
     2299        api.Menus.MenuAutoAddControl = api.Control.extend({
     2300
     2301                ready: function() {
    20372302                        var control = this,
    20382303                                settingValue = control.setting();
    … …  
    20532318                        };
    20542319
    2055                         control.nameElement = new api.Element( control.container.find( '.menu-name-field' ) );
    2056 
    2057                         control.nameElement.bind(function( value ) {
    2058                                 var settingValue = control.setting();
    2059                                 if ( settingValue && settingValue.name !== value ) {
    2060                                         settingValue = _.clone( settingValue );
    2061                                         settingValue.name = value;
    2062                                         control.setting.set( settingValue );
    2063                                 }
    2064                         });
    2065                         if ( settingValue ) {
    2066                                 control.nameElement.set( settingValue.name );
    2067                         }
    2068 
    2069                         control.setting.bind(function( object ) {
    2070                                 if ( object ) {
    2071                                         control.nameElement.set( object.name );
    2072                                 }
    2073                         });
    2074                 }
    2075 
    2076         });
    2077 
    2078         /**
    2079          * wp.customize.Menus.MenuAutoAddControl
    2080          *
    2081          * Customizer control for a nav menu's auto add.
    2082          *
    2083          * @constructor
    2084          * @augments wp.customize.Control
    2085          */
    2086         api.Menus.MenuAutoAddControl = api.Control.extend({
    2087 
    2088                 ready: function() {
    2089                         var control = this,
    2090                                 settingValue = control.setting();
    2091 
    2092                         /*
    2093                          * Since the control is not registered in PHP, we need to prevent the
    2094                          * preview's sending of the activeControls to result in this control
    2095                          * being deactivated.
    2096                          */
    2097                         control.active.validate = function() {
    2098                                 var value, section = api.section( control.section() );
    2099                                 if ( section ) {
    2100                                         value = section.active();
    2101                                 } else {
    2102                                         value = false;
    2103                                 }
    2104                                 return value;
    2105                         };
    2106 
    21072320                        control.autoAddElement = new api.Element( control.container.find( 'input[type=checkbox].auto_add' ) );
    21082321
    … …  
    21812394
    21822395                        this._setupAddition();
    2183                         this._setupLocations();
    21842396                        this._setupTitle();
    21852397
    … …  
    22112423                                }
    22122424                        }
     2425
     2426                        /*
     2427                         * Wait for menu items to be added.
     2428                         * Ideally, we'd bind to an event indicating construction is complete,
     2429                         * but deferring appears to be the best option today.
     2430                         */
     2431                        _.defer( function () {
     2432                                control.updateInvitationVisibility();
     2433                        } );
    22132434                },
    22142435
    … …  
    22362457                                }
    22372458                        } );
    2238 
    2239                         control.container.find( '.menu-delete-item .button-link-delete' ).on( 'click', function( event ) {
    2240                                 event.preventDefault();
    2241                                 control.setting.set( false );
    2242                         });
    22432459                },
    22442460
    … …  
    23922608                        widgetTemplate.find( '.nav-menu-widget-no-menus-message:first' ).toggle( 0 === navMenuCount );
    23932609                        widgetTemplate.find( 'option[value=' + String( menuId ) + ']' ).remove();
    2394                 },
    2395 
    2396                 // Setup theme location checkboxes.
    2397                 _setupLocations: function() {
    2398                         var control = this;
    2399 
    2400                         control.container.find( '.assigned-menu-location' ).each(function() {
    2401                                 var container = $( this ),
    2402                                         checkbox = container.find( 'input[type=checkbox]' ),
    2403                                         element,
    2404                                         updateSelectedMenuLabel,
    2405                                         navMenuLocationSetting = api( 'nav_menu_locations[' + checkbox.data( 'location-id' ) + ']' );
    2406 
    2407                                 updateSelectedMenuLabel = function( selectedMenuId ) {
    2408                                         var menuSetting = api( 'nav_menu[' + String( selectedMenuId ) + ']' );
    2409                                         if ( ! selectedMenuId || ! menuSetting || ! menuSetting() ) {
    2410                                                 container.find( '.theme-location-set' ).hide();
    2411                                         } else {
    2412                                                 container.find( '.theme-location-set' ).show().find( 'span' ).text( displayNavMenuName( menuSetting().name ) );
    2413                                         }
    2414                                 };
    2415 
    2416                                 element = new api.Element( checkbox );
    2417                                 element.set( navMenuLocationSetting.get() === control.params.menu_id );
    2418 
    2419                                 checkbox.on( 'change', function() {
    2420                                         // Note: We can't use element.bind( function( checked ){ ... } ) here because it will trigger a change as well.
    2421                                         navMenuLocationSetting.set( this.checked ? control.params.menu_id : 0 );
    2422                                 } );
    2423 
    2424                                 navMenuLocationSetting.bind(function( selectedMenuId ) {
    2425                                         element.set( selectedMenuId === control.params.menu_id );
    2426                                         updateSelectedMenuLabel( selectedMenuId );
    2427                                 });
    2428                                 updateSelectedMenuLabel( navMenuLocationSetting.get() );
    2429 
    2430                         });
    24312610                },
    24322611
    … …  
    26082787                        } );
    26092788
     2789                        menuControl.updateInvitationVisibility( menuItemControls );
    26102790                        menuControl.container.find( '.reorder-toggle' ).toggle( menuItemControls.length > 1 );
    26112791                },
    … …  
    26822862
    26832863                        return menuItemControl;
     2864                },
     2865
     2866                /**
     2867                 * Show an invitation to add new menu items when there are no menu items.
     2868                 *
     2869                 * @since 4.9.0
     2870                 *
     2871                 * @param {wp.customize.controlConstructor.nav_menu_item[]} optionalMenuItemControls
     2872                 */
     2873                updateInvitationVisibility: function ( optionalMenuItemControls ) {
     2874                        var menuItemControls = optionalMenuItemControls || this.getMenuItemControls();
     2875
     2876                        this.container.find( '.new-menu-item-invitation' ).toggle( menuItemControls.length === 0 );
    26842877                }
    26852878        } );
    2686 
    2687         /**
    2688          * wp.customize.Menus.NewMenuControl
    2689          *
    2690          * Customizer control for creating new menus and handling deletion of existing menus.
    2691          * Note that 'new_menu' must match the WP_Customize_New_Menu_Control::$type.
    2692          *
    2693          * @constructor
    2694          * @augments wp.customize.Control
    2695          */
    2696         api.Menus.NewMenuControl = api.Control.extend({
    2697                 /**
    2698                  * Set up the control.
    2699                  */
    2700                 ready: function() {
    2701                         this._bindHandlers();
    2702                 },
    2703 
    2704                 _bindHandlers: function() {
    2705                         var self = this,
    2706                                 name = $( '#customize-control-new_menu_name input' ),
    2707                                 submit = $( '#create-new-menu-submit' );
    2708                         name.on( 'keydown', function( event ) {
    2709                                 if ( 13 === event.which ) { // Enter.
    2710                                         self.submit();
    2711                                 }
    2712                         } );
    2713                         submit.on( 'click', function( event ) {
    2714                                 self.submit();
    2715                                 event.stopPropagation();
    2716                                 event.preventDefault();
    2717                         } );
    2718                 },
    2719 
    2720                 /**
    2721                  * Create the new menu with the name supplied.
    2722                  */
    2723                 submit: function() {
    2724 
    2725                         var control = this,
    2726                                 container = control.container.closest( '.accordion-section-new-menu' ),
    2727                                 nameInput = container.find( '.menu-name-field' ).first(),
    2728                                 name = nameInput.val(),
    2729                                 menuSection,
    2730                                 customizeId,
    2731                                 placeholderId = api.Menus.generatePlaceholderAutoIncrementId();
    2732 
    2733                         if ( ! name ) {
    2734                                 nameInput.addClass( 'invalid' );
    2735                                 nameInput.focus();
    2736                                 return;
    2737                         }
    2738 
    2739                         customizeId = 'nav_menu[' + String( placeholderId ) + ']';
    2740 
    2741                         // Register the menu control setting.
    2742                         api.create( customizeId, customizeId, {}, {
    2743                                 type: 'nav_menu',
    2744                                 transport: api.Menus.data.settingTransport,
    2745                                 previewer: api.previewer
    2746                         } );
    2747                         api( customizeId ).set( $.extend(
    2748                                 {},
    2749                                 api.Menus.data.defaultSettingValues.nav_menu,
    2750                                 {
    2751                                         name: name
    2752                                 }
    2753                         ) );
    2754 
    2755                         /*
    2756                          * Add the menu section (and its controls).
    2757                          * Note that this will automatically create the required controls
    2758                          * inside via the Section's ready method.
    2759                          */
    2760                         menuSection = new api.Menus.MenuSection( customizeId, {
    2761                                 panel: 'nav_menus',
    2762                                 title: displayNavMenuName( name ),
    2763                                 customizeAction: api.Menus.data.l10n.customizingMenus,
    2764                                 type: 'nav_menu',
    2765                                 priority: 10,
    2766                                 menu_id: placeholderId
    2767                         } );
    2768                         api.section.add( menuSection );
    2769 
    2770                         // Clear name field.
    2771                         nameInput.val( '' );
    2772                         nameInput.removeClass( 'invalid' );
    2773 
    2774                         wp.a11y.speak( api.Menus.data.l10n.menuAdded );
    2775 
    2776                         // Focus on the new menu section.
    2777                         api.section( customizeId ).focus(); // @todo should we focus on the new menu's control and open the add-items panel? Thinking user flow...
    2778                 }
    2779         });
    27802879
    27812880        /**
    … …  
    27882887                nav_menu: api.Menus.MenuControl,
    27892888                nav_menu_name: api.Menus.MenuNameControl,
    2790                 nav_menu_auto_add: api.Menus.MenuAutoAddControl,
    2791                 new_menu: api.Menus.NewMenuControl
     2889                nav_menu_locations: api.Menus.MenuLocationsControl,
     2890                nav_menu_auto_add: api.Menus.MenuAutoAddControl
    27922891        });
    27932892
  • trunk/src/wp-includes/class-wp-customize-control.php

    r41750 r41768  
    771771
    772772/**
     773 * WP_Customize_Nav_Menu_Locations_Control class.
     774 */
     775require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-locations-control.php' );
     776
     777/**
    773778 * WP_Customize_Nav_Menu_Auto_Add_Control class.
    774779 */
    … …  
    776781
    777782/**
    778  * WP_Customize_New_Menu_Control class.
    779  */
    780 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-control.php' );
    781 
    782 /**
    783783 * WP_Customize_Date_Time_Control class.
    784784 */
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r41750 r41768  
    316316                require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-location-control.php' );
    317317                require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-name-control.php' );
     318                require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-locations-control.php' );
    318319                require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-auto-add-control.php' );
    319                 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-control.php' );
    320320
    321321                require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menus-panel.php' );
    … …  
    325325                require_once( ABSPATH . WPINC . '/customize/class-wp-customize-sidebar-section.php' );
    326326                require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-section.php' );
    327                 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-section.php' );
    328327
    329328                require_once( ABSPATH . WPINC . '/customize/class-wp-customize-custom-css-setting.php' );
  • trunk/src/wp-includes/class-wp-customize-nav-menus.php

    r41670 r41768  
    396396                $temp_nav_menu_item_setting = new WP_Customize_Nav_Menu_Item_Setting( $this->manager, 'nav_menu_item[-1]' );
    397397
     398                $num_locations = count( get_registered_nav_menus() );
     399                if ( 1 === $num_locations ) {
     400                        $locations_description = __( 'Your theme can display menus in one location.' );
     401                } else {
     402                        /* translators: %s: number of menu locations */
     403                        $locations_description = sprintf( _n( 'Your theme can display menus in %s location.', 'Your theme can display menus in %s locations.', $num_locations ), number_format_i18n( $num_locations ) );
     404                }
     405
    398406                // Pass data to JS.
    399407                $settings = array(
    … …  
    401409                        'itemTypes'            => $this->available_item_types(),
    402410                        'l10n'                 => array(
    403                                 'untitled'          => _x( '(no label)', 'missing menu item navigation label' ),
    404                                 'unnamed'           => _x( '(unnamed)', 'Missing menu name.' ),
    405                                 'custom_label'      => __( 'Custom Link' ),
    406                                 'page_label'        => get_post_type_object( 'page' )->labels->singular_name,
    407                                 /* translators: %s: menu location */
    408                                 'menuLocation'      => _x( '(Currently set to: %s)', 'menu' ),
    409                                 'menuNameLabel'     => __( 'Menu Name' ),
    410                                 'itemAdded'         => __( 'Menu item added' ),
    411                                 'itemDeleted'       => __( 'Menu item deleted' ),
    412                                 'menuAdded'         => __( 'Menu created' ),
    413                                 'menuDeleted'       => __( 'Menu deleted' ),
    414                                 'movedUp'           => __( 'Menu item moved up' ),
    415                                 'movedDown'         => __( 'Menu item moved down' ),
    416                                 'movedLeft'         => __( 'Menu item moved out of submenu' ),
    417                                 'movedRight'        => __( 'Menu item is now a sub-item' ),
     411                                'untitled'               => _x( '(no label)', 'missing menu item navigation label' ),
     412                                'unnamed'                => _x( '(unnamed)', 'Missing menu name.' ),
     413                                'custom_label'           => __( 'Custom Link' ),
     414                                'page_label'             => get_post_type_object( 'page' )->labels->singular_name,
     415                                /* translators: %s:      menu location */
     416                                'menuLocation'           => _x( '(Currently set to: %s)', 'menu' ),
     417                                'locationsDescription'   => $locations_description,
     418                                'menuNameLabel'          => __( 'Menu Name' ),
     419                                'newMenuNameDescription' => __( 'If your theme has multiple menus, giving them clear names will help you manage them.' ),
     420                                'itemAdded'              => __( 'Menu item added' ),
     421                                'itemDeleted'            => __( 'Menu item deleted' ),
     422                                'menuAdded'              => __( 'Menu created' ),
     423                                'menuDeleted'            => __( 'Menu deleted' ),
     424                                'movedUp'                => __( 'Menu item moved up' ),
     425                                'movedDown'              => __( 'Menu item moved down' ),
     426                                'movedLeft'              => __( 'Menu item moved out of submenu' ),
     427                                'movedRight'             => __( 'Menu item is now a sub-item' ),
    418428                                /* translators: ▸ is the unicode right-pointing triangle, and %s is the section title in the Customizer */
    419                                 'customizingMenus'  => sprintf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'nav_menus' )->title ) ),
     429                                'customizingMenus'       => sprintf( __( 'Customizing ▸ %s' ), esc_html( $this->manager->get_panel( 'nav_menus' )->title ) ),
    420430                                /* translators: %s: title of menu item which is invalid */
    421                                 'invalidTitleTpl'   => __( '%s (Invalid)' ),
     431                                'invalidTitleTpl'        => __( '%s (Invalid)' ),
    422432                                /* translators: %s: title of menu item in draft status */
    423                                 'pendingTitleTpl'   => __( '%s (Pending)' ),
    424                                 'itemsFound'        => __( 'Number of items found: %d' ),
    425                                 'itemsFoundMore'    => __( 'Additional items found: %d' ),
    426                                 'itemsLoadingMore'  => __( 'Loading more results... please wait.' ),
    427                                 'reorderModeOn'     => __( 'Reorder mode enabled' ),
    428                                 'reorderModeOff'    => __( 'Reorder mode closed' ),
    429                                 'reorderLabelOn'    => esc_attr__( 'Reorder menu items' ),
    430                                 'reorderLabelOff'   => esc_attr__( 'Close reorder mode' ),
     433                                'pendingTitleTpl'        => __( '%s (Pending)' ),
     434                                'itemsFound'             => __( 'Number of items found: %d' ),
     435                                'itemsFoundMore'         => __( 'Additional items found: %d' ),
     436                                'itemsLoadingMore'       => __( 'Loading more results... please wait.' ),
     437                                'reorderModeOn'          => __( 'Reorder mode enabled' ),
     438                                'reorderModeOff'         => __( 'Reorder mode closed' ),
     439                                'reorderLabelOn'         => esc_attr__( 'Reorder menu items' ),
     440                                'reorderLabelOff'        => esc_attr__( 'Close reorder mode' ),
    431441                        ),
    432442                        'settingTransport'     => 'postMessage',
    … …  
    538548                $this->manager->register_control_type( 'WP_Customize_Nav_Menu_Control' );
    539549                $this->manager->register_control_type( 'WP_Customize_Nav_Menu_Name_Control' );
     550                $this->manager->register_control_type( 'WP_Customize_Nav_Menu_Locations_Control' );
    540551                $this->manager->register_control_type( 'WP_Customize_Nav_Menu_Auto_Add_Control' );
    541552                $this->manager->register_control_type( 'WP_Customize_Nav_Menu_Item_Control' );
    … …  
    559570                // Menu locations.
    560571                $locations     = get_registered_nav_menus();
    561                 $num_locations = count( array_keys( $locations ) );
     572                $num_locations = count( $locations );
    562573                if ( 1 == $num_locations ) {
    563                         $description = '<p>' . __( 'Your theme supports one menu. Select which menu you would like to use.' ) . '</p>';
     574                        $description = '<p>' . __( 'Your theme can display menus in one location. Select which menu you would like to use.' ) . '</p>';
    564575                } else {
    565576                        /* translators: %s: number of menu locations */
    566                         $description = '<p>' . sprintf( _n( 'Your theme supports %s menu. Select which menu appears in each location.', 'Your theme supports %s menus. Select which menu appears in each location.', $num_locations ), number_format_i18n( $num_locations ) ) . '</p>';
    567                 }
     577                        $description = '<p>' . sprintf( _n( 'Your theme can display menus in %s location. Select which menu you would like to use.', 'Your theme can display menus in %s locations. Select which menu appears in each location.', $num_locations ), number_format_i18n( $num_locations ) ) . '</p>';
     578                }
     579
    568580                if ( current_theme_supports( 'widgets' ) ) {
    569581                        /* translators: URL to the widgets panel of the customizer */
    570                         $description .= '<p>' . sprintf( __( 'You can also place menus in <a href="%s">widget areas</a> with the &#8220;Custom Menu&#8221; widget.' ), "javascript:wp.customize.panel( 'widgets' ).focus();" ) . '</p>';
     582                        $description .= '<p>' . sprintf( __( 'If your theme has widget areas, you can also add menus there. Visit the <a href="%s">Widgets panel</a> and add a &#8220;Custom Menu widget&#8221; to display a menu in a sidebar or footer.' ), "javascript:wp.customize.panel( 'widgets' ).focus();" ) . '</p>';
    571583                }
    572584
    573585                $this->manager->add_section( 'menu_locations', array(
    574                         'title'       => __( 'Menu Locations' ),
    575                         'panel'       => 'nav_menus',
    576                         'priority'    => 5,
    577                         'description' => $description,
     586                        'title'         => __( 'View All Locations' ),
     587                        'panel'         => 'nav_menus',
     588                        'priority'      => 30,
     589                        'description'   => $description
    578590                ) );
    579591
    … …  
    668680
    669681                // Add the add-new-menu section and controls.
    670                 $this->manager->add_section( new WP_Customize_New_Menu_Section( $this->manager, 'add_menu', array(
    671                         'title'    => __( 'Add a Menu' ),
     682                $this->manager->add_section( 'add_menu', array(
     683                        'type'     => 'new_menu',
     684                        'title'    => __( 'New Menu' ),
    672685                        'panel'    => 'nav_menus',
    673                         'priority' => 999,
    674                 ) ) );
    675 
    676                 $this->manager->add_control( 'new_menu_name', array(
    677                         'label'       => __( 'New menu name' ),
    678                         'section'     => 'add_menu',
    679                         'type'        => 'text',
    680                         'settings'    => array(),
    681                         'input_attrs' => array(
    682                                 'class'       => 'menu-name-field',
    683                         ),
     686                        'priority' => 20,
    684687                ) );
    685 
    686                 $this->manager->add_control( new WP_Customize_New_Menu_Control( $this->manager, 'create_new_menu', array(
    687                         'section'  => 'add_menu',
    688                         'settings' => array(),
    689                 ) ) );
    690688
    691689                $this->manager->add_setting( new WP_Customize_Filter_Setting( $this->manager, 'nav_menus_created_posts', array(
    … …  
    925923                                ?>
    926924                        </div>
     925                </script>
     926
     927                <script type="text/html" id="tmpl-nav-menu-delete-button">
     928                        <div class="menu-delete-item">
     929                                <button type="button" class="button-link button-link-delete">
     930                                        <?php _e( 'Delete Menu' ); ?>
     931                                </button>
     932                        </div>
     933                </script>
     934
     935                <script type="text/html" id="tmpl-nav-menu-submit-new-button">
     936                        <p id="customize-new-menu-submit-description"><?php _e( 'Click "next" to start adding links to your new menu.' ); ?></p>
     937                        <button id="customize-new-menu-submit" type="button" class="button" aria-describedby="customize-new-menu-submit-description"><?php _e( 'Next' ); ?></button>
     938                </script>
     939
     940                <script type="text/html" id="tmpl-nav-menu-locations-header">
     941                        <span class="customize-control-title customize-section-title-menu_locations-heading"><?php _e( 'Menu Locations' ); ?></span>
     942                        <p class="customize-control-description customize-section-title-menu_locations-description">{{ data.l10n.locationsDescription }}</p>
     943                </script>
     944
     945                <script type="text/html" id="tmpl-nav-menu-create-menu-section-title">
     946                        <h3>
     947                                <button type="button" class="button customize-add-menu-button">
     948                                        <?php _e( 'Create New Menu' ); ?>
     949                                </button>
     950                        </h3>
    927951                </script>
    928952        <?php
  • trunk/src/wp-includes/class-wp-customize-section.php

    r41390 r41768  
    386386/** WP_Customize_Nav_Menu_Section class */
    387387require_once( ABSPATH . WPINC . '/customize/class-wp-customize-nav-menu-section.php' );
    388 
    389 /** WP_Customize_New_Menu_Section class */
    390 require_once( ABSPATH . WPINC . '/customize/class-wp-customize-new-menu-section.php' );
  • trunk/src/wp-includes/customize/class-wp-customize-nav-menu-auto-add-control.php

    r41162 r41768  
    3939        protected function content_template() {
    4040                ?>
     41                <# var elementId = _.uniqueId( 'customize-nav-menu-auto-add-control-' ); #>
    4142                <span class="customize-control-title"><?php _e( 'Menu Options' ); ?></span>
    42                 <label>
    43                         <input type="checkbox" class="auto_add" />
    44                         <?php _e( 'Automatically add new top-level pages to this menu' ); ?>
    45                 </label>
     43                <span class="customize-inside-control-row">
     44                        <input id="{{ elementId }}" type="checkbox" class="auto_add" />
     45                        <label for="{{ elementId }}">
     46                                <?php _e( 'Automatically add new top-level pages to this menu' ); ?>
     47                        </label>
     48                </span>
    4649                <?php
    4750        }
  • trunk/src/wp-includes/customize/class-wp-customize-nav-menu-control.php

    r41740 r41768  
    2424
    2525        /**
    26          * The nav menu setting.
    27          *
    28          * @since 4.3.0
    29          * @var WP_Customize_Nav_Menu_Setting
    30          */
    31         public $setting;
    32 
    33         /**
    3426         * Don't render the control's content - it uses a JS template instead.
    3527         *
    … …  
    4537        public function content_template() {
    4638                ?>
    47                 <# var elementId; #>
    48                 <button type="button" class="button add-new-menu-item" aria-label="<?php esc_attr_e( 'Add or remove menu items' ); ?>" aria-expanded="false" aria-controls="available-menu-items">
    49                         <?php _e( 'Add Items' ); ?>
    50                 </button>
    51                 <button type="button" class="button-link reorder-toggle" aria-label="<?php esc_attr_e( 'Reorder menu items' ); ?>" aria-describedby="reorder-items-desc-{{ data.menu_id }}">
    52                         <span class="reorder"><?php _e( 'Reorder' ); ?></span>
    53                         <span class="reorder-done"><?php _e( 'Done' ); ?></span>
    54                 </button>
     39                <p class="new-menu-item-invitation"><?php _e( 'Time to add some links! Click "Add menu items" to start putting pages, categories, and custom links in your menu. Add as many things as you\'d like.' ); ?></p>
     40                <div class="customize-control-nav_menu-buttons">
     41                        <button type="button" class="button add-new-menu-item" aria-label="<?php esc_attr_e( 'Add or remove menu items' ); ?>" aria-expanded="false" aria-controls="available-menu-items">
     42                                <?php _e( 'Add Items' ); ?>
     43                        </button>
     44                        <button type="button" class="button-link reorder-toggle" aria-label="<?php esc_attr_e( 'Reorder menu items' ); ?>" aria-describedby="reorder-items-desc-{{ data.menu_id }}">
     45                                <span class="reorder"><?php _e( 'Reorder' ); ?></span>
     46                                <span class="reorder-done"><?php _e( 'Done' ); ?></span>
     47                        </button>
     48                </div>
    5549                <p class="screen-reader-text" id="reorder-items-desc-{{ data.menu_id }}"><?php _e( 'When in reorder mode, additional controls to reorder menu items will be available in the items list above.' ); ?></p>
    56                 <span class="menu-delete-item">
    57                         <button type="button" class="button-link button-link-delete">
    58                                 <?php _e( 'Delete Menu' ); ?>
    59                         </button>
    60                 </span>
    61                 <?php if ( current_theme_supports( 'menus' ) ) : ?>
    62                 <ul class="menu-settings">
    63                         <li class="customize-control">
    64                                 <span class="customize-control-title"><?php _e( 'Display Location' ); ?></span>
    65                         </li>
    66 
    67                         <?php foreach ( get_registered_nav_menus() as $location => $description ) : ?>
    68                                 <# elementId = _.uniqueId( 'customize-nav-menu-control-location-' ); #>
    69                                 <li class="customize-control customize-control-checkbox assigned-menu-location customize-inside-control-row">
    70                                         <input id="{{ elementId }}" type="checkbox" data-menu-id="{{ data.menu_id }}" data-location-id="<?php echo esc_attr( $location ); ?>" class="menu-location" />
    71                                         <label for="{{ elementId }}">
    72                                                 <?php echo $description; ?>
    73                                                 <span class="theme-location-set">
    74                                                         <?php
    75                                                         /* translators: %s: menu name */
    76                                                         printf( _x( '(Current: %s)', 'menu location' ),
    77                                                                 '<span class="current-menu-location-name-' . esc_attr( $location ) . '"></span>'
    78                                                         );
    79                                                         ?>
    80                                                 </span>
    81                                         </label>
    82                                 </li>
    83                         <?php endforeach; ?>
    84                 </ul>
    85                 <?php endif; ?>
    8650                <?php
    8751        }
  • trunk/src/wp-includes/customize/class-wp-customize-nav-menu-name-control.php

    r41162 r41768  
    4141                <label>
    4242                        <# if ( data.label ) { #>
    43                                 <span class="customize-control-title screen-reader-text">{{ data.label }}</span>
     43                                <span class="customize-control-title">{{ data.label }}</span>
    4444                        <# } #>
    45                         <input type="text" class="menu-name-field live-update-section-title" />
     45                        <input type="text" class="menu-name-field live-update-section-title"
     46                                <# if ( data.description ) { #>
     47                                        aria-describedby="{{ data.section }}-description"
     48                                <# } #>
     49                                />
    4650                </label>
     51                <# if ( data.description ) { #>
     52                        <p id="{{ data.section }}-description">{{ data.description }}</p>
     53                <# } #>
    4754                <?php
    4855        }
  • trunk/src/wp-includes/customize/class-wp-customize-nav-menus-panel.php

    r41162 r41768  
    9393                        </div>
    9494                </li>
     95                <?php
     96                // NOTE: The following is a workaround for an inability to treat (and thus label) a list of sections as a whole.
     97                ?>
     98                <li class="customize-control-title customize-section-title-nav_menus-heading"><?php _e( 'Menus' ); ?></li>
    9599        <?php
    96100        }
  • trunk/tests/qunit/wp-admin/js/customize-nav-menus.js

    r38049 r41768  
    6666                ok( controls[0].extended( api.Menus.MenuNameControl ), 'first control in menu section is MenuNameControl' );
    6767                ok( controls[1].extended( api.Menus.MenuItemControl ), 'second control in menu section is MenuItemControl' );
    68                 ok( controls[ controls.length - 1 ].extended( api.Menus.MenuAutoAddControl ), 'last control in menu section is a MenuAutoAddControl' );
     68                ok( controls[ controls.length - 1 ].extended( api.Menus.MenuDeleteControl ), 'last control in menu section is a MenuDeleteControl' );
    6969        } );
    7070        // @todo Add more tests for api.Menus.MenuSection behaviors
Note: See TracChangeset for help on using the changeset viewer.