wp/wp-admin/js/nav-menu.js
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
--- a/wp/wp-admin/js/nav-menu.js	Tue Dec 15 15:52:01 2020 +0100
+++ b/wp/wp-admin/js/nav-menu.js	Wed Sep 21 18:19:35 2022 +0200
@@ -45,6 +45,11 @@
 
 			this.attachMenuEditListeners();
 
+			this.attachBulkSelectButtonListeners();
+			this.attachMenuCheckBoxListeners();
+			this.attachMenuItemDeleteButton();
+			this.attachPendingMenuItemsListForDeletion();
+
 			this.attachQuickSearchListeners();
 			this.attachThemeLocationsListeners();
 			this.attachMenuSaveSubmitListeners();
@@ -390,7 +395,7 @@
 				thisItem.shiftHorizontally( 1 );
 				break;
 			}
-			$this.focus();
+			$this.trigger( 'focus' );
 			api.registerChange();
 			api.refreshKeyboardAccessibility();
 			api.refreshAdvancedAccessibility();
@@ -572,7 +577,7 @@
 						break;
 					}
 					// Put focus back on same menu item.
-					$( '#edit-' + thisItemData['menu-item-db-id'] ).focus();
+					$( '#edit-' + thisItemData['menu-item-db-id'] ).trigger( 'focus' );
 					return false;
 				});
 			});
@@ -608,7 +613,7 @@
 			// Hide fields.
 			api.menuList.hideAdvancedMenuItemFields();
 
