PageSourceSearch

https://liberocanto.org/wp-content/themes/merchato/assets/js/vendor/wp-nav-menus.js?ver=2.0.0

js liberocanto.org collected 2026-10-10 01:59:35 UTC 34,671 bytes, 1,186 lines download raw bytes

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

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.