PageSourceSearch

https://cambioycorto.es/wp-content/themes/cherie/assets/js/vendors-libs/mega-menu.js?ver=1.10.6

js cambioycorto.es collected 2026-10-08 23:17:05 UTC 47,114 bytes, 1,070 lines download raw bytes

1/*
2Copyright © 2013 Adobe Systems Incorporated.
3
4Licensed under the Apache License, Version 2.0 (the “License”);
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an “AS IS” BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17/**
18 * See <a href="http://jquery.com">http://jquery.com</a>.
19 * @name jquery
20 * @class
21 * See the jQuery Library  (<a href="http://jquery.com">http://jquery.com</a>) for full details.  This just
22 * documents the function and classes that are added to jQuery by this plug-in.
23 */
24
25/**
26 * See <a href="http://jquery.com">http://jquery.com</a>
27 * @name fn
28 * @class
29 * See the jQuery Library  (<a href="http://jquery.com">http://jquery.com</a>) for full details.  This just
30 * documents the function and classes that are added to jQuery by this plug-in.
31 * @memberOf jquery
32 */
33
34/**
35 * @fileOverview accessibleMegaMenu plugin
36 *
37 *<p>Licensed under the Apache License, Version 2.0 (the “License”)
38 *<br />Copyright © 2013 Adobe Systems Incorporated.
39 *<br />Project page <a href="https://github.com/adobe-accessibility/Accessible-Mega-Menu">https://github.com/adobe-accessibility/Accessible-Mega-Menu</a>
40 * @version 0.1
41 * @author Michael Jordan
42 * @requires jquery
43 */
44
45/*jslint browser: true, devel: true, plusplus: true, nomen: true */
46/*global jQuery */
47(function ($, window, document) {
48    "use strict";
49    var pluginName = "accessibleMegaMenu",
50        defaults = {
51            uuidPrefix: "accessible-megamenu", // unique ID's are required to indicate aria-owns, aria-controls and aria-labelledby
52            menuClass: "accessible-megamenu", // default css class used to define the megamenu styling
53            topNavItemClass: "accessible-megamenu-top-nav-item", // default css class for a top-level navigation item in the megamenu
54            panelClass: "accessible-megamenu-panel", // default css class for a megamenu panel
55            panelGroupClass: "accessible-megamenu-panel-group", // default css class for a group of items within a megamenu panel
56            hoverClass: "hover", // default css class for the hover state
57            focusClass: "focus", // default css class for the focus state
58            openClass: "open", // default css class for the open state
59            openDelay: 0, // default open delay when opening menu via mouseover
60            closeDelay: 250 // default open delay when opening menu via mouseover
61        },
62        Keyboard = {
63            BACKSPACE: 8,
64            COMMA: 188,
65            DELETE: 46,
66            DOWN: 40,
67            END: 35,
68            ENTER: 13,
69            ESCAPE: 27,
70            HOME: 36,
71            LEFT: 37,
72            PAGE_DOWN: 34,
73            PAGE_UP: 33,
74            PERIOD: 190,
75            RIGHT: 39,
76            SPACE: 32,
77            TAB: 9,
78            UP: 38,
79            keyMap: {
80                48: "0",
81                49: "1",
82                50: "2",
83                51: "3",
84                52: "4",
85                53: "5",
86                54: "6",
87                55: "7",
88                56: "8",
89                57: "9",
90                59: ";",
91                65: "a",
92                66: "b",
93                67: "c",
94                68: "d",
95                69: "e",
96                70: "f",
97                71: "g",
98                72: "h",
99                73: "i",
100                74: "j",
101                75: "k",
102                76: "l",
103                77: "m",
104                78: "n",
105                79: "o",
106                80: "p",
107                81: "q",
108                82: "r",
109                83: "s",
110                84: "t",
111                85: "u",
112                86: "v",
113                87: "w",
114                88: "x",
115                89: "y",
116                90: "z",
117                96: "0",
118                97: "1",
119                98: "2",
120                99: "3",
121                100: "4",
122                101: "5",
123                102: "6",
124                103: "7",
125                104: "8",
126                105: "9",
127                190: "."
128            }
129        };
130    /**
131     * @desc Creates a new accessible mega menu instance.
132     * @param {jquery} element
133     * @param {object} [options] Mega Menu options
134     * @param {string} [options.uuidPrefix=accessible-megamenu] - Prefix for generated unique id attributes, which are required to indicate aria-owns, aria-controls and aria-labelledby
135     * @param {string} [options.menuClass=accessible-megamenu] - CSS class used to define the megamenu styling
136     * @param {string} [options.topNavItemClass=accessible-megamenu-top-nav-item] - CSS class for a top-level navigation item in the megamenu
137     * @param {string} [options.panelClass=accessible-megamenu-panel] - CSS class for a megamenu panel
138     * @param {string} [options.panelGroupClass=accessible-megamenu-panel-group] - CSS class for a group of items within a megamenu panel
139     * @param {string} [options.hoverClass=hover] - CSS class for the hover state
140     * @param {string} [options.focusClass=focus] - CSS class for the focus state
141     * @param {string} [options.openClass=open] - CSS class for the open state
142     * @constructor
143     */
144    function AccessibleMegaMenu(element, options) {
145        this.element = element;
146
147        // merge optional settings and defaults into settings
148        this.settings = $.extend({}, defaults, options);
149
150        this._defaults = defaults;
151        this._name = pluginName;
152
153        this.mouseTimeoutID = null;
154        this.focusTimeoutID = null;
155        this.mouseFocused = false;
156        this.justFocused = false;
157
158        this.init();
159    }
160
161    AccessibleMegaMenu.prototype = (function () {
162
163        /* private attributes and methods ------------------------ */
164        var uuid = 0,
165            keydownTimeoutDuration = 1000,
166            keydownSearchString = "",
167            isTouch = typeof window.hasOwnProperty === "function" && !!window.hasOwnProperty("ontouchstart"),
168            _getPlugin,
169            _addUniqueId,
170            _togglePanel,
171            _clickHandler,
172            _clickOutsideHandler,
173            _DOMAttrModifiedHandler,
174            _focusInHandler,
175            _focusOutHandler,
176            _keyDownHandler,
177            _mouseDownHandler,
178            _mouseOverHandler,
179            _mouseOutHandler,
180            _toggleExpandedEventHandlers;
181
182        /**
183         * @name jQuery.fn.accessibleMegaMenu~_getPlugin
184         * @desc Returns the parent accessibleMegaMenu instance for a given element
185         * @param {jQuery} element
186         * @memberof jQuery.fn.accessibleMegaMenu
187         * @inner
188         * @private
189         */
190        _getPlugin = function (element) {
191            return $(element).closest(':data(plugin_' + pluginName + ')').data("plugin_" + pluginName);
192        };
193
194        /**
195         * @name jQuery.fn.accessibleMegaMenu~_addUniqueId
196         * @desc Adds a unique id and element.
197         * The id string starts with the
198         * string defined in settings.uuidPrefix.
199         * @param {jQuery} element
200         * @memberof jQuery.fn.accessibleMegaMenu
201         * @inner
202         * @private
203         */
204        _addUniqueId = function (element) {
205            element = $(element);
206            var settings = this.settings;
207            if (!element.attr("id")) {
208                element.attr("id", settings.uuidPrefix + "-" + new Date().getTime() + "-" + (++uuid));
209            }
210        };
211
212        /**
213         * @name jQuery.fn.accessibleMegaMenu~_togglePanel
214         * @desc Toggle the display of mega menu panels in response to an event.
215         * The optional boolean value 'hide' forces all panels to hide.
216         * @param {event} event
217         * @param {Boolean} [hide] Hide all mega menu panels when true
218         * @memberof jQuery.fn.accessibleMegaMenu
219         * @inner
220         * @private
221         */
222        _togglePanel = function (event, hide) {
223            var target = $(event.target),
224                that = this,
225                settings = this.settings,
226                menu = this.menu,
227                topli = target.closest('.' + settings.topNavItemClass),
228                panel = target.hasClass(settings.panelClass) ? target : target.closest('.' + settings.panelClass),
229                newfocus;
230
231            _toggleExpandedEventHandlers.call(this, true);
232
233            if (hide) {
234                topli = menu.find('.' + settings.topNavItemClass + ' .' + settings.openClass + ':first').closest('.' + settings.topNavItemClass);
235                if (!(topli.is(event.relatedTarget) || topli.has(event.relatedTarget).length > 0)) {
236                    if ((event.type === 'mouseout' || event.type === 'focusout') && topli.has(document.activeElement).length > 0) {
237                        return;
238                    }
239                    topli.find('[aria-expanded]')
240                        .attr('aria-expanded', 'false')
241                        .removeClass(settings.openClass)
242                        .filter('.' + settings.panelClass)
243                        .attr('aria-hidden', 'true');
244                    if ((event.type === 'keydown' && event.keyCode === Keyboard.ESCAPE) || event.type === 'DOMAttrModified') {
245                        newfocus = topli.find(':tabbable:first');
246                        setTimeout(function () {
247                            menu.find('[aria-expanded].' + that.settings.panelClass).off('DOMAttrModified.accessible-megamenu');
248                            newfocus.focus();
249                            that.justFocused = false;
250                        }, 99);
251                    }
252                } else if (topli.length === 0) {
253                    menu.find('[aria-expanded=true]')
254                        .attr('aria-expanded', 'false')
255                        .removeClass(settings.openClass)
256                        .filter('.' + settings.panelClass)
257                        .attr('aria-hidden', 'true');
258                }
259            } else {
260                clearTimeout(that.focusTimeoutID);
261                topli.siblings()
262                    .find('[aria-expanded]')
263                    .attr('aria-expanded', 'false')
264                    .removeClass(settings.openClass)
265                    .filter('.' + settings.panelClass)
266                    .attr('aria-hidden', 'true');
267                topli.find('[aria-expanded]')
268                    .attr('aria-expanded', 'true')
269                    .addClass(settings.openClass)
270                    .filter('.' + settings.panelClass)
271                    .attr('aria-hidden', 'false');
272                if (event.type === 'mouseover' && target.is(':tabbable') && topli.length === 1 && panel.length === 0 && menu.has(document.activeElement).length > 0) {
273                    target.focus();
274                    that.justFocused = false;
275                }
276
277                _toggleExpandedEventHandlers.call(that);
278            }
279        };
280
281        /**
282         * @name jQuery.fn.accessibleMegaMenu~_clickHandler
283         * @desc Handle click event on mega menu item
284         * @param {event} Event object
285         * @memberof jQuery.fn.accessibleMegaMenu
286         * @inner
287         * @private
288         */
289        _clickHandler = function (event) {
290            var target = $(event.target).closest(':tabbable'),
291                topli = target.closest('.' + this.settings.topNavItemClass),
292                panel = target.closest('.' + this.settings.panelClass);
293            if (topli.length === 1
294                && panel.length === 0
295                && topli.find('.' + this.settings.panelClass).length === 1) {
296                if (!target.hasClass(this.settings.openClass)) {
297                    event.preventDefault();
298                    event.stopPropagation();
299                    _togglePanel.call(this, event);
300                    this.justFocused = false;
301                } else {
302                    if (this.justFocused) {
303                        event.preventDefault();
304                        event.stopPropagation();
305                        this.justFocused = false;
306                    } else if (isTouch) {
307                        event.preventDefault();
308                        event.stopPropagation();
309                        _togglePanel.call(this, event, target.hasClass(this.settings.openClass));
310                    }
311                }
312            }
313        };
314
315        /**
316         * @name jQuery.fn.accessibleMegaMenu~_clickOutsideHandler
317         * @desc Handle click event outside of a the megamenu
318         * @param {event} Event object
319         * @memberof jQuery.fn.accessibleMegaMenu
320         * @inner
321         * @private
322         */
323        _clickOutsideHandler = function (event) {
324            if ($(event.target).closest(this.menu).length === 0) {
325                event.preventDefault();
326                event.stopPropagation();
327                _togglePanel.call(this, event, true);
328            }
329        };
330
331        /**
332         * @name jQuery.fn.accessibleMegaMenu~_DOMAttrModifiedHandler
333         * @desc Handle DOMAttrModified event on panel to respond to Windows 8 Narrator ExpandCollapse pattern
334         * @param {event} Event object
335         * @memberof jQuery.fn.accessibleMegaMenu
336         * @inner
337         * @private
338         */
339        _DOMAttrModifiedHandler = function (event) {
340            if (event.originalEvent.attrName === 'aria-expanded'
341                && event.originalEvent.newValue === 'false'
342                && $(event.target).hasClass(this.settings.openClass)) {
343                event.preventDefault();
344                event.stopPropagation();
345                _togglePanel.call(this, event, true);
346            }
347        };
348
349        /**
350         * @name jQuery.fn.accessibleMegaMenu~_focusInHandler
351         * @desc Handle focusin event on mega menu item.
352         * @param {event} Event object
353         * @memberof jQuery.fn.accessibleMegaMenu
354         * @inner
355         * @private
356         */
357        _focusInHandler = function (event) {
358            clearTimeout(this.focusTimeoutID);
359            var target = $(event.target),
360                panel = target.closest('.' + this.settings.panelClass);
361            target
362                .addClass(this.settings.focusClass)
363                .on('click.accessible-megamenu', $.proxy(_clickHandler, this));
364            this.justFocused = !this.mouseFocused;
365            this.mouseFocused = false;
366            if (this.panels.not(panel).filter('.' + this.settings.openClass).length) {
367                _togglePanel.call(this, event);
368            }
369        };
370
371        /**
372         * @name jQuery.fn.accessibleMegaMenu~_focusOutHandler
373         * @desc Handle focusout event on mega menu item.
374         * @param {event} Event object
375         * @memberof jQuery.fn.accessibleMegaMenu
376         * @inner
377         * @private
378         */
379        _focusOutHandler = function (event) {
380            this.justFocused = false;
381            var that = this,
382                target = $(event.target),
383                topli = target.closest('.' + this.settings.topNavItemClass),
384                keepOpen = false;
385            target
386                .removeClass(this.settings.focusClass)
387                .off('click.accessible-megamenu');
388
389            if (window.cvox) {
390                // If ChromeVox is running...
391                that.focusTimeoutID = setTimeout(function () {
392                    window.cvox.Api.getCurrentNode(function (node) {
393                        if (topli.has(node).length) {
394                            // and the current node being voiced is in
395                            // the mega menu, clearTimeout,
396                            // so the panel stays open.
397                            clearTimeout(that.focusTimeoutID);
398                        } else {
399                            that.focusTimeoutID = setTimeout(function (scope, event, hide) {
400                                _togglePanel.call(scope, event, hide);
401                            }, 275, that, event, true);
402                        }
403                    });
404                }, 25);
405            } else {
406                that.focusTimeoutID = setTimeout(function () {
407                    _togglePanel.call(that, event, true);
408                }, 300);
409            }
410        };
411
412        /**
413         * @name jQuery.fn.accessibleMegaMenu~_keyDownHandler
414         * @desc Handle keydown event on mega menu.
415         * @param {event} Event object
416         * @memberof jQuery.fn.accessibleMegaMenu
417         * @inner
418         * @private
419         */
420        _keyDownHandler = function (event) {
421            var that = (this.constructor === AccessibleMegaMenu) ? this : _getPlugin(this), // determine the AccessibleMegaMenu plugin instance
422                settings = that.settings,
423                target = $($(this).is('.' + settings.hoverClass + ':tabbable') ? this : event.target), // if the element is hovered the target is this, otherwise, its the focused element
424                menu = that.menu,
425                topnavitems = that.topnavitems,
426                topli = target.closest('.' + settings.topNavItemClass),
427                tabbables = menu.find(':tabbable'),
428                panel = target.hasClass(settings.panelClass) ? target : target.closest('.' + settings.panelClass),
429                panelGroups = panel.find('.' + settings.panelGroupClass),
430                currentPanelGroup = target.closest('.' + settings.panelGroupClass),
431                next,
432                keycode = event.keyCode || event.which,
433                start,
434                i,
435                o,
436                label,
437                found = false,
438                newString = Keyboard.keyMap[event.keyCode] || '',
439                regex,
440                isTopNavItem = (topli.length === 1 && panel.length === 0);
441
442            if (target.is("input:focus, select:focus, textarea:focus, button:focus")) {
443                // if the event target is a form element we should handle keydown normally
444                return;
445            }
446
447            if (target.is('.' + settings.hoverClass + ':tabbable')) {
448                $('html').off('keydown.accessible-megamenu');
449            }
450
451            switch (keycode) {
452                case Keyboard.ESCAPE:
453                    _togglePanel.call(that, event, true);
454                    break;
455                case Keyboard.DOWN:
456                    event.preventDefault();
457                    if (isTopNavItem) {
458                        _togglePanel.call(that, event);
459                        found = (topli.find('.' + settings.panelClass + ' :tabbable:first').focus().length === 1);
460                    } else {
461                        found = (tabbables.filter(':gt(' + tabbables.index(target) + '):first').focus().length === 1);
462                    }
463
464                    if (!found && window.opera && opera.toString() === "[object Opera]" && (event.ctrlKey || event.metaKey)) {
465                        tabbables = $(':tabbable');
466                        i = tabbables.index(target);
467                        found = ($(':tabbable:gt(' + $(':tabbable').index(target) + '):first').focus().length === 1);
468                    }
469                    break;
470                case Keyboard.UP:
471                    event.preventDefault();
472                    if (isTopNavItem && target.hasClass(settings.openClass)) {
473                        _togglePanel.call(that, event, true);
474                        next = topnavitems.filter(':lt(' + topnavitems.index(topli) + '):last');
475                        if (next.children('.' + settings.panelClass).length) {
476                            found = (next.children()
477                                .attr('aria-expanded', 'true')
478                                .addClass(settings.openClass)
479                                .filter('.' + settings.panelClass)
480                                .attr('aria-hidden', 'false')
481                                .find(':tabbable:last')
482                                .focus() === 1);
483                        }
484                    } else if (!isTopNavItem) {
485                        found = (tabbables.filter(':lt(' + tabbables.index(target) + '):last').focus().length === 1);
486                    }
487
488                    if (!found && window.opera && opera.toString() === "[object Opera]" && (event.ctrlKey || event.metaKey)) {
489                        tabbables = $(':tabbable');
490                        i = tabbables.index(target);
491                        found = ($(':tabbable:lt(' + $(':tabbable').index(target) + '):first').focus().length === 1);
492                    }
493                    break;
494                case Keyboard.RIGHT:
495                    event.preventDefault();
496                    if (isTopNavItem) {
497                        found = (topnavitems.filter(':gt(' + topnavitems.index(topli) + '):first').find(':tabbable:first').focus().length === 1);
498                    } else {
499                        if (panelGroups.length && currentPanelGroup.length) {
500                            // if the current panel contains panel groups, and we are able to focus the first tabbable element of the next panel group
501                            found = (panelGroups.filter(':gt(' + panelGroups.index(currentPanelGroup) + '):first').find(':tabbable:first').focus().length === 1);
502                        }
503
504                        if (!found) {
505                            found = (topli.find(':tabbable:first').focus().length === 1);
506                        }
507                    }
508                    break;
509                case Keyboard.LEFT:
510                    event.preventDefault();
511                    if (isTopNavItem) {
512                        found = (topnavitems.filter(':lt(' + topnavitems.index(topli) + '):last').find(':tabbable:first').focus().length === 1);
513                    } else {
514                        if (panelGroups.length && currentPanelGroup.length) {
515                            // if the current panel contains panel groups, and we are able to focus the first tabbable element of the previous panel group
516                            found = (panelGroups.filter(':lt(' + panelGroups.index(currentPanelGroup) + '):last').find(':tabbable:first').focus().length === 1);
517                        }
518
519                        if (!found) {
520                            found = (topli.find(':tabbable:first').focus().length === 1);
521                        }
522                    }
523                    break;
524                case Keyboard.TAB:
525                    i = tabbables.index(target);
526                    if (event.shiftKey && isTopNavItem && target.hasClass(settings.openClass)) {
527                        _togglePanel.call(that, event, true);
528                        next = topnavitems.filter(':lt(' + topnavitems.index(topli) + '):last');
529                        if (next.children('.' + settings.panelClass).length) {
530                            found = next.children()
531                                .attr('aria-expanded', 'true')
532                                .addClass(settings.openClass)
533                                .filter('.' + settings.panelClass)
534                                .attr('aria-hidden', 'false')
535                                .find(':tabbable:last')
536                                .focus();
537                        }
538                    } else if (event.shiftKey && i > 0) {
539                        found = (tabbables.filter(':lt(' + i + '):last').focus().length === 1);
540                    } else if (!event.shiftKey && i < tabbables.length - 1) {
541                        found = (tabbables.filter(':gt(' + i + '):first').focus().length === 1);
542                    } else if (window.opera && opera.toString() === "[object Opera]") {
543                        tabbables = $(':tabbable');
544                        i = tabbables.index(target);
545                        if (event.shiftKey) {
546                            found = ($(':tabbable:lt(' + $(':tabbable').index(target) + '):last').focus().length === 1);
547                        } else {
548                            found = ($(':tabbable:gt(' + $(':tabbable').index(target) + '):first').focus().length === 1);
549                        }
550                    }
551
552                    if (found) {
553                        event.preventDefault();
554                    }
555                    break;
556                case Keyboard.SPACE:
557                    if (isTopNavItem) {
558                        event.preventDefault();
559                        _clickHandler.call(that, event);
560                    } else {
561                        return true;
562                    }
563                    break;
564                case Keyboard.ENTER:
565                    return true;
566                    break;
567                default:
568                    // alphanumeric filter
569                    clearTimeout(this.keydownTimeoutID);
570
571                    keydownSearchString += newString !== keydownSearchString ? newString : '';
572
573                    if (keydownSearchString.length === 0) {
574                        return;
575                    }
576
577                    this.keydownTimeoutID = setTimeout(function () {
578                        keydownSearchString = '';
579                    }, keydownTimeoutDuration);
580
581                    if (isTopNavItem && !target.hasClass(settings.openClass)) {
582                        tabbables = tabbables.filter(':not(.' + settings.panelClass + ' :tabbable)');
583                    } else {
584                        tabbables = topli.find(':tabbable');
585                    }
586
587                    if (event.shiftKey) {
588                        tabbables = $(tabbables.get()
589                            .reverse());
590                    }
591
592                    for (i = 0; i < tabbables.length; i++) {
593                        o = tabbables.eq(i);
594                        if (o.is(target)) {
595                            start = (keydownSearchString.length === 1) ? i + 1 : i;
596                            break;
597                        }
598                    }
599
600                    regex = new RegExp('^' + keydownSearchString.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'), 'i');
601
602                    for (i = start; i < tabbables.length; i++) {
603                        o = tabbables.eq(i);
604                        label = $.trim(o.text());
605                        if (regex.test(label)) {
606                            found = true;
607                            o.focus();
608                            break;
609                        }
610                    }
611                    if (!found) {
612                        for (i = 0; i < start; i++) {
613                            o = tabbables.eq(i);
614                            label = $.trim(o.text());
615                            if (regex.test(label)) {
616                                o.focus();
617                                break;
618                            }
619                        }
620                    }
621                    break;
622            }
623            that.justFocused = false;
624        };
625
626        /**
627         * @name jQuery.fn.accessibleMegaMenu~_mouseDownHandler
628         * @desc Handle mousedown event on mega menu.
629         * @param {event} Event object
630         * @memberof accessibleMegaMenu
631         * @inner
632         * @private
633         */
634        _mouseDownHandler = function (event) {
635            if ($(event.target).is(this.settings.panelClass) || $(event.target).closest(":focusable").length) {
636                this.mouseFocused = true;
637            }
638            clearTimeout(this.mouseTimeoutID);
639            this.mouseTimeoutID = setTimeout(function () {
640                clearTimeout(this.focusTimeoutID);
641            }, 1);
642        };
643
644        /**
645         * @name jQuery.fn.accessibleMegaMenu~_mouseOverHandler
646         * @desc Handle mouseover event on mega menu.
647         * @param {event} Event object
648         * @memberof jQuery.fn.accessibleMegaMenu
649         * @inner
650         * @private
651         */
652        _mouseOverHandler = function (event) {
653            clearTimeout(this.mouseTimeoutID);
654            var that = this;
655            this.mouseTimeoutID = setTimeout(function () {
656                $(event.target).addClass(that.settings.hoverClass);
657                _togglePanel.call(that, event);
658                if ($(event.target).is(':tabbable')) {
659                    $('html').on('keydown.accessible-megamenu', $.proxy(_keyDownHandler, event.target));
660                }
661            }, this.settings.openDelay);
662        };
663
664        /**
665         * @name jQuery.fn.accessibleMegaMenu~_mouseOutHandler
666         * @desc Handle mouseout event on mega menu.
667         * @param {event} Event object
668         * @memberof jQuery.fn.accessibleMegaMenu
669         * @inner
670         * @private
671         */
672        _mouseOutHandler = function (event) {
673            clearTimeout(this.mouseTimeoutID);
674            var that = this;
675            $(event.target)
676                .removeClass(that.settings.hoverClass);
677
678            that.mouseTimeoutID = setTimeout(function () {
679                _togglePanel.call(that, event, true);
680            }, this.settings.closeDelay);
681            if ($(event.target).is(':tabbable')) {
682                $('html').off('keydown.accessible-megamenu');
683            }
684        };
685
686        _toggleExpandedEventHandlers = function (hide) {
687            var menu = this.menu;
688            if (hide) {
689                $('html').off('mouseup.outside-accessible-megamenu, touchend.outside-accessible-megamenu, mspointerup.outside-accessible-megamenu,  pointerup.outside-accessible-megamenu');
690
691                menu.find('[aria-expanded].' + this.settings.panelClass).off('DOMAttrModified.accessible-megamenu');
692            } else {
693                $('html').on('mouseup.outside-accessible-megamenu, touchend.outside-accessible-megamenu, mspointerup.outside-accessible-megamenu,  pointerup.outside-accessible-megamenu', $.proxy(_clickOutsideHandler, this));
694
695                /* Narrator in Windows 8 automatically toggles the aria-expanded property on double tap or click.
696                   To respond to the change to collapse the panel, we must add a listener for a DOMAttrModified event. */
697                menu.find('[aria-expanded=true].' + this.settings.panelClass).on('DOMAttrModified.accessible-megamenu', $.proxy(_DOMAttrModifiedHandler, this));
698            }
699        };
700
701        /* public attributes and methods ------------------------- */
702        return {
703            constructor: AccessibleMegaMenu,
704
705            /**
706             * @lends jQuery.fn.accessibleMegaMenu
707             * @desc Initializes an instance of the accessibleMegaMenu plugins
708             * @memberof jQuery.fn.accessibleMegaMenu
709             * @instance
710             */
711            init: function () {
712                var settings = this.settings,
713                    nav = $(this.element),
714                    menu = nav.children().first(),
715                    topnavitems = menu.children();
716                this.start(settings, nav, menu, topnavitems);
717            },
718
719            start: function(settings, nav, menu, topnavitems) {
720                var that = this;
721                this.settings = settings;
722                this.menu = menu;
723                this.topnavitems = topnavitems;
724
725                nav.attr("role", "navigation");
726                menu.addClass(settings.menuClass);
727                topnavitems.each(function (i, topnavitem) {
728                    var topnavitemlink, topnavitempanel;
729                    topnavitem = $(topnavitem);
730                    topnavitem.addClass(settings.topNavItemClass);
731                    topnavitemlink = topnavitem.find(":tabbable:first");
732                    topnavitempanel = topnavitem.children(":not(:tabbable):last");
733                    _addUniqueId.call(that, topnavitemlink);
734                    if (topnavitempanel.length) {
735                        _addUniqueId.call(that, topnavitempanel);
736                        topnavitemlink.attr({
737                            // "aria-haspopup": true,
738                            "aria-controls": topnavitempanel.attr("id"),
739                            "aria-expanded": false
740                        });
741
742                        topnavitempanel.attr({
743                            "role": "region",
744                            "aria-expanded": false,
745                            "aria-hidden": true
746                        })
747                            .addClass(settings.panelClass)
748                            .not("[aria-labelledby]")
749                            .attr("aria-labelledby", topnavitemlink.attr("id"));
750                    }
751                });
752
753                this.panels = menu.find("." + settings.panelClass);
754
755                menu.on("focusin.accessible-megamenu", ":focusable, ." + settings.panelClass, $.proxy(_focusInHandler, this))
756                    .on("focusout.accessible-megamenu", ":focusable, ." + settings.panelClass, $.proxy(_focusOutHandler, this))
757                    .on("keydown.accessible-megamenu", $.proxy(_keyDownHandler, this))
758                    .on("mouseover.accessible-megamenu", $.proxy(_mouseOverHandler, this))
759                    .on("mouseout.accessible-megamenu", $.proxy(_mouseOutHandler, this))
760                    .on("mousedown.accessible-megamenu", $.proxy(_mouseDownHandler, this));
761
762                if (isTouch) {
763                    menu.on("touchstart.accessible-megamenu",  $.proxy(_clickHandler, this));
764                }
765
766                menu.find("hr").attr("role", "separator");
767
768                if ($(document.activeElement).closest(menu).length) {
769                    $(document.activeElement).trigger("focusin.accessible-megamenu");
770                }
771            },
772
773            /**
774             * @desc Get default values
775             * @example $(selector).accessibleMegaMenu("getDefaults");
776             * @return {object}
777             * @memberof jQuery.fn.accessibleMegaMenu
778             * @instance
779             */
780            getDefaults: function () {
781                return this._defaults;
782            },
783
784            /**
785             * @desc Get any option set to plugin using its name (as string)
786             * @example $(selector).accessibleMegaMenu("getOption", some_option);
787             * @param {string} opt
788             * @return {string}
789             * @memberof jQuery.fn.accessibleMegaMenu
790             * @instance
791             */
792            getOption: function (opt) {
793                return this.settings[opt];
794            },
795
796            /**
797             * @desc Get all options
798             * @example $(selector).accessibleMegaMenu("getAllOptions");
799             * @return {object}
800             * @memberof jQuery.fn.accessibleMegaMenu
801             * @instance
802             */
803            getAllOptions: function () {
804                return this.settings;
805            },
806
807            /**
808             * @desc Set option
809             * @example $(selector).accessibleMegaMenu("setOption", "option_name",  "option_value",  reinitialize);
810             * @param {string} opt - Option name
811             * @param {string} val - Option value
812             * @param {boolean} [reinitialize] - boolean to re-initialize the menu.
813             * @memberof jQuery.fn.accessibleMegaMenu
814             * @instance
815             */
816            setOption: function (opt, value, reinitialize) {
817                this.settings[opt] = value;
818                if (reinitialize) {
819                    this.init();
820                }
821            }
822        };
823    }());
824
825    /* lightweight plugin wrapper around the constructor,
826       to prevent against multiple instantiations */
827
828    /**
829     * @class accessibleMegaMenu
830     * @memberOf jQuery.fn
831     * @classdesc Implements an accessible mega menu as a jQuery plugin.
832     * <p>The mega-menu It is modeled after the mega menu on {@link http://adobe.com|adobe.com} but has been simplified for use by others. A brief description of the interaction design choices can be found in a blog post at {@link http://blogs.adobe.com/accessibility/2013/05/adobe-com.html|Mega menu accessibility on adobe.com}.</p>
833     * <h3>Keyboard Accessibility</h3>
834     * <p>The accessible mega menu supports keyboard interaction modeled after the behavior described in the {@link http://www.w3.org/TR/wai-aria-practices/#menu|WAI-ARIA Menu or Menu bar (widget) design pattern}, however we also try to respect users' general expectations for the behavior of links in a global navigation. To this end, the accessible mega menu implementation permits tab focus on each of the six top-level menu items. When one of the menu items has focus, pressing the Enter key, Spacebar or Down arrow will open the submenu panel, and pressing the Left or Right arrow key will shift focus to the adjacent menu item. Links within the submenu panels are included in the tab order when the panel is open. They can also be navigated with the arrow keys or by typing the first character in the link name, which speeds up keyboard navigation considerably. Pressing the Escape key closes the submenu and restores focus to the parent menu item.</p>
835     * <h3>Screen Reader Accessibility</h3>
836     * <p>The accessible mega menu models its use of WAI-ARIA Roles, States, and Properties after those described 
836in the {@link http://www.w3.org/TR/wai-aria-practices/#menu|WAI-ARIA Menu or Menu bar (widget) design pattern} with some notable exceptions, so that it behaves better with screen reader user expectations for global navigation. We don't use <code class="prettyprint prettyprinted" style=""><span class="pln">role</span><span class="pun">=</span><span class="str">"menu"</span></code> for the menu container and <code class="prettyprint prettyprinted" style=""><span class="pln">role</span><span class="pun">=</span><span class="str">"menuitem"</span></code> for each of the links therein, because if we do, assistive technology will no longer interpret the links as links, but instead, as menu items, and the links in our global navigation will no longer show up when a screen reader user executes a shortcut command to bring up a list of links in the page.</p>
837     * @example <h4>HTML</h4><hr/>
838     &lt;nav&gt;
839     &lt;ul class=&quot;nav-menu&quot;&gt;
840     &lt;li class=&quot;nav-item&quot;&gt;
841     &lt;a href=&quot;?movie&quot;&gt;Movies&lt;/a&gt;
842     &lt;div class=&quot;sub-nav&quot;&gt;
843     &lt;ul class=&quot;sub-nav-group&quot;&gt;
844     &lt;li&gt;&lt;a href=&quot;?movie&amp;genre=0&quot;&gt;Action &amp;amp; Adventure&lt;/a&gt;&lt;/li&gt;
845     &lt;li&gt;&lt;a href=&quot;?movie&amp;genre=2&quot;&gt;Children &amp;amp; Family&lt;/a&gt;&lt;/li&gt;
846     &lt;li&gt;&amp;#8230;&lt;/li&gt;
847     &lt;/ul&gt;
848     &lt;ul class=&quot;sub-nav-group&quot;&gt;
849     &lt;li&gt;&lt;a href=&quot;?movie&amp;genre=7&quot;&gt;Dramas&lt;/a&gt;&lt;/li&gt;
850     &lt;li&gt;&lt;a href=&quot;?movie&amp;genre=9&quot;&gt;Foreign&lt;/a&gt;&lt;/li&gt;
851     &lt;li&gt;&amp;#8230;&lt;/li&gt;
852     &lt;/ul&gt;
853     &lt;ul class=&quot;sub-nav-group&quot;&gt;
854     &lt;li&gt;&lt;a href=&quot;?movie&amp;genre=14&quot;&gt;Musicals&lt;/a&gt;&lt;/li&gt;
855     &lt;li&gt;&lt;a href=&quot;?movie&amp;genre=15&quot;&gt;Romance&lt;/a&gt;&lt;/li&gt;
856     &lt;li&gt;&amp;#8230;&lt;/li&gt;
857     &lt;/ul&gt;
858     &lt;/div&gt;
859     &lt;/li&gt;
860     &lt;li class=&quot;nav-item&quot;&gt;
861     &lt;a href=&quot;?tv&quot;&gt;TV Shows&lt;/a&gt;
862     &lt;div class=&quot;sub-nav&quot;&gt;
863     &lt;ul class=&quot;sub-nav-group&quot;&gt;
864     &lt;li&gt;&lt;a href=&quot;?tv&amp;genre=20&quot;&gt;Classic TV&lt;/a&gt;&lt;/li&gt;
865     &lt;li&gt;&lt;a href=&quot;?tv&amp;genre=21&quot;&gt;Crime TV&lt;/a&gt;&lt;/li&gt;
866     &lt;li&gt;&amp;#8230;&lt;/li&gt;
867     &lt;/ul&gt;
868     &lt;ul class=&quot;sub-nav-group&quot;&gt;
869     &lt;li&gt;&lt;a href=&quot;?tv&amp;genre=27&quot;&gt;Reality TV&lt;/a&gt;&lt;/li&gt;
870     &lt;li&gt;&lt;a href=&quot;?tv&amp;genre=30&quot;&gt;TV Action&lt;/a&gt;&lt;/li&gt;
871     &lt;li&gt;&amp;#8230;&lt;/li&gt;
872     &lt;/ul&gt;
873     &lt;ul class=&quot;sub-nav-group&quot;&gt;
874     &lt;li&gt;&lt;a href=&quot;?tv&amp;genre=33&quot;&gt;TV Dramas&lt;/a&gt;&lt;/li&gt;
875     &lt;li&gt;&lt;a href=&quot;?tv&amp;genre=34&quot;&gt;TV Horror&lt;/a&gt;&lt;/li&gt;
876     &lt;li&gt;&amp;#8230;&lt;/li&gt;
877     &lt;/ul&gt;
878     &lt;/div&gt;
879     &lt;/li&gt;
880     &lt;/ul&gt;
881     &lt;/nav&gt;
882     * @example <h4>CSS</h4><hr/>
883     &#47;* Rudimentary mega menu CSS for demonstration *&#47;
884
885     &#47;* mega menu list *&#47;
886     .nav-menu {
887    display: block;
888    position: relative;
889    list-style: none;
890    margin: 0;
891    padding: 0;
892    z-index: 15;
893}
894
895     &#47;* a top level navigation item in the mega menu *&#47;
896     .nav-item {
897    list-style: none;
898    display: inline-block;
899    padding: 0;
900    margin: 0;
901}
902
903     &#47;* first descendant link within a top level navigation item *&#47;
904     .nav-item &gt; a {
905    position: relative;
906    display: inline-block;
907    padding: 0.5em 1em;
908    margin: 0 0 -1px 0;
909    border: 1px solid transparent;
910}
911
912     &#47;* focus/open states of first descendant link within a top level
913     navigation item *&#47;
914     .nav-item &gt; a:focus,
915     .nav-item &gt; a.open {
916    border: 1px solid #dedede;
917}
918
919     &#47;* open state of first descendant link within a top level
920     navigation item *&#47;
921     .nav-item &gt; a.open {
922    background-color: #fff;
923    border-bottom: none;
924    z-index: 1;
925}
926
927     &#47;* sub-navigation panel *&#47;
928     .sub-nav {
929    position: absolute;
930    display: none;
931    top: 2.2em;
932    margin-top: -1px;
933    padding: 0.5em 1em;
934    border: 1px solid #dedede;
935    background-color: #fff;
936}
937
938     &#47;* sub-navigation panel open state *&#47;
939     .sub-nav.open {
940    display: block;
941}
942
943     &#47;* list of items within sub-navigation panel *&#47;
944     .sub-nav ul {
945    display: inline-block;
946    vertical-align: top;
947    margin: 0 1em 0 0;
948    padding: 0;
949}
950
951     &#47;* list item within sub-navigation panel *&#47;
952     .sub-nav li {
953    display: block;
954    list-style-type: none;
955    margin: 0;
956    padding: 0;
957}
958     * @example <h4>JavaScript</h4><hr/>
959     &lt;!-- include jquery --&gt;
960     &lt;script src=&quot;http://code.jquery.com/jquery-1.10.1.min.js&quot;&gt;&lt;/script&gt;
961
962     &lt;!-- include the jquery-accessibleMegaMenu plugin script --&gt;
963     &lt;script src=&quot;js/jquery-accessibleMegaMenu.js&quot;&gt;&lt;/script&gt;
964
965     &lt;!-- initialize a selector as an accessibleMegaMenu --&gt;
966     &lt;script&gt;
967     $(&quot;nav:first&quot;).accessibleMegaMenu({
968        &#47;* prefix for generated unique id attributes, which are required to indicate aria-owns, aria-controls and aria-labelledby *&#47;
969        uuidPrefix: &quot;accessible-megamenu&quot;,
970
971        &#47;* css class used to define the megamenu styling *&#47;
972        menuClass: &quot;nav-menu&quot;,
973
974        &#47;* css class for a top-level navigation item in the megamenu *&#47;
975        topNavItemClass: &quot;nav-item&quot;,
976
977        &#47;* css class for a megamenu panel *&#47;
978        panelClass: &quot;sub-nav&quot;,
979
980        &#47;* css class for a group of items within a megamenu panel *&#47;
981        panelGroupClass: &quot;sub-nav-group&quot;,
982
983        &#47;* css class for the hover state *&#47;
984        hoverClass: &quot;hover&quot;,
985
986        &#47;* css class for the focus state *&#47;
987        focusClass: &quot;focus&quot;,
988
989        &#47;* css class for the open state *&#47;
990        openClass: &quot;open&quot;
991    });
992     &lt;/script&gt;
993     * @param {object} [options] Mega Menu options
994     * @param {string} [options.uuidPrefix=accessible-megamenu] - Prefix for generated unique id attributes, which are required to indicate aria-owns, aria-controls and aria-labelledby
995     * @param {string} [options.menuClass=accessible-megamenu] - CSS class used to define the megamenu styling
996     * @param {string} [options.topNavItemClass=accessible-megamenu-top-nav-item] - CSS class for a top-level navigation item in the megamenu
997     * @param {string} [options.panelClass=accessible-megamenu-panel] - CSS class for a megamenu panel
998     * @param {string} [options.panelGroupClass=accessible-megamenu-panel-group] - CSS class for a group of items within a megamenu panel
999     * @param {string} [options.hoverClass=hover] - CSS class for the hover state
1000     * @param {string} [options.focusClass=focus] - CSS class for the focus state
1001     * @param {string} [options.openClass=open] - CSS class for the open state
1002     * @param {string} [options.openDelay=0] - Open delay when opening menu via mouseover
1003     * @param {string} [options.closeDelay=250] - Open delay when opening menu via mouseover
1004     */
1005    $.fn[pluginName] = function (options) {
1006        return this.each(function () {
1007            if (!$.data(this, "plugin_" + pluginName)) {
1008                $.data(this, "plugin_" + pluginName, new $.fn[pluginName].Acce
1008ssibleMegaMenu(this, options));
1009            }
1010        });
1011    };
1012
1013    $.fn[pluginName].AccessibleMegaMenu = AccessibleMegaMenu;
1014
1015    /* :focusable and :tabbable selectors from
1016       https://raw.github.com/jquery/jquery-ui/master/ui/jquery.ui.core.js */
1017
1018    /**
1019     * @private
1020     */
1021    function visible(element) {
1022        return $.expr.filters.visible(element) && !$(element).parents().addBack().filter(function () {
1023            return $.css(this, "visibility") === "hidden";
1024        }).length;
1025    }
1026
1027    /**
1028     * @private
1029     */
1030    function focusable(element, isTabIndexNotNaN) {
1031        var map, mapName, img,
1032            nodeName = element.nodeName.toLowerCase();
1033        if ("area" === nodeName) {
1034            map = element.parentNode;
1035            mapName = map.name;
1036            if (!element.href || !mapName || map.nodeName.toLowerCase() !== "map") {
1037                return false;
1038            }
1039            img = $("img[usemap=#" + mapName + "]")[0];
1040            return !!img && visible(img);
1041        }
1042        return (/input|select|textarea|button|object/.test(nodeName) ? !element.disabled :
1043            "a" === nodeName ?
1044                element.href || isTabIndexNotNaN :
1045                isTabIndexNotNaN) &&
1046            // the element and all of its ancestors must be visible
1047            visible(element);
1048    }
1049
1050    $.extend($.expr[":"], {
1051        data: $.expr.createPseudo ? $.expr.createPseudo(function (dataName) {
1052                return function (elem) {
1053                    return !!$.data(elem, dataName);
1054                };
1055            }) : // support: jQuery <1.8
1056            function (elem, i, match) {
1057                return !!$.data(elem, match[3]);
1058            },
1059
1060        focusable: function (element) {
1061            return focusable(element, !isNaN($.attr(element, "tabindex")));
1062        },
1063
1064        tabbable: function (element) {
1065            var tabIndex = $.attr(element, "tabindex"),
1066                isTabIndexNaN = isNaN(tabIndex);
1067            return (isTabIndexNaN || tabIndex >= 0) && focusable(element, !isTabIndexNaN);
1068        }
1069    });
1070}(jQuery, window, document));

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.