From b6a549671c9bd95080151a94147ed22cce6efe42 Mon Sep 17 00:00:00 2001 From: AKSHAT2802 Date: Mon, 21 Jul 2025 16:35:48 +0530 Subject: [PATCH 1/5] Enhance Nav Menu functionality: Add check for already added menu items and update UI accordingly --- src/js/_enqueues/wp/customize/nav-menus.js | 52 +++++++++++++++++++--- src/wp-admin/css/nav-menus.css | 4 ++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/js/_enqueues/wp/customize/nav-menus.js b/src/js/_enqueues/wp/customize/nav-menus.js index f193d5463bfe4..0b0b6b8a20c5d 100644 --- a/src/js/_enqueues/wp/customize/nav-menus.js +++ b/src/js/_enqueues/wp/customize/nav-menus.js @@ -292,6 +292,20 @@ this.doSearch( 1 ); }, + isMenuItemAlreadyAdded: function(menuItem) { + if ( ! this.currentMenuControl ) return false; + var objectId = parseInt(menuItem.get('object_id'), 10); + var object = menuItem.get('object'); + var type = menuItem.get('type'); + + return this.currentMenuControl.getMenuItemControls().some(function(control) { + var setting = control.setting(); + return parseInt(setting.object_id, 10) === objectId && + setting.object === object && + setting.type === type; + }); + }, + // Get search results. doSearch: function( page ) { var self = this, params, @@ -341,8 +355,21 @@ items = new api.Menus.AvailableItemCollection( data.items ); self.collection.add( items.models ); items.each( function( menuItem ) { - $content.append( itemTemplate( menuItem.attributes ) ); - } ); + var $item = $( itemTemplate( menuItem.attributes ) ); + var inUse = this.currentMenuControl.getMenuItemControls().some( function( control ) { + var setting = control.setting(); + return setting.object_id == menuItem.get( 'object_id' ) && + setting.type === menuItem.get( 'type' ) && + setting.object === menuItem.get( 'object' ); + }); + + if ( inUse ) { + $item.find( '.menu-item-title' ).addClass( 'in-use' ); + } + + $content.append( $item ); + }); + if ( 20 > items.length ) { self.pages.search = -1; // Up to 20 posts and 20 terms in results, if <20, no more results for either. } else { @@ -451,11 +478,20 @@ } else if ( ( 'post_type:page' === name ) && ( ! availableMenuItemContainers[ name ].hasClass( 'open' ) ) ) { availableMenuItemContainers[ name ].find( '.accordion-section-title > button' ).trigger( 'click' ); } - typeItems = new api.Menus.AvailableItemCollection( typeItems ); // @todo Why is this collection created and then thrown away? + typeItems = new api.Menus.AvailableItemCollection( typeItems ); self.collection.add( typeItems.models ); typeInner = availableMenuItemContainers[ name ].find( '.available-menu-items-list' ); - typeItems.each( function( menuItem ) { - typeInner.append( itemTemplate( menuItem.attributes ) ); + typeInner.empty(); + typeItems.each(function(menuItem) { + var $item = $(itemTemplate(menuItem.attributes)); + + if (self.isMenuItemAlreadyAdded(menuItem)) { + $item.find('.menu-item-title').addClass('in-use'); + } else { + $item.find('.menu-item-title').removeClass('in-use'); + } + + typeInner.append($item); } ); self.pages[ name ] += 1; }); @@ -723,6 +759,11 @@ this.currentMenuControl = menuControl; + // Reset pagination tracking + _.each( api.Menus.data.itemTypes, function( itemType ) { + panel.pages[ itemType.type + ':' + itemType.object ] = 0; + }); + this.itemSectionHeight(); if ( api.section.has( 'publish_settings' ) ) { @@ -745,6 +786,7 @@ this.$el.find( '.selected' ).removeClass( 'selected' ); this.$search.trigger( 'focus' ); + this.loadItems( api.Menus.data.itemTypes ); }, // Closes the panel. diff --git a/src/wp-admin/css/nav-menus.css b/src/wp-admin/css/nav-menus.css index 0c02cde9a4997..3441ae976cb99 100644 --- a/src/wp-admin/css/nav-menus.css +++ b/src/wp-admin/css/nav-menus.css @@ -530,6 +530,10 @@ input.bulk-select-switcher:focus + .bulk-select-button-label { font-weight: 600; } +.menu-item-title.in-use { + font-weight: normal; +} + /* Nav Menu */ #menu-container .inside { padding-bottom: 10px; From 25923f0875d10fe8a3173e2411f8a0dc1cb0255f Mon Sep 17 00:00:00 2001 From: AKSHAT2802 Date: Mon, 21 Jul 2025 17:07:48 +0530 Subject: [PATCH 2/5] Enhance Nav Menu functionality: Refactor menu item rendering and improve in-use state handling --- src/js/_enqueues/wp/customize/nav-menus.js | 48 +++++++++------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/js/_enqueues/wp/customize/nav-menus.js b/src/js/_enqueues/wp/customize/nav-menus.js index 0b0b6b8a20c5d..083b4ff360f20 100644 --- a/src/js/_enqueues/wp/customize/nav-menus.js +++ b/src/js/_enqueues/wp/customize/nav-menus.js @@ -306,12 +306,22 @@ }); }, + renderMenuItem: function(menuItem) { + var $item = $(wp.template('available-menu-item')(menuItem.attributes)); + + $item.find('.menu-item-title').toggleClass( + 'in-use', + this.isMenuItemAlreadyAdded(menuItem) + ); + + return $item; + }, + // Get search results. doSearch: function( page ) { var self = this, params, $section = $( '#available-menu-items-search' ), - $content = $section.find( '.accordion-section-content' ), - itemTemplate = wp.template( 'available-menu-item' ); + $content = $section.find( '.accordion-section-content' ) if ( self.currentRequest ) { self.currentRequest.abort(); @@ -354,20 +364,9 @@ self.loading = false; items = new api.Menus.AvailableItemCollection( data.items ); self.collection.add( items.models ); - items.each( function( menuItem ) { - var $item = $( itemTemplate( menuItem.attributes ) ); - var inUse = this.currentMenuControl.getMenuItemControls().some( function( control ) { - var setting = control.setting(); - return setting.object_id == menuItem.get( 'object_id' ) && - setting.type === menuItem.get( 'type' ) && - setting.object === menuItem.get( 'object' ); - }); - - if ( inUse ) { - $item.find( '.menu-item-title' ).addClass( 'in-use' ); - } - - $content.append( $item ); + items.each(function(menuItem) { + var $item = self.renderMenuItem(menuItem); + $content.append($item); }); if ( 20 > items.length ) { @@ -422,8 +421,7 @@ * @return {void} */ loadItems: function( itemTypes, deprecated ) { - var self = this, _itemTypes, requestItemTypes = [], params, request, itemTemplate, availableMenuItemContainers = {}; - itemTemplate = wp.template( 'available-menu-item' ); + var self = this, _itemTypes, requestItemTypes = [], params, request, availableMenuItemContainers = {}; if ( _.isString( itemTypes ) && _.isString( deprecated ) ) { _itemTypes = [ { type: itemTypes, object: deprecated } ]; @@ -480,19 +478,11 @@ } typeItems = new api.Menus.AvailableItemCollection( typeItems ); self.collection.add( typeItems.models ); - typeInner = availableMenuItemContainers[ name ].find( '.available-menu-items-list' ); - typeInner.empty(); + typeInner = availableMenuItemContainers[name].find('.available-menu-items-list').empty(); typeItems.each(function(menuItem) { - var $item = $(itemTemplate(menuItem.attributes)); - - if (self.isMenuItemAlreadyAdded(menuItem)) { - $item.find('.menu-item-title').addClass('in-use'); - } else { - $item.find('.menu-item-title').removeClass('in-use'); - } - + var $item = self.renderMenuItem(menuItem); typeInner.append($item); - } ); + }); self.pages[ name ] += 1; }); }); From 4c0e6c06a2c0c093c4de57412f63b53f23882a94 Mon Sep 17 00:00:00 2001 From: AKSHAT2802 Date: Mon, 21 Jul 2025 17:20:54 +0530 Subject: [PATCH 3/5] Fix syntax error in nav-menus.js: Add missing semicolon in doSearch function --- src/js/_enqueues/wp/customize/nav-menus.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/_enqueues/wp/customize/nav-menus.js b/src/js/_enqueues/wp/customize/nav-menus.js index 083b4ff360f20..edb4b545cb622 100644 --- a/src/js/_enqueues/wp/customize/nav-menus.js +++ b/src/js/_enqueues/wp/customize/nav-menus.js @@ -321,7 +321,7 @@ doSearch: function( page ) { var self = this, params, $section = $( '#available-menu-items-search' ), - $content = $section.find( '.accordion-section-content' ) + $content = $section.find( '.accordion-section-content' ); if ( self.currentRequest ) { self.currentRequest.abort(); From ebe219ea778013dfa8b6146911ab62a924652205 Mon Sep 17 00:00:00 2001 From: AKSHAT2802 Date: Tue, 22 Jul 2025 13:16:00 +0530 Subject: [PATCH 4/5] Enhance Menu Item Rendering: Add in-use state indication and screen reader text for already added items --- src/js/_enqueues/wp/customize/nav-menus.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/js/_enqueues/wp/customize/nav-menus.js b/src/js/_enqueues/wp/customize/nav-menus.js index edb4b545cb622..37081e0febe29 100644 --- a/src/js/_enqueues/wp/customize/nav-menus.js +++ b/src/js/_enqueues/wp/customize/nav-menus.js @@ -308,11 +308,20 @@ renderMenuItem: function(menuItem) { var $item = $(wp.template('available-menu-item')(menuItem.attributes)); + var $title = $item.find('.menu-item-title'); + var $button = $item.find('.item-add'); + var $srtext = $button.find('.screen-reader-text'); + var isInUse = this.isMenuItemAlreadyAdded(menuItem); - $item.find('.menu-item-title').toggleClass( - 'in-use', - this.isMenuItemAlreadyAdded(menuItem) - ); + $title.toggleClass('in-use', isInUse); + + // Append screen reader text if already in menu + if (isInUse) { + var markerText = wp.i18n.__('(in current menu)'); + if (!$srtext.text().includes(markerText)) { + $srtext.append(' ' + markerText); + } + } return $item; }, From b72e41e5210a69eb2c455d8e39f96cd9e4f64c04 Mon Sep 17 00:00:00 2001 From: AKSHAT2802 Date: Tue, 22 Jul 2025 15:16:49 +0530 Subject: [PATCH 5/5] Refactor: re-add deleted comment --- src/js/_enqueues/wp/customize/nav-menus.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/_enqueues/wp/customize/nav-menus.js b/src/js/_enqueues/wp/customize/nav-menus.js index 37081e0febe29..9e7205ad023a4 100644 --- a/src/js/_enqueues/wp/customize/nav-menus.js +++ b/src/js/_enqueues/wp/customize/nav-menus.js @@ -485,7 +485,7 @@ } else if ( ( 'post_type:page' === name ) && ( ! availableMenuItemContainers[ name ].hasClass( 'open' ) ) ) { availableMenuItemContainers[ name ].find( '.accordion-section-title > button' ).trigger( 'click' ); } - typeItems = new api.Menus.AvailableItemCollection( typeItems ); + typeItems = new api.Menus.AvailableItemCollection( typeItems ); // @todo Why is this collection created and then thrown away? self.collection.add( typeItems.models ); typeInner = availableMenuItemContainers[name].find('.available-menu-items-list').empty(); typeItems.each(function(menuItem) {