PageSourceSearch

https://issasongwriters.com/wp-content/themes/obsidian/assets/js/vendor/wp-nav-menus.js?ver=1727567091

js issasongwriters.com collected 2026-10-02 06:17:31 UTC 27,823 bytes, 948 lines download raw bytes

vendor: 1,162 bytes, lines 1-12
1/**
2 * wp-nav-menus.js
3 * https://github.com/cedaro/wp-nav-menus
4 *
5 * @copyright Copyright (c) 2016 Cedaro, LLC
6 * @license MIT
7 * @version 1.0.0
8 */
9(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.cedaroNavMenu = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
10(function (global){
11"use strict";
12var jQuery = (typeof window !== "undefined" ? window['jQuery'] : typeof global !== "undefined" ? global['jQuery'] : null),
13	wpNavMenu = require( './src/entry' );
14
15if ( jQuery ) {
16	/**
17	 * jQuery method to initialize menus.
18	 *
19	 * @memberOf jQuery.fn
20	 *
21	 * @param {Object} options Menu options.
22	 * @return {jQuery} Chainable jQuery collection.
23	 */
24	jQuery.fn.cedaroNavMenu = function( options ) {
25		return this.each(function() {
26			var menu = wpNavMenu( this, options );
27			menu.initialize();
28		});
29	};
30}
31
32/**
33 * Export the method for instantiating a new menu.
34 */
35module.exports = wpNavMenu;
36
37}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
38},{"./src/entry":2}],2:[function(require,module,exports){
39(function (global){
40"use strict";
41var l10n,
42	$ = require( './query' ),
43	customizerPartials = {},
44	NavMenu = require( './nav-menu.js' ),
45	wp = (typeof window !== "undefined" ? window['wp'] : typeof global !== "undefined" ? global['wp'] : null);
46
47// Merge global localized strings.
48l10n = $.extend({
49	collapseSubmenu: 'Collapse submenu',
50	expandSubmenu: 'Expand submenu'
51}, global._cedaroNavMenuL10n );
52
53/**
54 * Initialize a partial placement in the customizer.
55 *
56 * Managing menus in the customizer causes the placement to be replaced for
57 * each change, so it needs to be reinitialized each time to ensure submenus
58 * are accessible.
59 *
60 * @param {wp.customize.selectiveRefresh.Placement} placement Partial placement.
61 */
62function initializeCustomizePlacement( placement ) {
63	var addedMenu, removedMenu;
64
65	if ( ! ( placement.partial.id in customizerPartials ) ) {
66		return;
67	}
68
69	removedMenu = customizerPartials[ placement.partial.id ];
70	removedMenu.destroy();
71
72	// Initialize the new placement.
73	addedMenu = new NavMenu( placement.container[0], removedMenu.options );
74	addedMenu.initialize();
75
76	// Synchronize expanded states from the removed menu.
77	placement.removedNodes.find( '.' + removedMenu.options.expandedMenuItemClass ).each(function() {
78		placement.container
79			.find( '#' + this.id )
80			.find( '> .{class}, > a .{class}'.replace( /{class}/g, removedMenu.options.submenuToggleClass ) )
81			.trigger( 'click' );
82	});
83}
84
85/**
86 * Selective refresh support in the customizer.
87 */
88if ( wp && 'customize' in wp ) {
89	wp.customize.bind( 'preview-ready', function() {
90		wp.customize.selectiveRefresh.bind( 'partial-content-rendered', initializeCustomizePlacement );
91	});
92}
93
94/**
95 * Create a new menu object.
96 *
97 * @param {string|Element} el      Selector or HTML element.
98 * @param {object}         options Menu options.
99 * @return {NavMenu}               Nav menu instance.
100 */
101module.exports = function( el, options ) {
102	var menu,
103		partialId;
104
105	// Fail gracefully in unsupported browsers.
106	if ( ! ( 'addEventListener' in global ) ) {
107		return;
108	}
109
110	options = options || {};
111	options.l10n = options.l10n || {};
112
113	// Merge global localized strings.
114	$.extend( options.l10n, l10n );
115
116	menu = new NavMenu( el, options );
117
118	// Attempt to detect the partial id in the customizer and store a
119	// reference so it can be cleaned up during a selective refresh.
120	partialId = menu.el.getAttribute( 'data-customize-partial-id' );
121	if ( partialId ) {
122		customizerPartials[ partialId ] = menu;
123	}
124
125	return menu;
126};
127
128}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
129},{"./nav-menu.js":3,"./query":4}],3:[function(require,module,exports){
130"use strict";
131var $ = require ( './query' ),
132	document = window.document;
133
134/**
135 * Create a menu instance.
136 *
137 * @class NavMenu
138 *
139 * @param {Element|string} el                                 HTML element or selector.
140 * @param {object}         options                            Menu options.
141 * @param {string}         options.activeMenuItemClass        HTML class for active menu items.
142 * @param {number}         options.breakpoint                 Breakpoint to switch between mobile and full site mode.
143 * @param {boolean}        options.expandCurrentItem          Whether to expand the current menu item on initial load.
144 * @param {string}         options.expandedMenuItemClass      HTML class applied to the menu item that contains an expanded submenu.
145 * @param {string}         options.expandedSubmenuClass       HTML class applied to expanded submenus.
146 * @param {string}         options.expandedSubmenuToggleClass HTML class applied to submenu toggle buttons when the submenu is expanded.
147 * @param {number}         options.hoverTimeout               Delay in milliseconds before hiding submenus.
148 * @param {object}         options.l10n                       Localized strings specific to this instance.
149 * @param {string}         options.submenuToggleClass         HTML class for submenu toggle buttons.
150 * @param {string}         options.submenuToggleInsert        Where to insert submenu toggle buttons. Defaults to before the submenu.
151 * @param {string}         options.submenuToggleMode          Mode for displaying submenus.
152 */
153function NavMenu( el, options ) {
154	var menu = this;
155
156	this.el = $( el )[0];
157	this.options = $.extend( {}, NavMenu.defaults, options );
158	this.el.setAttribute( 'data-nav-menu-options', JSON.stringify( this.options ) );
159
160	// Automatically bind all event handlers.
161	Object.keys( Object.getPrototypeOf( this ) ).filter(function( key ) {
162		return 'function' === typeof menu[ key ] && 0 === key.indexOf( 'on' );
163	}
163).forEach(function( key ) {
164		menu[ key ] = menu[ key ].bind( menu );
165	});
166}
167
168NavMenu.defaults = {
169	breakpoint: 768, // disable
170	expandCurrentItem: false,
171	hoverTimeout: 50,
172	l10n: {},
173	submenuToggleInsert: '', // default|append|false
174	submenuToggleMode: 'hover', // hover|click; @todo hover-tap?
175
176	// Configurable HTML classes.
177	activeMenuItemClass: 'is-active',
178	expandedMenuItemClass: 'is-sub-menu-open',
179	expandedSubmenuClass: 'is-open',
180	expandedSubmenuToggleClass: 'is-open',
181	submenuToggleClass: 'sub-menu-toggle'
182};
183
184NavMenu.prototype = {
185	_initialized: false,
186	_hasExpandedSubmenu: false,
187	_hoverTimeouts: [],
188	_touchStarted: false,
189	_viewportWidth: null,
190
191	/**
192	 * Initialize the menu.
193	 *
194	 * @return {this}
195	 */
196	initialize: function() {
197		var menu = this;
198
199		if ( this._initialized ) {
200			return;
201		}
202
203		this._initialized = true;
204
205		// Ensure every menu item has an id to manage the hover state timeouts.
206		this.$items = $( 'li', this.el ).each(function( el ) {
207			el.id = $.getUid( el, 'menu-item' );
208		});
209
210		this.$submenus = $( 'li ul', this.el ).each(function( el ) {
211			el.setAttribute( 'aria-expanded', 'false' );
212		});
213
214		if ( false !== this.options.submenuToggleInsert ) {
215			this.insertSubmenuToggleButtons();
216		}
217
218		document.addEventListener( 'click', this.onDocumentClick, true );
219		this.el.addEventListener( 'click', this.onSubmenuToggleClick, false );
220
221		if ( 'hover' === this.options.submenuToggleMode /*&& 'disable' !== this.options.breakpoint*/ ) {
222			this.el.addEventListener( 'touchstart', this.onMenuLinkTouchStart, false );
223			this.el.addEventListener( 'mouseover', this.onMenuItemMouseEnter, false );
224			this.el.addEventListener( 'mouseout', this.onMenuItemMouseLeave, false );
225		}
226
227		// Use capturing mode to support event delegation.
228		// @link https://developer.mozilla.org/en-US/docs/Web/Events/blur#Event_delegation
229		this.el.addEventListener( 'focus', this.onMenuLinkFocus, true );
230		this.el.addEventListener( 'blur', this.onMenuLinkBlur, true );
231
232		// Expand current submenus on initialization.
233		if (
234			menu.options.expandCurrentItem &&
235			( 'click' === menu.options.submenuToggleMode || menu.isMobile() )
236		) {
237			this.$items.filter(function( el ) {
238				return el.classList.contains( 'current-menu-item' ) || el.classList.contains( 'current-menu-ancestor' );
239			}).each(function( el ) {
240				menu.expandSubmenu( el );
241			});
242		}
243
244		return this;
245	},
246
247	/**
248	 * Destroy the menu.
249	 *
250	 * Cleans up delegated event listeners.
251	 *
252	 * @todo Consider removing toggle buttons.
253	 */
254	destroy: function() {
255		document.removeEventListener( 'click', this.onDocumentClick, true );
256		this.el.removeEventListener( 'click', this.onSubmenuToggleClick, false );
257		this.el.removeEventListener( 'mouseover', this.onMenuItemMouseEnter, false );
258		this.el.removeEventListener( 'mouseout', this.onMenuItemMouseLeave, false );
259		this.el.removeEventListener( 'focus', this.onMenuLinkFocus, true );
260		this.el.removeEventListener( 'blur', this.onMenuLinkBlur, true );
261	},
262
263	/**
264	 * Whether the menu is in mobile mode.
265	 *
266	 * @return {boolean}
267	 */
268	isMobile: function() {
269		if ( 'disable' === this.options.breakpoint ) {
270			return true;
271		}
272
273		return this.getViewportWidth() < this.options.breakpoint;
274	},
275
276	/**
277	 * Collapse the submenu in a menu item.
278	 *
279	 * @param {Element} menuItem Menu item element.
280	 */
281	collapseSubmenu: function( menuItem ) {
282		var button = this.getSubmenuToggle( menuItem ),
283			$submenu = $( '.sub-menu', menuItem );
284
285		menuItem.classList.remove( this.options.expandedMenuItemClass );
286
287		if ( button ) {
288			button.classList.remove( this.options.expandedSubmenuToggleClass );
289			button.setAttribute( 'aria-expanded', 'false' );
290			$( '.screen-reader-text', button )[0].innerHTML = this.options.l10n.expandSubmenu || 'Expand submenu';
291		}
292
293		if ( $submenu.length ) {
294			$submenu[0].classList.remove( this.options.expandedSubmenuClass );
295			$submenu[0].setAttribute( 'aria-expanded', 'false' );
296		}
297	},
298
299	/**
300	 * Collapse all submenus.
301	 */
302	collapseAllSubmenus: function() {
303		var menu = this;
304
305		this.$items.each(function( el ) {
306			el.classList.remove( menu.options.activeMenuItemClass );
307			menu.collapseSubmenu( el );
308		});
309	},
310
311	/**
312	 * Collapse submenus in branches that don't contain the focused element.
313	 *
314	 * @param {Element} focusedEl Element that has focus.
315	 */
316	collapseUnrelatedSubmenus: function( focusedEl ) {
317		var menu = this;
318
319		this.$items.each(function( el ) {
320			if ( ! el.contains( focusedEl ) ) {
321				el.classList.remove( menu.options.activeMenuItemClass );
322				menu.collapseSubmenu( el );
323			}
324		});
325	},
326
327	/**
328	 * Expand the submenu in a menu item.
329	 *
330	 * @param {Element} menuItem Menu item element.
331	 */
332	expandSubmenu: function( menuItem ) {
333		var button = this.getSubmenuToggle( menuItem ),
334			$submenu = $( '.sub-menu', menuItem );
335
336		menuItem.classList.add( this.options.activeMenuItemClass );
337
338		if ( ! this.hasSubmenu( menuItem ) ) {
339			return;
340		}
341
342		menuItem.classList.add( this.options.expandedMenuItemClass );
343
344		if ( button ) {
345			button.classList.add( this.options.expandedSubmenuToggleClass );
346			button.setAttribute( 'aria-expanded', 'true' );
347			$( '.screen-reader-text', button )[0].innerHTML = this.options.l10n.collapseSubmenu || 'Collapse submenu';
348		}
349
350		if ( $submenu.length ) {
351			$submenu[0].classList.add( this.options.expandedSubmenuClass );
352			$submenu[0].setAttribute( 'aria-expanded', 'true' );
353		}
354	},
355
356	/**
357	 * Retrieve the viewport width.
358	 *
359	 * @return {number}
360	 */
361	getViewportWidth: function() {
362		return this._viewportWidth || Math.max( document.documentElement.clientWidth, window.innerWidth || 0 );
363	},
364
365	/**
366	 * Set the viewport width.
367	 *
368	 * @param  {number} width Width of the viewport.
369	 * @return {this}
370	 */
371	setViewportWidth: function( width ) {
372		this._viewportWidth = parseInt( width, 10 );
373		return this;
374	},
375
376	/**
377	 * Retrieve the submenu toggle button from a menu item.
378	 *
379	 * @param  {Element} menuItem Menu item element.
380	 * @return {Element}
381	 */
382	getSubmenuToggle: function( menuItem ) {
383		return $( '.' + this.options.submenuToggleClass, menuItem )[0];
384	},
385
386	/**
387	 * Whether a menu item has a submenu.
388	 *
389	 * WordPress adds the 'menu-item-has-children' class to menu items even when
390	 * the children are hidden with a depth restriction, so we have to query for
391	 * the submenu to see if it exists.
392	 *
393	 * @param  {Element}  menuItem Menu item element.
394	 * @return {Boolean}
395	 */
396	hasSubmenu: function ( menuItem ) {
397		return $( '.sub-menu', menuItem ).length > 0; //classList.contains( 'menu-item-has-children' );
398	},
399
400	/**
401	 * Insert toggle buttons in menu items that contain a submenu.
402	 */
403	insertSubmenuToggleButtons: function() {
404		var button, span,
405			menu = this;
406
407		button = document.createElement( 'button' );
408		button.setAttribute( 'class', menu.options.submenuToggleClass );
409		button.setAttribute( 'aria-expanded', 'false' );
410
411		span = document.createElement( 'span' );
412		span.setAttribute( 'class', 'screen-reader-text' );
413		span.innerHTML = this.options.l10n.expandSubmenu || 'Expand submenu';
414
415		button.appendChild( span );
416
417		this.$submenus.each(function( submenu ) {
418			var buttonInstance = button.cloneNode( true );
419
420			// Assign an id to each submenu to use in ARIA attributes.
421			if ( ! submenu.id ) {
422				submenu.id = $.getUid( submenu, 'sub-menu' );
423			}
424
425			buttonInstance.setAttribute( 'aria-controls', submenu.id );
426
427			if ( 'append' !== menu.options.submenuToggleInsert ) {
428				// Insert the toggle button before the submenu element.
429				submenu.parentElement.insertBefore( buttonInstance, submenu );
430				return;
431			}
432
433			// Append the toggle button to the parent item anchor element.
434			// This should primarily be used for backward compatibility.
435			$( submenu.parentElement.children ).each(function( el ) {
436				if ( 'A' === el.nodeName ) {
437					el.appendChild( buttonInstance );
438					return false;
439				}
440			});
441		});
442	},
443
444	isSubmenuExpanded: function( menuItem ) {
445		return menuItem.classList.contains( this.options.expandedMenuItemClass );
446	},
447
448	/**
449	 * Toggle the submenu in a menu item.
450	 *
451	 * @param {Element} menuItem Menu item element.
452	 */
453	toggleSubmenu: function( menuItem ) {
454		if ( this.isSubmenuExpanded( menuItem ) ) {
455			this.collapseSubmenu( menuItem );
456		} else {
457			this.expandSubmenu( menuItem );
458		}
459	},
460
461	/**
462	 * Collapse all submenus when clicking outside the menu.
463	 *
464	 * On touch devices without toggle buttons, tapping a link will expand
465	 * the submenu. It's not possible to close it without clicking another link
466	 * with a submenu, which leads back to the initial problem.
467	 *
468	 * Submenus also won't be collapsed when the keyboard is used to focus
469	 * an element and a click occurs outside the menu.
470	 */
471	onDocumentClick: function( e ) {
472		// Don't do this in click mode or on mobile.
473		if ( 'click' === this.options.submenuToggleMode || this.isMobile() ) {
474			return;
475		}
476
477		if ( this.el === e.target || ! this.el.contains( e.target ) ) {
478			this.collapseAllSubmenus();
479		}
480	},
481
482	/**
483	 * Handle clicks on submenu toggle buttons.
484	 *
485	 * Delegated to the menu element, so need to ensure the click is on a
486	 * toggle button before handling it.
487	 *
488	 * @param {MouseEvent} e Mouse event object.
489	 */
490	onSubmenuToggleClick: function( e ) {
491		var menuItem,
492			button = $( e.target ).closest( '.' + this.options.submenuToggleClass, this.el );
493
494		// Bail if this isn't a click on a toggle button.
495		if ( ! button ) {
496			return;
497		}
498
499		e.preventDefault();
500
501		menuItem = $( e.target ).closest( 'li', this.el );
502		this.toggleSubmenu( menuItem );
503	},
504
505	/**
506	 * Handle touchstart events on menu links.
507	 *
508	 * On touch devices, make the first click open a submenu if there isn't a
509	 * clickable toggle button available. Otherwise, the submenus w
509ouldn't be
510	 * accessible on touch devices.
511	 *
512	 * @param {TouchEvent} e Touch event object.
513	 */
514	onMenuLinkTouchStart: function( e ) {
515		var button, target;
516
517		// Bail if this isn't a touchstart on the anchor element.
518		if ( ! $.isElementOrDescendant( e.target, 'A', this.el ) ) {
519			return;
520		}
521
522		target = $( e.target ).closest( 'li', this.el );
523
524		// Bail if a target couldn't be found.
525		if ( ! target ) {
526			return;
527		}
528
529		// Bail if there isn't a submenu in this item or it's already expanded.
530		if ( ! this.hasSubmenu( target ) || this.isSubmenuExpanded( target ) ) {
531			return;
532		}
533
534		button = this.getSubmenuToggle( target );
535
536		// Expand the submenu and disable the click event if a clickable toggle
537		// button isn't available.
538		if ( ! $.isClickable( button ) ) {
539			e.stopImmediatePropagation();
540			e.preventDefault();
541			this.expandSubmenu( target );
542			this.collapseUnrelatedSubmenus( e.target );
543		} else {
544			this._touchStarted = true;
545		}
546	},
547
548	/**
549	 * Handle mouseenter events on menu items.
550	 *
551	 * When the mouse enters a menu item:
552	 * - Add an 'is-active' class to the menu item to aid in styling. Using
553	 *   the class should prevent needing to use :hover, which can cause
554	 *   double tap issues on touch devices.
555	 * - Expand the submenu if not on mobile. The toggle button should be
556	 *   used to control submenus on mobile.
557	 *
558	 * Mimics mouseenter, but is delegated to the menu element instead of
559	 * being bound to each item. The actual mouseenter event cannot be
560	 * delegated.
561	 *
562	 * @link https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter
563	 * @link http://stackoverflow.com/a/22444819
564	 * @link https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW7
565	 * @link https://patrickhlauke.github.io/touch/tests/results/
566	 *
567	 * @param {MouseEvent} e Mouse event object.
568	 */
569	onMenuItemMouseEnter: function( e ) {
570		var related, target,
571			isTouchEvent = this._touchStarted,
572			menu = this;
573
574		// Reset the touch started flag.
575		this._isTouchStarted = false;
576
577		target = $( e.target ).closest( 'li', this.el );
578		related = $( e.relatedTarget ).closest( 'li', this.el );
579
580		/*
581		 * Bail if a target couldn't be found, or if the cursor is already in
582		 * the target element. Handling mouseover events like this mimics
583		 * mousenter behavior.
584		 */
585		if ( ! target || related === target ) {
586			return;
587		}
588
589		// Clear the timeout to hide a submenu when re-entering an item.
590		$( e.target ).up( 'li', this.el ).each(function( el ) {
591			clearTimeout( menu._hoverTimeouts[ el.id ] );
592			el.classList.add( menu.options.activeMenuItemClass );
593		});
594
595		// Bail if there isn't a submenu in this item or it's already expanded.
596		if ( ! this.hasSubmenu( target ) || this.isSubmenuExpanded( target ) ) {
597			return;
598		}
599
600		/*
601		 * If a submenu has been expanded by a focus event, hovering over
602		 * unrelated menu items won't collapse the submenu. This should only
603		 * happen when the keyboard is used to focus a link, then the mouse is
604		 * used to interact with the menu. It's an edge case an may not be worth
605		 * the performance impact of looping through every item on mouseenter to
606		 * collapse unrelated submenus.
607		 */
608		// if ( ! this.isMobile() ) {
609		// 	this.collapseUnrelatedSubmenus( target );
610		// }
611
612		/*
613		 * If this event was triggered by a touchstart event and the target is
614		 * an anchor element, don't open the submenu to prevent it from flashing
615		 * before the link is followed. Also prevents a double tap from being
616		 * required on iOS.
617		 */
618		if ( ! isTouchEvent || ! $.isElementOrDescendant( e.target, 'A', this.el ) ) {
619			// Don't expand on mobile to prevent the menu from jumping.
620			if ( ! this.isMobile() ) {
621				this.expandSubmenu( target );
622			}
623		}
624	},
625
626	/**
627	 * Handle mouseleave events on menu items.
628	 *
629	 * When the mouse leaves a menu item, collapse submenus  and remove the
630	 * 'is-active' class for any menu items that no longer have the cursor
631	 * hovering over them.
632	 *
633	 * Mimics mouseleave, but is delegated to the menu element instead of
634	 * being bound to each item.
635	 *
636	 * @link https://developer.mozilla.org/en-US/docs/Web/Events/mouseleave
637	 *
638	 * @param {MouseEvent} e Moust event object.
639	 */
640	onMenuItemMouseLeave: function( e ) {
641		var menu = this,
642			isMobile = menu.isMobile();
643
644		$( e.target ).up( 'li', this.el ).filter(function( el ) {
645			return el !== e.relatedTarget && ! el.contains( e.relatedTarget );
646		}).each(function( el ) {
647			el.classList.remove( menu.options.activeMenuItemClass );
648
649			// Bail in mobile mode to prevent the menu from jumping.
650			if ( isMobile ) {
651				return;
652			}
653
654			menu._hoverTimeouts[ el.id ] = setTimeout(function() {
655				menu.collapseSubmenu( el );
656			}, menu.options.hoverTimeout );
657		});
658	},
659
660	/**
661	 * Handle the focus event on elements within the menu.
662	 *
663	 * Aids keyboard navigation by:
664	 * - Collapsing submenus in unrelated items to prevent submenus from
665	 *   overlapping in full screen mode. This is not done in mobile mode to
666	 *   prevent the menu from jumping when tabbing through items.
667	 * - Adding an 'is-active' class to ancestor menu items when any
668	 *   descendant is focused.
669	 * - Expanding a submenu when an element (link or toggle button) in the
670	 *   parent menu item receives focus.
671	 *
672	 * @param {FocusEvent} e Focus event object.
673	 */
674	onMenuLinkFocus: function( e ) {
675		var button, $parents,
676			menu = this;
677
678		// Collapse unrelated submenus except in mobile mode.
679		if ( 'click' !== menu.options.submenuToggleMode && ! menu.isMobile() ) {
680			menu.collapseUnrelatedSubmenus( e.target );
681		}
682
683		$parents = $( e.target ).parents( 'li', menu.el ).each(function( el ) {
684			el.classList.add( menu.options.activeMenuItemClass );
685		});
686
687		// Bail if the target menu item doesn't have a submenu.
688		if ( ! menu.hasSubmenu( $parents[ 0 ] ) ) {
689			return;
690		}
691
692		button = this.getSubmenuToggle( $parents[0] );
693
694		/*
695		 * Expand the submenu if a toggle button isn't visible.
696		 *
697		 * Also expands parents since keyboards can access elements positioned
698		 * off-screen, so reverse tabbing through a menu needs to make sure
699		 * parents are visible.
700		 */
701		if ( ! button || ! $.isVisible( button ) ) {
702			$parents.each(function( el ) {
703				menu.expandSubmenu( el );
704			});
705		}
706	},
707
708	/**
709	 * Close submenus when focus leaves the containing item.
710	 *
711	 * Aids keyboard navigation in full screen mode by preventing multiple
712	 * expanded submenus from overlapping when tabbing through items.
713	 *
714	 * The relatedTarget property isn't available in some browsers for focus
715	 * events, so it's not possible to grab the focused element in a blur
716	 * event handler. For that reason, unrelated submenus are also collapsed in
717	 * onMenuLinkFocus.
718	 *
719	 * @link https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/relatedTarget
720	 *
721	 * @todo Blur events sent when clicking outside the element the event is
722	 *       bound to also send null for the relatedTarget. This prevents
723	 *       clicking anywhere else in the document from collapsing the submenu.
724	 *
725	 * @param {FocusEvent} e Focus event object.
726	 */
727	onMenuLinkBlur: function( e ) {
728		var menu = this;
729
730		// Remove the activeMenuItemClass from the parent menu items.
731		$( e.target ).parents( 'li', menu.el ).each(function( el ) {
732			el.classList.remove( menu.options.activeMenuItemClass );
733		});
734
735		// Bail if the relatedTarget event is null.
736		if ( ! e.relatedTarget ) {
737			return;
738		}
739
740		// Disable on mobile to prevent the menu from jumping while tabbing
741		// through menu items and toggle buttons.
742		if ( 'click' === menu.options.submenuToggleMode || menu.isMobile() ) {
743			return;
744		}
745
746		menu.collapseUnrelatedSubmenus( e.relatedTarget );
747	}
748};
749
750module.exports = NavMenu;
751
752},{"./query":4}],4:[function(require,module,exports){
753"use strict";
754var _ = require( './utils' );
755
756function Query( selector, context ) {
757	var i, length;
758
759	if ( selector instanceof Query ) {
760		return selector;
761	}
762
763	if ( ! selector ) {
764		return this;
765	}
766
767	context = context || document;
768	if ( context.length ) {
769		context = context[0];
770	}
771
772	if ( 'string' === typeof selector ) {
773		selector = context.querySelectorAll( selector );
774	}
775
776	if ( selector && selector.nodeType ) {
777		this.length = 1;
778		this[0] = selector;
779	} else {
780		selector = Array.prototype.slice.call( selector );
781		length = this.length = selector.length;
782
783		for ( i = 0; i < length; i++ ) {
784			this[ i ] = selector[ i ];
785		}
786	}
787}
788
789_.extend( Query.prototype, {
790	length: 0,
791
792	closest: function( selector, context ) {
793		var el = this[0];
794		context = context || document.body;
795
796		while ( el && el !== context ) {
797			if ( _.matches( el, selector ) ) {
798				return el;
799			}
800
801			el = el.parentElement;
802		}
803
804		return null;
805	},
806
807	each: function( callback ) {
808		_.each( this, callback );
809		return this;
810	},
811
812	filter: function( callback ) {
813		return query( Array.prototype.filter.call( this, callback ) );
814	},
815
816	/**
817	 * @todo Improve performance: http://ryanmorr.com/abstract-away-the-performance-faults-of-queryselectorall/
818	 */
819	find: function( selector ) {
820		return query( this[0].querySelectorAll( selector ) );
821	},
822
823	parents: function( selector, context ) {
824		var el = this[0],
825			parents = [];
826
827		context = context || document.body;
828
829		while ( el && el.parentElement && el.parentElement !== context ) {
830			if ( _.matches( el.parentElement, selector ) ) {
831				parents.push( el.parentElement );
832			}
833			el = el.parentElement;
834		}
835
836		return query( parents );
837	},
838
839	up: function( selector, context ) {
840		var items = Array.prototype.slice.call( this.parents( selector, context ) );
841
842		if ( _.matches( this[0], selector ) ) {
843			items.unshift( this[0] );
844		}
845
846		return query( items );
847	}
848});
849
850function query( selector, context ) {
851	return new Query( selector, context );
852}
853
854module.exports = _.extend( query, _, {
855	isClickable: function( el ) {
856		var styles;
857
858		if ( ! el ) {
859			return false;
860		}
861
862		styles = window.getComputedStyle( el );
863		return 'none' !== styles.display && 'none' !== styles.pointerEvents;
864	},
865
866	isElementOrDescendant: function( el, tagName, container ) {
867		return tagName === el.nodeName || null !== query( el ).closest( tagName, container );
868	},
869
870	isVisible: function( el ) {
871		return el && 'none' !== window.getComputedStyle( el ).display;
872	}
873});
874
875},{"./utils":5}],5:[function(require,module,exports){
876"use strict";
877function each( items, callback ) {
878	var i,
879		length = items.length;
880
881	for ( i = 0; i < length; i++ ) {
882		if ( false === callback.call( items[i], items[i], i ) ) {
883			break;
884		}
885	}
886}
887
888function extend( target ) {
889	var i = 0,
890		length = arguments.length;
891
892	target = target || {};
893
894	while ( ++i < length ) {
895		if ( ! arguments[ i ] ) {
896			continue;
897		}
898
899		for ( var key in arguments[ i ] ) {
900			if ( arguments[ i ].hasOwnProperty( key ) ) {
901				target[ key ] = arguments[ i ][ key ];
902			}
903		}
904	}
905
906	return target;
907}
908
909function generateUniqueId( prefix ) {
910	prefix = prefix || '';
911	if ( '' !== prefix ) {
912		prefix += '-';
913	}
914	return prefix + Math.random().toString( 36 ).slice( 2, 15 );
915}
916
917function getUniqueId( el, prefix ) {
918	if ( el.id ) {
919		return el.id;
920	}
921
922	return generateUniqueId( prefix );
923}
924
925/**
926 * @link https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
927 */
928function matches( el, selector ) {
929	var fn = el && (
930		el.matches ||
931		el.webkitMatchesSelector ||
932		el.mozMatchesSelector ||
933		el.msMatchesSelector ||
934		el.oMatchesSelector
935	);
936
937	return !! fn && fn.call( el, selector );
938}
939
940module.exports = {
941	each: each,
942	extend: extend,
943	getUid: getUniqueId,
944	matches: matches
945};
946
947},{}]},{},[1])(1)
948});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.