-			$('.hide-postbox-tog').click(function () {
+			$('.hide-postbox-tog').on( 'click', function () {
 				var hidden = $( '.accordion-container li.accordion-section' ).filter(':hidden').map(function() { return this.id; }).get().join(',');
 				$.post(ajaxurl, {
 					action: 'closed-postboxes',
@@ -809,7 +814,7 @@
 		},
 
 		initManageLocations : function () {
-			$('#menu-locations-wrap form').submit(function(){
+			$('#menu-locations-wrap form').on( 'submit', function(){
 				window.onbeforeunload = null;
 			});
 			$('.menu-location-menus select').on('change', function () {
@@ -823,7 +828,7 @@
 
 		attachMenuEditListeners : function() {
 			var that = this;
-			$('#update-nav-menu').bind('click', function(e) {
+			$('#update-nav-menu').on('click', function(e) {
 				if ( e.target && e.target.className ) {
 					if ( -1 != e.target.className.indexOf('item-edit') ) {
 						return that.eventOnClickEditLink(e.target);
@@ -852,22 +857,212 @@
 				}
 			}, 500 ) );
 
-			$('#add-custom-links input[type="text"]').keypress(function(e){
+			$('#add-custom-links input[type="text"]').on( 'keypress', function(e){
 				$('#customlinkdiv').removeClass('form-invalid');
 
 				if ( e.keyCode === 13 ) {
 					e.preventDefault();
-					$( '#submit-customlinkdiv' ).click();
+					$( '#submit-customlinkdiv' ).trigger( 'click' );
+				}
+			});
+		},
+
+		/**
+		 * Handle toggling bulk selection checkboxes for menu items.
+		 *
+		 * @since 5.8.0
+		 */ 
+		attachBulkSelectButtonListeners : function() {
+			var that = this;
+
+			$( '.bulk-select-switcher' ).on( 'change', function() {
+				if ( this.checked ) {
+					$( '.bulk-select-switcher' ).prop( 'checked', true );
+					that.enableBulkSelection();
+				} else {
+					$( '.bulk-select-switcher' ).prop( 'checked', false );
+					that.disableBulkSelection();
 				}
 			});
 		},
 
+		/**
+		 * Enable bulk selection checkboxes for menu items.
+		 *
+		 * @since 5.8.0
+		 */ 
+		enableBulkSelection : function() {
+			var checkbox = $( '#menu-to-edit .menu-item-checkbox' );
+
+			$( '#menu-to-edit' ).addClass( 'bulk-selection' );
+			$( '#nav-menu-bulk-actions-top' ).addClass( 'bulk-selection' );
+			$( '#nav-menu-bulk-actions-bottom' ).addClass( 'bulk-selection' );
+
+			$.each( checkbox, function() {
+				$(this).prop( 'disabled', false );
+			});
+		},
+
+		/**
+		 * Disable bulk selection checkboxes for menu items.
+		 *
+		 * @since 5.8.0
+		 */ 
+		disableBulkSelection : function() {
+			var checkbox = $( '#menu-to-edit .menu-item-checkbox' );
+
+			$( '#menu-to-edit' ).removeClass( 'bulk-selection' );
+			$( '#nav-menu-bulk-actions-top' ).removeClass( 'bulk-selection' );
+			$( '#nav-menu-bulk-actions-bottom' ).removeClass( 'bulk-selection' );
+
+			if ( $( '.menu-items-delete' ).is( '[aria-describedby="pending-menu-items-to-delete"]' ) ) {
+				$( '.menu-items-delete' ).removeAttr( 'aria-describedby' );
+			}
+
+			$.each( checkbox, function() {
+				$(this).prop( 'disabled', true ).prop( 'checked', false );
+			});
+
+			$( '.menu-items-delete' ).addClass( 'disabled' );
+			$( '#pending-menu-items-to-delete ul' ).empty();
+		},
+
+		/**
+		 * Listen for state changes on bulk action checkboxes.
+		 *
+		 * @since 5.8.0
+		 */ 
+		attachMenuCheckBoxListeners : function() {
+			var that = this;
+
+			$( '#menu-to-edit' ).on( 'change', '.menu-item-checkbox', function() {
+				that.setRemoveSelectedButtonStatus();
+			});
+		},
+
+		/**
+		 * Create delete button to remove menu items from collection.
+		 *
+		 * @since 5.8.0
+		 */ 
+		attachMenuItemDeleteButton : function() {
+			var that = this;
+
+			$( document ).on( 'click', '.menu-items-delete', function( e ) {
+				var itemsPendingDeletion, itemsPendingDeletionList, deletionSpeech;
+
+				e.preventDefault();
+
+				if ( ! $(this).hasClass( 'disabled' ) ) {
+					$.each( $( '.menu-item-checkbox:checked' ), function( index, element ) {
+						$( element ).parents( 'li' ).find( 'a.item-delete' ).trigger( 'click' );
+					});
+
+					$( '.menu-items-delete' ).addClass( 'disabled' );
+					$( '.bulk-select-switcher' ).prop( 'checked', false );
+
+					itemsPendingDeletion     = '';
+					itemsPendingDeletionList = $( '#pending-menu-items-to-delete ul li' );
+
+					$.each( itemsPendingDeletionList, function( index, element ) {
+						var itemName = $( element ).find( '.pending-menu-item-name' ).text();
+						var itemSpeech = menus.menuItemDeletion.replace( '%s', itemName );
+
+						itemsPendingDeletion += itemSpeech;
+						if ( ( index + 1 ) < itemsPendingDeletionList.length ) {
+							itemsPendingDeletion += ', ';
+						}
+					});
+
+					deletionSpeech = menus.itemsDeleted.replace( '%s', itemsPendingDeletion );
+					wp.a11y.speak( deletionSpeech, 'polite' );
+					that.disableBulkSelection();
+				}
+			});
+		},
+
+		/**
+		 * List menu items awaiting deletion.
+		 *
+		 * @since 5.8.0
+		 */ 
+		attachPendingMenuItemsListForDeletion : function() {
+			$( '#post-body-content' ).on( 'change', '.menu-item-checkbox', function() {
+				var menuItemName, menuItemType, menuItemID, listedMenuItem;
+
+				if ( ! $( '.menu-items-delete' ).is( '[aria-describedby="pending-menu-items-to-delete"]' ) ) {
+					$( '.menu-items-delete' ).attr( 'aria-describedby', 'pending-menu-items-to-delete' );
+				}
+
+				menuItemName = $(this).next().text();
+				menuItemType = $(this).parent().next( '.item-controls' ).find( '.item-type' ).text();
+				menuItemID   = $(this).attr( 'data-menu-item-id' );
+
+				listedMenuItem = $( '#pending-menu-items-to-delete ul' ).find( '[data-menu-item-id=' + menuItemID + ']' );
+				if ( listedMenuItem.length > 0 ) {
+					listedMenuItem.remove();
+				}
+
+				if ( this.checked === true ) {
+					$( '#pending-menu-items-to-delete ul' ).append(
+						'<li data-menu-item-id="' + menuItemID + '">' +
+							'<span class="pending-menu-item-name">' + menuItemName + '</span> ' +
+							'<span class="pending-menu-item-type">(' + menuItemType + ')</span>' +
+							'<span class="separator"></span>' +
+						'</li>'
+					);
+				}
+
+				$( '#pending-menu-items-to-delete li .separator' ).html( ', ' );
+				$( '#pending-menu-items-to-delete li .separator' ).last().html( '.' );
+			});
+		},
+
+		/**
+		 * Set status of bulk delete checkbox.
+		 *
+		 * @since 5.8.0
+		 */ 
+		setBulkDeleteCheckboxStatus : function() {
+			var that = this;
+			var checkbox = $( '#menu-to-edit .menu-item-checkbox' );
+
+			$.each( checkbox, function() {
+				if ( $(this).prop( 'disabled' ) ) {
+					$(this).prop( 'disabled', false );
+				} else {
+					$(this).prop( 'disabled', true );
+				}
+
+				if ( $(this).is( ':checked' ) ) {
+					$(this).prop( 'checked', false );
+				}
+			});
+
+			that.setRemoveSelectedButtonStatus();
+		},
+
+		/**
+		 * Set status of menu items removal button.
+		 *
+		 * @since 5.8.0
+		 */ 
+		setRemoveSelectedButtonStatus : function() {
+			var button = $( '.menu-items-delete' );
+
+			if ( $( '.menu-item-checkbox:checked' ).length > 0 ) {
+				button.removeClass( 'disabled' );
+			} else {
+				button.addClass( 'disabled' );
+			}
+		},
+
 		attachMenuSaveSubmitListeners : function() {
 			/*
 			 * When a navigation menu is saved, store a JSON representation of all form data
 			 * in a single input to avoid PHP `max_input_vars` limitations. See #14134.
 			 */
-			$( '#update-nav-menu' ).submit( function() {
+			$( '#update-nav-menu' ).on( 'submit', function() {
 				var navMenuData = $( '#update-nav-menu' ).serializeArray();
 				$( '[name="nav-menu-data"]' ).val( JSON.stringify( navMenuData ) );
 			});
@@ -877,7 +1072,7 @@
 			var loc = $('#nav-menu-theme-locations'), params = {};
 			params.action = 'menu-locations-save';
 			params['menu-settings-column-nonce'] = $('#menu-settings-column-nonce').val();
-			loc.find('input[type="submit"]').click(function() {
+			loc.find('input[type="submit"]').on( 'click', function() {
 				loc.find('select').each(function() {
 					params[this.name] = $(this).val();
 				});
@@ -908,7 +1103,7 @@
 
 				searchTimer = setTimeout( function() {
 					api.updateQuickSearchResults( $this );
- 				}, 500 );
+				}, 500 );
 			}).on( 'blur', '.quick-search', function() {
 				api.lastSearch = '';
 			});
@@ -947,9 +1142,13 @@
 		},
 
 		addCustomLink : function( processMethod ) {
-			var url = $('#custom-menu-item-url').val().trim(),
+			var url = $('#custom-menu-item-url').val().toString(),
 				label = $('#custom-menu-item-name').val();
 
+			if ( '' !== url ) {
+				url = url.trim();
+			}
+
 			processMethod = processMethod || api.addMenuItemToBottom;
 
 			if ( '' === url || 'https://' == url || 'http://' == url ) {
@@ -963,7 +1162,7 @@
 				// Remove the Ajax spinner.
 				$( '.customlinkdiv .spinner' ).removeClass( 'is-active' );
 				// Set custom link form back to defaults.
-				$('#custom-menu-item-name').val('').blur();
+				$('#custom-menu-item-name').val('').trigger( 'blur' );
 				$( '#custom-menu-item-url' ).val( '' ).attr( 'placeholder', 'https://' );
 			});
 		},
@@ -999,7 +1198,8 @@
 			$.post( ajaxurl, params, function(menuMarkup) {
 				var ins = $('#menu-instructions');
 
-				menuMarkup = $.trim( menuMarkup ); // Trim leading whitespaces.
+				menuMarkup = menuMarkup || '';
+				menuMarkup = menuMarkup.toString().trim(); // Trim leading whitespaces.
 				processMethod(menuMarkup, params);
 
 				// Make it stand out a bit more visually, by adding a fadeIn.
@@ -1043,7 +1243,7 @@
 		},
 
 		attachUnsavedChangesListener : function() {
-			$('#menu-management input, #menu-management select, #menu-management, #menu-management textarea, .menu-location-menus select').change(function(){
+			$('#menu-management input, #menu-management select, #menu-management, #menu-management textarea, .menu-location-menus select').on( 'change', function(){
 				api.registerChange();
 			});
 
@@ -1054,7 +1254,7 @@
 				};
 			} else {
 				// Make the post boxes read-only, as they can't be used yet.
-				$( '#menu-settings-column' ).find( 'input,select' ).end().find( 'a' ).attr( 'href', '#' ).unbind( 'click' );
+				$( '#menu-settings-column' ).find( 'input,select' ).end().find( 'a' ).attr( 'href', '#' ).off( 'click' );
 			}
 		},
 
@@ -1063,7 +1263,7 @@
 		},
 
 		attachTabsPanelListeners : function() {
-			$('#menu-settings-column').bind('click', function(e) {
+			$('#menu-settings-column').on('click', function(e) {
 				var selectAreaMatch, selectAll, panelId, wrapper, items,
 					target = $(e.target);
 
@@ -1083,7 +1283,7 @@
 					target.parent().addClass('tabs');
 
 					// Select the search bar.
-					$('.quick-search', wrapper).focus();
+					$('.quick-search', wrapper).trigger( 'focus' );
 
 					// Hide controls in the search tab if no items found.
 					if ( ! wrapper.find( '.tabs-panel-active .menu-item-title' ).length ) {
@@ -1136,7 +1336,7 @@
 
 				$.post( ajaxurl, this.href.replace( /.*\?/, '' ).replace( /action=([^&]*)/, '' ) + '&action=menu-get-metabox',
 					function( resp ) {
-						var metaBoxData = $.parseJSON( resp ),
+						var metaBoxData = JSON.parse( resp ),
 							toReplace;
 
 						if ( -1 === resp.indexOf( 'replace-id' ) ) {
@@ -1326,6 +1526,27 @@
 
 	};
 
-	$(document).ready(function(){ wpNavMenu.init(); });
+	$( function() {
+
+		wpNavMenu.init();
+
+		// Prevent focused element from being hidden by the sticky footer.
+		$( '.menu-edit a, .menu-edit button, .menu-edit input, .menu-edit textarea, .menu-edit select' ).on('focus', function() {
+			if ( window.innerWidth >= 783 ) {
+				var navMenuHeight = $( '#nav-menu-footer' ).height() + 20;
+				var bottomOffset = $(this).offset().top - ( $(window).scrollTop() + $(window).height() - $(this).height() );
+
+				if ( bottomOffset > 0 ) {
+					bottomOffset = 0;
+				}
+				bottomOffset = bottomOffset * -1;
+
+				if( bottomOffset < navMenuHeight ) {
+					var scrollTop = $(document).scrollTop();
+					$(document).scrollTop( scrollTop + ( navMenuHeight - bottomOffset ) );
+				}
+			}
+		});
+	});
 
 })(jQuery);