--- a/wp/wp-admin/js/customize-nav-menus.js Fri Sep 05 18:40:08 2025 +0200
+++ b/wp/wp-admin/js/customize-nav-menus.js Fri Sep 05 18:52:52 2025 +0200
@@ -223,6 +223,9 @@
this.$el.on( 'input', '#custom-menu-item-name.invalid, #custom-menu-item-url.invalid', function() {
$( this ).removeClass( 'invalid' );
+ var errorMessageId = $( this ).attr( 'aria-describedby' );
+ $( '#' + errorMessageId ).hide();
+ $( this ).removeAttr( 'aria-invalid' ).removeAttr( 'aria-describedby' );
});
// Load available items if it looks like we'll need them.
@@ -546,8 +549,11 @@
var menuItem,
itemName = $( '#custom-menu-item-name' ),
itemUrl = $( '#custom-menu-item-url' ),
+ urlErrorMessage = $( '#custom-url-error' ),
+ nameErrorMessage = $( '#custom-name-error' ),
url = itemUrl.val().trim(),
- urlRegex;
+ urlRegex,
+ errorText;
if ( ! this.currentMenuControl ) {
return;
@@ -566,15 +572,37 @@
* so this pattern does not need to be complete.
*/
urlRegex = /^((\w+:)?\/\/\w.*|\w+:(?!\/\/$)|\/|\?|#)/;
-
- if ( '' === itemName.val() ) {
- itemName.addClass( 'invalid' );
- return;
- } else if ( ! urlRegex.test( url ) ) {
- itemUrl.addClass( 'invalid' );
+ if ( ! urlRegex.test( url ) || '' === itemName.val() ) {
+ if ( ! urlRegex.test( url ) ) {
+ itemUrl.addClass( 'invalid' )
+ .attr( 'aria-invalid', 'true' )
+ .attr( 'aria-describedby', 'custom-url-error' );
+ urlErrorMessage.show();
+ errorText = urlErrorMessage.text();
+ // Announce error message via screen reader
+ wp.a11y.speak( errorText, 'assertive' );
+ }
+ if ( '' === itemName.val() ) {
+ itemName.addClass( 'invalid' )
+ .attr( 'aria-invalid', 'true' )
+ .attr( 'aria-describedby', 'custom-name-error' );
+ nameErrorMessage.show();
+ errorText = ( '' === errorText ) ? nameErrorMessage.text() : errorText + nameErrorMessage.text();
+ // Announce error message via screen reader
+ wp.a11y.speak( errorText, 'assertive' );
+ }
return;
}
+ urlErrorMessage.hide();
+ nameErrorMessage.hide();
+ itemName.removeClass( 'invalid' )
+ .removeAttr( 'aria-invalid', 'true' )
+ .removeAttr( 'aria-describedby', 'custom-name-error' );
+ itemUrl.removeClass( 'invalid' )
+ .removeAttr( 'aria-invalid', 'true' )
+ .removeAttr( 'aria-describedby', 'custom-name-error' );
+
menuItem = {
'title': itemName.val(),
'url': url,
@@ -1107,7 +1135,7 @@
var section = this,
$title;
- $title = section.container.find( '.accordion-section-title:first' );
+ $title = section.container.find( '.accordion-section-title button:first' );
$title.find( '.menu-in-location' ).remove();
_.each( themeLocationSlugs, function( themeLocationSlug ) {
var $label, locationName;