: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
.removeAttr( "aria-hidden" )
.attr( "aria-expanded", "true" )
collapseAll: function( event, all ) {
clearTimeout( this.timer );
this.timer = this._delay( function() {
// If we were passed an event, look for the submenu that contains the event
var currentMenu = all ? this.element :
$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
// If we found no valid submenu ancestor, use the main menu to close all
if ( !currentMenu.length ) {
currentMenu = this.element;
this._close( currentMenu );
// Work around active item staying active after menu is blurred
this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
this.activeMenu = currentMenu;
}, all ? 0 : this.delay );
// With no arguments, closes the currently active menu - if nothing is active
// it closes all menus. If passed an argument, it will search for menus BELOW
_close: function( startMenu ) {
startMenu = this.active ? this.active.parent() : this.element;
startMenu.find( ".ui-menu" )
.attr( "aria-hidden", "true" )
.attr( "aria-expanded", "false" );
_closeOnDocumentClick: function( event ) {
return !$( event.target ).closest( ".ui-menu" ).length;
_isDivider: function( item ) {
// Match hyphen, em dash, en dash
return !/[^\-\u2014\u2013\s]/.test( item.text() );
collapse: function( event ) {
var newItem = this.active &&
this.active.parent().closest( ".ui-menu-item", this.element );
if ( newItem && newItem.length ) {
this.focus( event, newItem );
expand: function( event ) {
var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
if ( newItem && newItem.length ) {
this._open( newItem.parent() );
// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
this._delay( function() {
this.focus( event, newItem );
next: function( event ) {
this._move( "next", "first", event );
previous: function( event ) {
this._move( "prev", "last", event );
isFirstItem: function() {
return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
_menuItems: function( menu ) {
return ( menu || this.element )
.find( this.options.items )
.filter( ".ui-menu-item" );
_move: function( direction, filter, event ) {
if ( direction === "first" || direction === "last" ) {
[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
[ direction + "All" ]( ".ui-menu-item" )
if ( !next || !next.length || !this.active ) {
next = this._menuItems( this.activeMenu )[ filter ]();
this.focus( event, next );
nextPage: function( event ) {
if ( this.isLastItem() ) {
if ( this._hasScroll() ) {
base = this.active.offset().top;
height = this.element.innerHeight();
// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
this.active.nextAll( ".ui-menu-item" ).each( function() {
return item.offset().top - base - height < 0;
this.focus( event, item );
this.focus( event, this._menuItems( this.activeMenu )
[ !this.active ? "first" : "last" ]() );
previousPage: function( event ) {
if ( this.isFirstItem() ) {
if ( this._hasScroll() ) {
base = this.active.offset().top;
height = this.element.innerHeight();
// jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
this.active.prevAll( ".ui-menu-item" ).each( function() {
return item.offset().top - base + height > 0;
this.focus( event, item );
this.focus( event, this._menuItems( this.activeMenu ).first() );
return this.element.outerHeight() < this.element.prop( "scrollHeight" );
select: function( event ) {
// TODO: It should never be possible to not have an active item at this
// point, but the tests don't trigger mouseenter before click.
this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
var ui = { item: this.active };
if ( !this.active.has( ".ui-menu" ).length ) {
this.collapseAll( event, true );
this._trigger( "select", event, ui );
_filterMenuItems: function( character ) {
var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
regex = new RegExp( "^" + escapedCharacter, "i" );
.find( this.options.items )
// Only match on items, not dividers or other content (#10571)
.filter( ".ui-menu-item" )
String.prototype.trim.call(
$( this ).children( ".ui-menu-item-wrapper" ).text() ) );