PageSourceSearch

https://blowingrockcountryclub.com/CMSScripts/Custom/jquery_smartmenus.js?639245304013216275

js blowingrockcountryclub.com collected 2026-09-26 07:58:44 UTC 61,217 bytes, 1,219 lines download raw bytes

1/*
2 * SmartMenus jQuery v1.0.0
3 * http://www.smartmenus.org/
4 *
5 * Copyright Vasil Dinkov, Vadikom Web Ltd.
6 * http://vadikom.com/
7 *
8 * Released under the MIT license:
9 * http://www.opensource.org/licenses/MIT
10 */
11
12! function (jQuery) {
13
14    var menuTrees = [],
15		IE = !!window.createPopup, // detect it for the iframe shim
16		mouse = false, // optimize for touch by default - we will detect for mouse input
17		touchEvents = 'ontouchstart' in window, // we use this just to choose between toucn and pointer events, not for touch screen detection
18		mouseDetectionEnabled = false,
19		requestAnimationFrame = window.requestAnimationFrame || function (callback) { return setTimeout(callback, 1000 / 60); },
20		cancelAnimationFrame = window.cancelAnimationFrame || function (id) { clearTimeout(id); };
21
22    // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
23    function initMouseDetection(disable) {
24        var eNS = '.smartmenus_mouse';
25        if (!mouseDetectionEnabled && !disable) {
26            // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
27            // in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events)
28            var firstTime = true,
29				lastMove = null;
30            jQuery(document).bind(getEventsNS([
31				['mousemove', function (e) {
32				    var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
33				    if (lastMove) {
34				        var deltaX = Math.abs(lastMove.x - thisMove.x),
35							deltaY = Math.abs(lastMove.y - thisMove.y);
36				        if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
37				            mouse = true;
38				            // if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes
39				            if (firstTime) {
40				                var $a = jQuery(e.target).closest('a');
41				                if ($a.is('a')) {
42				                    jQuery.each(menuTrees, function () {
43				                        if (jQuery.contains(this.$root[0], $a[0])) {
44				                            this.itemEnter({ currentTarget: $a[0] });
45				                            return false;
46				                        }
47				                    });
48				                }
49				                firstTime = false;
50				            }
51				        }
52				    }
53				    lastMove = thisMove;
54				}],
55				[touchEvents ? 'touchstart' : 'pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut', function (e) {
56				    if (isTouchEvent(e.originalEvent)) {
57				        mouse = false;
58				    }
59				}]
60            ], eNS));
61            mouseDetectionEnabled = true;
62        } else if (mouseDetectionEnabled && disable) {
63            jQuery(document).unbind(eNS);
64            mouseDetectionEnabled = false;
65        }
66    }
67
68    function isTouchEvent(e) {
69        return !/^(4|mouse)$/.test(e.pointerType);
70    }
71
72    // returns a jQuery bind() ready object
73    function getEventsNS(defArr, eNS) {
74        if (!eNS) {
75            eNS = '';
76        }
77        var obj = {};
78        jQuery.each(defArr, function (index, value) {
79            obj[value[0].split(' ').join(eNS + ' ') + eNS] = value[1];
80        });
81        return obj;
82    }
83
84    jQuery.SmartMenus = function (elm, options) {
85        this.$root = jQuery(elm);
86        this.opts = options;
87        this.rootId = ''; // internal
88        this.accessIdPrefix = '';
89        this.$subArrow = null;
90        this.activatedItems = []; // stores last activated A's for each level
91        this.visibleSubMenus = []; // stores visible sub menus UL's (might be in no particular order)
92        this.showTimeout = 0;
93        this.hideTimeout = 0;
94        this.scrollTimeout = 0;
95        this.clickActivated = false;
96        this.focusActivated = true;
97        this.zIndexInc = 0;
98        this.idInc = 0;
99        this.$firstLink = null; // we'll use these for some tests
100        this.$firstSub = null; // at runtime so we'll cache them
101        this.disabled = false;
102        this.$disableOverlay = null;
103        this.$touchScrollingSub = null;
104        this.cssTransforms3d = 'perspective' in elm.style || 'webkitPerspective' in elm.style;
105        this.wasCollapsible = false;
106        this.init();
107    };
108
109    jQuery.extend(jQuery.SmartMenus, {
110        hideAll: function () {
111            jQuery.each(menuTrees, function () {
112                this.menuHideAll();
113            });
114        },
115        destroy: function () {
116            while (menuTrees.length) {
117                menuTrees[0].destroy();
118            }
119            initMouseDetection(true);
120        },
121        prototype: {
122            init: function (refresh) {
123                var self = this;
124
125                if (!refresh) {
126                    menuTrees.push(this);
127
128                    this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
129                    this.accessIdPrefix = 'sm-' + this.rootId + '-';
130
131                    if (this.$root.hasClass('sm-rtl')) {
132                        this.opts.rightToLeftSubMenus = true;
133                    }
134
135                    // init root (main menu)
136                    var eNS = '.smartmenus';
137                    this.$root
138						.data('smartmenus', this)
139						.attr('data-smartmenus-id', this.rootId)
140						.dataSM('level', 1)
141						.bind(getEventsNS([
142							['mouseover focusin', jQuery.proxy(this.rootOver, this)],
143							['mouseout focusout', jQuery.proxy(this.rootOut, this)],
144							['keydown', jQuery.proxy(this.rootKeyDown, this)]
145						], eNS))
146						.delegate('a', getEventsNS([
147							['mouseenter', jQuery.proxy(this.itemEnter, this)],
148							['mouseleave', jQuery.proxy(this.itemLeave, this)],
149							['mousedown', jQuery.proxy(this.itemDown, this)],
150							['focus', jQuery.proxy(this.itemFocus, this)],
151							['blur', jQuery.proxy(this.itemBlur, this)],
152							['click', jQuery.proxy(this.itemClick, this)]
153						], eNS));
154
155                    // hide menus on tap or click outside the root UL
156                    eNS += this.rootId;
157                    if (this.opts.hideOnClick) {
158                        jQuery(document).bind(getEventsNS([
159							['touchstart', jQuery.proxy(this.docTouchStart, this)],
160							['touchmove', jQuery.proxy(this.docTouchMove, this)],
161							['touchend', jQuery.proxy(this.docTouchEnd, this)],
162							// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
163							['click', jQuery.proxy(this.docClick, this)]
164                        ], eNS));
165                    }
166                    // hide sub menus on resize
167                    jQuery(window).bind(getEventsNS([['resize orientationchange', jQuery.proxy(this.winResize, this)]], eNS));
168
169                    if (this.opts.subIndicators) {
170                        this.$subArrow = jQuery('<span/>').addClass('sub-arrow fa fa-angle-down');
171                        if (this.opts.subIndicatorsText) {
172                            this.$subArrow.html(this.opts.subIndicatorsText);
173                        }
174                    }
175
176                    // make sure mouse detection is enabled
177                    initMouseDetection();
178                }
179
180                // init sub menus
181                this.$firstSub = this.$root.find('ul').each(function () { self.menuInit(jQuery(this)); }).eq(0);
182
183                this.$firstLink = this.$root.find('a').eq(0);
184
185                // find current item
186                if (this.opts.markCurrentItem) {
187                    var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
188						reHash = /#.*/,
189						locHref = window.location.href.replace(reDefaultDoc, ''),
190						locHrefNoHash = locHref.replace(reHash, '');
191                    this.$root.find('a').each(function () {
192                        var href = this.href.replace(reDefaultDoc, ''),
193							$this = jQuery(this);
194                        if (href == locHref || href == locHrefNoHash) {
195                            $this.addClass('current');
196                            if (self.opts.markCurrentTree) {
197                                $this.parentsUntil('[data-smartmenus-id]', 'ul').each(function () {
198                                    jQuery(this).dataSM('parent-a').addClass('current');
199                                });
200                            }
201                        }
202                    });
203                }
204
205                if (window.matchMedia('(max-width: 1025px)').matches) {
206                    this.itemActivate(jQuery('a.current').last());
207                }
208                // save initial state
209                this.wasCollapsible = this.isCollapsible();
210            },
211
212            destroy: function (refresh) {
213                if (!refresh) {
214                    var eNS = '.smartmenus';
215                    this.$root
216						.removeData('smartmenus')
217						.removeAttr('data-smartmenus-id')
218						.removeDataSM('level')
219						.unbind(eNS)
220						.undelegate(eNS);
221                    eNS += this.rootId;
222                    jQuery(document).unbind(eNS);
223                    jQuery(window).unbind(eNS);
224                    if (this.opts.subIndicators) {
225                        this.$subArrow = null;
226                    }
227                }
228                this.menuHideAll();
229                var self = this;
230                this.$root.find('ul').each(function () {
231                    var $this = jQuery(this);
232                    if ($this.dataSM('scroll-arrows')) {
233                        $this.dataSM('scroll-arrows').remove();
234                    }
235                    if ($this.dataSM('shown-before')) {
236                        if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
237                            $this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
238                        }
239                        if ($this.dataSM('scroll-arrows')) {
240                            $this.dataSM('scroll-arrows').remove();
241                        }
242                        $this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
243                    }
244                    if (($this.attr('id') || '').indexOf(self.accessIdPrefix) == 0) {
245                        $this.removeAttr('id');
246                    }
247                })
248					.removeDataSM('in-mega')
249					.removeDataSM('shown-before')
250					.removeDataSM('ie-shim')
251					.removeDataSM('scroll-arrows')
252					.removeDataSM('parent-a')
253					.removeDataSM('level')
254					.removeDataSM('beforefirstshowfired')
255					.removeAttr('role')
256					.removeAttr('aria-hidden')
257					.removeAttr('aria-labelledby')
258					.removeAttr('aria-expanded');
259                this.$root.find('a.has-submenu').each(function () {
260                    var $this = jQuery(this);
261                    if ($this.attr('id').indexOf(self.accessIdPrefix) == 0) {
262                        $this.removeAttr('id');
263                    }
264                })
265					.removeClass('has-submenu')
266					.removeDataSM('sub')
267					.removeAttr('aria-haspopup')
268					.removeAttr('aria-controls')
269					.removeAttr('aria-expanded')
270					.closest('li').removeDataSM('sub');
271                if (this.opts.subIndicators) {
272                    this.$root.find('span.sub-arrow').remove();
273                }
274                if (this.opts.markCurrentItem) {
275                    this.$root.find('a.current').removeClass('current');
276                }
277                if (!refresh) {
278                    this.$root = null;
279                    this.$firstLink = null;
280                    this.$firstSub = null;
281                    if (this.$disableOverlay) {
282                        this.$disableOverlay.remove();
283                        this.$disableOverlay = null;
284                    }
285                    menuTrees.splice(jQuery.inArray(this, menuTrees), 1);
286                }
287            },
288            disable: function (noOverlay) {
289                if (!this.disabled) {
290                    this.menuHideAll();
291                    // display overlay over the menu to prevent interaction
292                    if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
293                        var pos = this.$root.offset();
294                        this.$disableOverlay = jQuery('<div class="sm-jquery-disable-overlay"/>').css({
295                            position: 'absolute',
296                            top: pos.top,
297                            left: pos.left,
298                            width: this.$root.outerWidth(),
299                            height: this.$root.outerHeight(),
300                            zIndex: this.getStartZIndex(true),
301                            opacity: 0
302                        }).appendTo(document.body);
303                    }
304                    this.disabled = true;
305                }
306            },
307            docClick: function (e) {
308                if (this.$touchScrollingSub) {
309                    this.$touchScrollingSub = null;
310                    return;
311                }
312                // hide on any click outside the menu or on a menu link
313                if (this.visibleSubMenus.length && !jQuery.contains(this.$root[0], e.target) || jQuery(e.target).is('a')) {
314                    this.menuHideAll();
315                }
316            },
317            docTouchEnd: function (e) {
318                if (!this.lastTouch) {
319                    return;
320                }
321                if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !jQuery.contains(this.$root[0], this.lastTouch.target))) {
322                    if (this.hideTimeout) {
323                        clearTimeout(this.hideTimeout);
324                        this.hideTimeout = 0;
325                    }
326                    // hide with a delay to prevent triggering accidental unwanted click on some page element
327                    var self = this;
328                    this.hideTimeout = setTimeout(function () { self.menuHideAll(); }, 350);
329                }
330                this.lastTouch = null;
331            },
332            docTouchMove: function (e) {
333                if (!this.lastTouch) {
334                    return;
335                }
336                var touchPoint = e.originalEvent.touches[0];
337                this.lastTouch.x2 = touchPoint.pageX;
338                this.lastTouch.y2 = touchPoint.pageY;
339            },
340            docTouchStart: function (e) {
341                var touchPoint = e.originalEvent.touches[0];
342                this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
343            },
344            enable: function () {
345                if (this.disabled) {
346                    if (this.$disableOverlay) {
347                        this.$disableOverlay.remove();
348                        this.$disableOverlay = null;
349                    }
350                    this.disabled = false;
351                }
352            },
353            getClosestMenu: function (elm) {
354                var $closestMenu = jQuery(elm).closest('ul');
355                while ($closestMenu.dataSM('in-mega')) {
356                    $closestMenu = $closestMenu.parent().closest('ul');
357                }
358                return $closestMenu[0] || null;
359            },
360            getHeight: function ($elm) {
361                return this.getOffset($elm, true);
362            },
363            // returns precise width/height float values
364            getOffset: function ($elm, height) {
365                var old;
366                if ($elm.css('display') == 'none') {
367                    old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
368                    $elm.css({ position: 'absolute', visibility: 'hidden' }).show();
369                }
370                var box = $elm[0].getBoundingClientRect && $elm[0].getBoundingClientRect(),
371					val = box && (height ? box.height || box.bottom - box.top : box.width || box.right - box.left);
372                if (!val && val !== 0) {
373                    val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
374                }
375                if (old) {
376                    $elm.hide().css(old);
377                }
378                return val;
379            },
380            getStartZIndex: function (root) {
381                var zIndex = parseInt(this[root ? '$root' : '$firstSub'].css('z-index'));
382                if (!root && isNaN(zIndex)) {
383                    zIndex = parseInt(this.$root.css('z-index'));
384                }
385                return !isNaN(zIndex) ? zIndex : 1;
386            },
387            getTouchPoint: function (e) {
388                return e.touches && e.touches[0] || e.changedTouches && e.changedTouches[0] || e;
389            },
390            getViewport: function (height) {
391                var name = height ? 'Height' : 'Width',
392					val = document.documentElement['client' + name],
393					val2 = window['inner' + name];
394                if (val2) {
395                    val = Math.min(val, val2);
396                }
397                return val;
398            },
399            getViewportHeight: function () {
400                return this.getViewport(true);
401            },
402            getViewportWidth: function () {
403                return this.getViewport();
404            },
405            getWidth: function ($elm) {
406                return this.getOffset($elm);
407            },
408            handleEvents: function () {
409                return !this.disabled && this.isCSSOn();
410            },
411            handleItemEvents: function ($a) {
412                return this.handleEvents() && !this.isLinkInMegaMenu($a);
413            },
414            isCollapsible: function () {
415                return this.$firstSub.css('position') == 'static';
416            },
417            isCSSOn: function () {
418                return this.$firstLink.css('display') == 'block';
419            },
420            isFixed: function () {
421                var isFixed = this.$root.css('position') == 'fixed';
422                if (!isFixed) {
423                    this.$root.parentsUntil('body').each(function () {
424                        if (jQuery(this).css('position') == 'fixed') {
425                            isFixed = true;
426                            return false;
427                        }
428                    });
429                }
430                return isFixed;
431            },
432            isLinkInMegaMenu: function ($a) {
433                return jQuery(this.getClosestMenu($a[0])).hasClass('mega-menu');
434            },
435            isTouchMode: function () {
436                return !mouse || this.opts.noMouseOver || this.isCollapsible();
437            },
438            itemActivate: function ($a, focus) {
439                var $ul = $a.closest('ul'),
440					level = $ul.dataSM('level');
441                // if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first
442                if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
443                    var self = this;
444                    jQuery($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function () {
445                        self.itemActivate(jQuery(this).dataSM('parent-a'));
446                    });
447                }
448                // hide any visible deeper level sub menus
449                if (!this.isCollapsible() || focus) {
450                    this.menuHideSubMenus(!this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level);
451                }
452                // save new active item for this level
453                this.activatedItems[level - 1] = $a;
454                if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
455                    return;
456                }
457                // show the sub menu if this item has one
458                var $sub = $a.dataSM('sub');
459                if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
460                    this.menuShow($sub);
461                }
462            },
463            itemBlur: function (e) {
464                var $a = jQuery(e.currentTarget);
465                if (!this.handleItemEvents($a)) {
466                    return;
467                }
468                this.$root.triggerHandler('blur.smapi', $a[0]);
469            },
470            itemClick: function (e) {
471                var $a = jQuery(e.currentTarget);
472                if (!this.handleItemEvents($a)) {
473                    return;
474                }
475                if ($a.attr('href') && !jQuery(e.target).is('span.sub-arrow')) {
476                    return; // WEB-315: when link is active and not clicking on arrow, do not open the menu
477                }
478                if (this.$touchScrollingSub && this.$touchScrollingSub[0] == $a.closest('ul')[0]) {
479                    this.$touchScrollingSub = null;
480                    e.stopPropagation();
481                    return false;
482                }
483                if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
484                    return false;
485                }
486                var subArrowClicked = jQuery(e.target).is('span.sub-arrow'),
487					$sub = $a.dataSM('sub'),
488					firstLevelSub = $sub ? $sub.dataSM('level') == 2 : false;
489                // if the sub is not visible
490                if ($sub && !$sub.is(':visible')) {
491                    if (this.opts.showOnClick && firstLevelSub) {
492                        this.clickActivated = true;
493                    }
494                    // try to activate the item and show the sub
495                    this.itemActivate($a);
496                    // if "itemActivate" showed the sub, prevent the click so that the link is not loaded
497                    // if it couldn't show it, then the sub menus are disabled 
497with an !important declaration (e.g. via mobile styles) so let the link get loaded
498                    if ($sub.is(':visible')) {
499                        this.focusActivated = true;
500                        return false;
501                    }
502                } else if ($sub && this.isCollapsible()) { // WEB-315: allow clicking on link to expand menu
503                    this.itemActivate($a);
504                    this.menuHide($sub);
505                    return false;
506                }
507                if (this.opts.showOnClick && firstLevelSub || $a.hasClass('disabled') || this.$root.triggerHandler('select.smapi', $a[0]) === false) {
508                    return false;
509                }
510            },
511            itemDown: function (e) {
512                var $a = jQuery(e.currentTarget);
513                if (!this.handleItemEvents($a)) {
514                    return;
515                }
516                $a.dataSM('mousedown', true);
517            },
518            itemEnter: function (e) {
519                var $a = jQuery(e.currentTarget);
520                if (!this.handleItemEvents($a)) {
521                    return;
522                }
523                if (!this.isTouchMode()) {
524                    if (this.showTimeout) {
525                        clearTimeout(this.showTimeout);
526                        this.showTimeout = 0;
527                    }
528                    var self = this;
529                    this.showTimeout = setTimeout(function () { self.itemActivate($a); }, this.opts.showOnClick && $a.closest('ul').dataSM('level') == 1 ? 1 : this.opts.showTimeout);
530                }
531                this.$root.triggerHandler('mouseenter.smapi', $a[0]);
532            },
533            itemFocus: function (e) {
534                var $a = jQuery(e.currentTarget);
535                if (!this.handleItemEvents($a)) {
536                    return;
537                }
538                // fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus
539                if (this.focusActivated && (!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
540                    this.itemActivate($a, true);
541                }
542                this.$root.triggerHandler('focus.smapi', $a[0]);
543            },
544            itemLeave: function (e) {
545                var $a = jQuery(e.currentTarget);
546                if (!this.handleItemEvents($a)) {
547                    return;
548                }
549                if (!this.isTouchMode()) {
550                    $a[0].blur();
551                    if (this.showTimeout) {
552                        clearTimeout(this.showTimeout);
553                        this.showTimeout = 0;
554                    }
555                }
556                $a.removeDataSM('mousedown');
557                this.$root.triggerHandler('mouseleave.smapi', $a[0]);
558            },
559            menuHide: function ($sub) {
560                if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
561                    return;
562                }
563                $sub.stop(true, true);
564                if ($sub.css('display') != 'none') {
565                    var complete = function () {
566                        // unset z-index
567                        $sub.css('z-index', '');
568                    };
569                    // if sub is collapsible (mobile view)
570                    if (this.isCollapsible()) {
571                        if (this.opts.collapsibleHideFunction) {
572                            this.opts.collapsibleHideFunction.call(this, $sub, complete);
573                        } else {
574                            $sub.hide(this.opts.collapsibleHideDuration, complete);
575                        }
576                    } else {
577                        if (this.opts.hideFunction) {
578                            this.opts.hideFunction.call(this, $sub, complete);
579                        } else {
580                            $sub.hide(this.opts.hideDuration, complete);
581                        }
582                    }
583                    // remove IE iframe shim
584                    if ($sub.dataSM('ie-shim')) {
585                        $sub.dataSM('ie-shim').remove().css({ '-webkit-transform': '', transform: '' });
586                    }
587                    // deactivate scrolling if it is activated for this sub
588                    if ($sub.dataSM('scroll')) {
589                        this.menuScrollStop($sub);
590                        $sub.css({ 'touch-action': '', '-ms-touch-action': '', '-webkit-transform': '', transform: '' })
591							.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
592                    }
593                    // unhighlight parent item + accessibility
594                    $sub.dataSM('parent-a').removeClass('highlighted').attr('aria-expanded', 'false');
595                    $sub.attr({
596                        'aria-expanded': 'false',
597                        'aria-hidden': 'true'
598                    });
599                    var level = $sub.dataSM('level');
600                    this.activatedItems.splice(level - 1, 1);
601                    this.visibleSubMenus.splice(jQuery.inArray($sub, this.visibleSubMenus), 1);
602                    this.$root.triggerHandler('hide.smapi', $sub[0]);
603                }
604            },
605            menuHideAll: function () {
606                if (this.showTimeout) {
607                    clearTimeout(this.showTimeout);
608                    this.showTimeout = 0;
609                }
610                // hide all subs
611                // if it's a popup, this.visibleSubMenus[0] is the root UL
612                var level = this.opts.isPopup ? 1 : 0;
613
614                //AG - sprte-7706 - disabling menu hide when switching away from it
615                if (!window.matchMedia('(max-width: 1025px)').matches) {
616                    for (var i = this.visibleSubMenus.length - 1; i >= level; i--) {
617                        this.menuHide(this.visibleSubMenus[i]);
618                    }
619                }
620
621                // hide root if it's popup
622                if (this.opts.isPopup) {
623                    this.$root.stop(true, true);
624                    if (this.$root.is(':visible')) {
625                        if (this.opts.hideFunction) {
626                            this.opts.hideFunction.call(this, this.$root);
627                        } else {
628                            this.$root.hide(this.opts.hideDuration);
629                        }
630                        // remove IE iframe shim
631                        if (this.$root.dataSM('ie-shim')) {
632                            this.$root.dataSM('ie-shim').remove();
633                        }
634                    }
635                }
636                this.activatedItems = [];
637                this.visibleSubMenus = [];
638                this.clickActivated = false;
639                //this.focusActivated = false;
640                // reset z-index increment
641                this.zIndexInc = 0;
642                this.$root.triggerHandler('hideAll.smapi');
643            },
644            menuHideSubMenus: function (level) {
645                for (var i = this.activatedItems.length - 1; i >= level; i--) {
646                    var $sub = this.activatedItems[i].dataSM('sub');
647                    if ($sub) {
648                        this.menuHide($sub);
649                    }
650                }
651            },
652            menuIframeShim: function ($ul) {
653                // create iframe shim for the menu
654                if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
655                    $ul.dataSM('ie-shim', jQuery('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
656						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
657					);
658                }
659            },
660            menuInit: function ($ul) {
661                if (!$ul.dataSM('in-mega')) {
662                    // mark UL's in mega drop downs (if any) so we can neglect them
663                    if ($ul.hasClass('mega-menu')) {
664                        $ul.find('ul').dataSM('in-mega', true);
665                    }
666                    // get level (much faster than, for example, using parentsUntil)
667                    var level = 2,
668						par = $ul[0];
669                    //ignore empty <ul> elements (no children)
670                    if (!par.firstChild)
671                        return;
672                    while (par != null && (par = par.parentNode.parentNode) != this.$root[0]) {
673                        level++;
674                    }
675                    // cache stuff for quick access
676                    var $a = $ul.prevAll('a').eq(-1);
677                    // if the link is nested (e.g. in a heading)
678                    if (!$a.length) {
679                        $a = $ul.prevAll().find('a').eq(-1);
680                    }
681                    $a.addClass('has-submenu').dataSM('sub', $ul);
682                    $ul.dataSM('parent-a', $a)
683						.dataSM('level', level)
684						.parent().dataSM('sub', $ul);
685                    // accessibility
686                    var aId = $a.attr('id') || this.accessIdPrefix + (++this.idInc),
687						ulId = $ul.attr('id') || this.accessIdPrefix + (++this.idInc);
688                    $a.attr({
689                        id: aId,
690                        'aria-haspopup': 'true',
691                        'aria-controls': ulId,
692                        'aria-expanded': 'false'
693                    });
694                    $ul.attr({
695                        id: ulId,
696                        'role': 'group',
697                        'aria-hidden': 'true',
698                        'aria-labelledby': aId,
699                        'aria-expanded': 'false'
700                    });
701                    // add sub indicator to parent item
702                    if (this.opts.subIndicators) {
703                        $a[this.opts.subIndicatorsPos](this.$subArrow.clone());
704                    }
705                }
706            },
707            menuPosition: function ($sub) {
708                var $a = $sub.dataSM('parent-a'),
709					$li = $a.closest('li'),
710					$ul = $li.parent(),
711					level = $sub.dataSM('level'),
712					subW = this.getWidth($sub),
713					subH = this.getHeight($sub),
714					itemOffset = $a.offset(),
715					itemX = itemOffset.left,
716					itemY = itemOffset.top,
717					itemW = this.getWidth($a),
718					itemH = this.getHeight($a),
719					$win = jQuery(window),
720					winX = $win.scrollLeft(),
721					winY = $win.scrollTop(),
722					winW = this.getViewportWidth(),
723					winH = this.getViewportHeight(),
724					horizontalParent = $ul.parent().is('[data-sm-horizontal-sub]') || level == 2 && !$ul.hasClass('sm-vertical'),
725					rightToLeft = this.opts.rightToLeftSubMenus && !$li.is('[data-sm-reverse]') || !this.opts.rightToLeftSubMenus && $li.is('[data-sm-reverse]'),
726					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
727					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
728					x, y;
729                if (horizontalParent) {
730                    x = rightToLeft ? itemW - subW - subOffsetX : subOffsetX;
731                    y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
732                } else {
733                    x = rightToLeft ? subOffsetX - subW : itemW - subOffsetX;
734                    y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
735                }
736                if (this.opts.keepInViewport) {
737                    var absX = itemX + x,
738						absY = itemY + y;
739                    if (rightToLeft && absX < winX) {
740                        x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
741                    } else if (!rightToLeft && absX + subW > winX + winW) {
742                        x = horizontalParent ? winX + winW - subW - absX + x : subOffsetX - subW;
743                    }
744                    if (!horizontalParent) {
745                        if (subH < winH && absY + subH > winY + winH) {
746                            y += winY + winH - subH - absY;
747                        } else if (subH >= winH || absY < winY) {
748                            y += winY - absY;
749                        }
750                    }
751                    // do we need scrolling?
752                    // 0.49 used for better precision when dealing with float values
753                    if (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49) {
754                        var self = this;
755                        if (!$sub.dataSM('scroll-arrows')) {
756                            $sub.dataSM('scroll-arrows', jQuery([jQuery('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], jQuery('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]])
757								.bind({
758								    mouseenter: function () {
759								        $sub.dataSM('scroll').up = jQuery(this).hasClass('scroll-up');
760								        self.menuScroll($sub);
761								    },
762								    mouseleave: function (e) {
763								        self.menuScrollStop($sub);
764								        self.menuScrollOut($sub, e);
765								    },
766								    'mousewheel DOMMouseScroll': function (e) { e.preventDefault(); }
767								})
768								.insertAfter($sub)
769							);
770                        }
771                        // bind scroll events and save scroll data for this sub
772                        var eNS = '.smartmenus_scroll';
773                        $sub.dataSM('scroll', {
774                            y: this.cssTransforms3d ? 0 : y - itemH,
775                            step: 1,
776                            // cache stuff for faster recalcs later
777                            itemH: itemH,
778                            subH: subH,
779                            arrowDownH: this.getHeight($sub.dataSM('scroll-arrows').eq(1))
780                        })
781							.bind(getEventsNS([
782								['mouseover', function (e) { self.menuScrollOver($sub, e); }],
783								['mouseout', function (e) { self.menuScrollOut($sub, e); }],
784								['mousewheel DOMMouseScroll', function (e) { self.menuScrollMousewheel($sub, e); }]
785							], eNS))
786							.dataSM('scroll-arrows').css({ top: 'auto', left: '0', marginLeft: x + (parseInt($sub.css('border-left-width')) || 0), width: subW - (parseInt($sub.css('border-left-width')) || 0) - (parseInt($sub.css('border-right-width')) || 0), zIndex: $sub.css('z-index') })
787								.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
788                        // when a menu tree is fixed positioned we allow scrolling via touch too
789                        // since there is no other way to access such long sub menus if no mouse is present
790                        if (this.isFixed()) {
791                            $sub.css({ 'touch-action': 'none', '-ms-touch-action': 'none' })
792								.bind(getEventsNS([
793									[touchEvents ? 'touchstart touchmove touchend' : 'pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp', function (e) {
794									    self.menuScrollTouch($sub, e);
795									}]
796								], eNS));
797                        }
798                    }
799                }
800                $sub.css({ top: 'auto', left: '0', marginLeft: x, marginTop: y - itemH });
801                // IE iframe shim
802                this.menuIframeShim($sub);
803                if ($sub.dataSM('ie-shim')) {
804                    $sub.dataSM('ie-shim').css({ zIndex: $sub.css('z-index'), width: subW, height: subH, marginLeft: x, marginTop: y - itemH });
805                }
806            },
807            menuScroll: function ($sub, once, step) {
808                var data = $sub.dataSM('scroll'),
809					$arrows = $sub.dataSM('scroll-arrows'),
810					end = data.up ? data.upEnd : data.downEnd,
811					diff;
812                if (!once && data.momentum) {
813                    data.momentum *= 0.92;
814                    diff = data.momentum;
815                    if (diff < 0.5) {
816                        this.menuScrollStop($sub);
817                        return;
818                    }
819                } else {
820                    diff = step || (once || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor(data.step));
821                }
822                // hide any visible deeper level sub menus
823                var level = $sub.dataSM('level');
824                if (this.activatedItems[level - 1] && this.activatedItems[level - 1].dataSM('sub') && this.activatedItems[level - 1].dataSM('sub').is(':visible')) {
825                    this.menuHideSubMenus(level - 1);
826                }
827                data.y = data.up && end <= data.y || !data.up && end >= data.y ? data.y : (Math.abs(end - data.y) > diff ? data.y + (data.up ? diff : -diff) : end);
828                $sub.add($sub.dataSM('ie-shim')).css(this.cssTransforms3d ? { '-webkit-transform': 'translate3d(0, ' + data.y + 'px, 0)', transform: 'translate3d(0, ' + data.y + 'px, 0)' } : { marginTop: data.y });
829                // show opposite arrow if appropriate
830                if (mouse && (data.up && data.y > data.downEnd || !data.up && data.y < data.upEnd)) {
831                    $arrows.eq(data.up ? 1 : 0).show();
832                }
833                // if we've reached the end
834                if (data.y == end) {
835                    if (mouse) {
836                        $arrows.eq(data.up ? 0 : 1).hide();
837                    }
838                    this.menuScrollStop($sub);
839                } else if (!once) {
840                    if (this.opts.scrollAccelerate && data.step < this.opts.scrollStep) {
841                        data.step += 0.2;
842                    }
843                    var self = this;
844                    this.scrollTimeout = requestAnimationFrame(function () { self.menuScroll($sub); });
845                }
846            },
847            menuScrollMousewheel: function ($sub, e) {
848                if (this.getClosestMenu(e.target) == $sub[0]) {
849                    e = e.originalEvent;
850                    var up = (e.wheelDelta || -e.detail) > 0;
851                    if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
852                        $sub.dataSM('scroll').up = up;
853                        this.menuScroll($sub, true);
854                    }
855                }
856                e.preventDefault();
857            },
858            menuScrollOut: function ($sub, e) {
859                if (mouse) {
860                    if (!/^scroll-(up|down)/.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !jQuery.contains($sub[0], e.relatedTarget) || this.getClosestMenu(e.relatedTarget) != $sub[0])) {
861                        $sub.dataSM('scroll-arrows').css('visibility', 'hidden');
862                    }
863                }
864            },
865            menuScrollOver: function ($sub, e) {
866                if (mouse) {
867                    if (!/^scroll-(up|down)/.test(e.target.className) && this.getClosestMenu(e.target) == $sub[0]) {
868                        this.menuScrollRefreshData($sub);
869                        var data = $sub.dataSM('scroll'),
870							upEnd = jQuery(window).scrollTop() - $sub.dataSM('parent-a').offset().top - data.itemH;
871                        $sub.dataSM('scroll-arrows').eq(0).css('margin-top', upEnd).end()
872							.eq(1).css('margin-top', upEnd + this.getViewportHeight() - data.arrowDownH).end()
873							.css('visibility', 'visible');
874                    }
875                }
876            },
877            menuScrollRefreshData: function ($sub) {
878                var data = $sub.dataSM('scroll'),
879					upEnd = jQuery(window).scrollTop() - $sub.dataSM('parent-a').offset().top - data.itemH;
880                if (this.cssTransforms3d) {
881                    upEnd = -(parseFloat($sub.css('margin-top')) - upEnd);
882                }
883                jQuery.extend(data, {
884                    upEnd: upEnd,
885                    downEnd: upEnd + this.getViewportHeight() - data.subH
886                });
887            },
888            menuScrollStop: function ($sub) {
889                if (this.scrollTimeout) {
890                    cancelAnimationFrame(this.scrollTimeout);
891                    this.scrollTimeout = 0;
892                    $sub.dataSM('scroll').step = 1;
893                    return true;
894                }
895            },
896            menuScrollTouch: function ($sub, e) {
897                e = e.originalEvent;
898                if (isTouchEvent(e)) {
899                    var touchPoint = this.getTouchPoint(e);
900                    // neglect event if we touched a visible deeper level sub menu
901                    if (this.getClosestMenu(touchPoint.target) == $sub[0]) {
902                        var data = $sub.dataSM('scroll');
903                        if (/(start|down)$/i.test(e.type)) {
904                            if (this.menuScrollStop($sub)) {
905                                // if we were scrolling, just stop and don't activate any link on the first touch
906                                e.preventDefault();
907                                this.$touchScrollingSub = $sub;
908                            } else {
909                                this.$touchScrollingSub = null;
910                            }
911                            // update scroll data since the user might have zoomed, etc.
912                            this.menuScrollRefreshData($sub);
913                            // extend it with the touch properties
914                            jQuery.extend(data, {
915                                touchStartY: touchPoint.pageY,
916                                touchStartTime: e.timeStamp
917                            });
918                        } else if (/move$/i.test(e.type)) {
919                            var prevY = data.touchY !== undefined ? data.touchY : data.touchStartY;
920                            if (prevY !== undefined && prevY != touchPoint.pageY) {
921                                this.$touchScrollingSub = $sub;
922                                var up = prevY < touchPoint.pageY;
923                                // changed direction? reset...
924                                if (data.up !== undefined && data.up != up) {
925                                    jQuery.extend(data, {
926                                        touchStartY: touchPoint.pageY,
927                                        touchStartTime: e.timeStamp
928                                    });
929                                }
930                                jQuery.extend(data, {
931                                    up: up,
932                                    touchY: touchPoint.pageY
933                                });
934                                this.menuScroll($sub, true, Math.abs(touchPoint.pageY - prevY));
935                            }
936                            e.preventDefault();
937                        } else { // touchend/pointerup
938                            if (data.touchY !== undefined) {
939                                if (data.momentum = Math.pow(Math.abs(touchPoint.pageY - data.touchStartY) / (e.timeStamp - data.touchStartTime), 2) * 15) {
940                                    this.menuScrollStop($sub);
941                                    this.menuScroll($sub);
942                                    e.preventDefault();
943                                }
944                                delete data.touchY;
945                            }
946                        }
947                    }
948                }
949            },
950            menuShow: function ($sub) {
951                if (!$sub.dataSM('beforefirstshowfired')) {
952                    $sub.dataSM('beforefirstshowfired', true);
953                    if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
954                        return;
955                    }
956                }
957                if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
958                    return;
959                }
960                $sub.dataSM('shown-before', true)
961					.stop(true, true);
962                if (!$sub.is(':visible')) {
963                    // highlight parent item
964                    var $a = $sub.dataSM('parent-a');
965                    if (this.opts.keepHighlighted || this.isCollapsible()) {
966                        $a.addClass('highlighted');
967                    }
968                    if (this.isCollapsible()) {
969                        $sub.removeClass('sm-nowrap').css({ zIndex: '', width: 'auto', minWidth: '', maxWidth: '', top: '', left: '', marginLeft: '', marginTop: '' });
970                    } else {
971                        // set z-index
972                        $sub.css('z-index', this.zIndexInc = (this.zIndexInc || this.get
972StartZIndex()) + 1);
973                        // min/max-width fix - no way to rely purely on CSS as all UL's are nested
974                        if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
975                            $sub.css({ width: 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
976                            if (this.opts.subMenusMinWidth) {
977                                $sub.css('min-width', this.opts.subMenusMinWidth);
978                            }
979                            if (this.opts.subMenusMaxWidth) {
980                                var noMaxWidth = this.getWidth($sub);
981                                $sub.css('max-width', this.opts.subMenusMaxWidth);
982                                if (noMaxWidth > this.getWidth($sub)) {
983                                    $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
984                                }
985                            }
986                        }
987                        this.menuPosition($sub);
988                        // insert IE iframe shim
989                        if ($sub.dataSM('ie-shim')) {
990                            $sub.dataSM('ie-shim').insertBefore($sub);
991                        }
992                    }
993                    var complete = function () {
994                        // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
995                        $sub.css('overflow', '');
996                    };
997                    // if sub is collapsible (mobile view)
998                    if (this.isCollapsible()) {
999                        if (this.opts.collapsibleShowFunction) {
1000                            this.opts.collapsibleShowFunction.call(this, $sub, complete);
1001                        } else {
1002                            $sub.show(this.opts.collapsibleShowDuration, complete);
1003                        }
1004                    } else {
1005                        if (this.opts.showFunction) {
1006                            this.opts.showFunction.call(this, $sub, complete);
1007                        } else {
1008                            $sub.show(this.opts.showDuration, complete);
1009                        }
1010                    }
1011                    // accessibility
1012                    $a.attr('aria-expanded', 'true');
1013                    $sub.attr({
1014                        'aria-expanded': 'true',
1015                        'aria-hidden': 'false'
1016                    });
1017                    // store sub menu in visible array
1018                    this.visibleSubMenus.push($sub);
1019                    this.$root.triggerHandler('show.smapi', $sub[0]);
1020                }
1021            },
1022            popupHide: function (noHideTimeout) {
1023                if (this.hideTimeout) {
1024                    clearTimeout(this.hideTimeout);
1025                    this.hideTimeout = 0;
1026                }
1027                var self = this;
1028                this.hideTimeout = setTimeout(function () {
1029                    self.menuHideAll();
1030                }, noHideTimeout ? 1 : this.opts.hideTimeout);
1031            },
1032            popupShow: function (left, top) {
1033                if (!this.opts.isPopup) {
1034                    alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
1035                    return;
1036                }
1037                if (this.hideTimeout) {
1038                    clearTimeout(this.hideTimeout);
1039                    this.hideTimeout = 0;
1040                }
1041                this.$root.dataSM('shown-before', true)
1042					.stop(true, true);
1043                if (!this.$root.is(':visible')) {
1044                    this.$root.css({ left: left, top: top });
1045                    // IE iframe shim
1046                    this.menuIframeShim(this.$root);
1047                    if (this.$root.dataSM('ie-shim')) {
1048                        this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
1048: left, top: top }).insertBefore(this.$root);
1049                    }
1050                    // show menu
1051                    var self = this,
1052						complete = function () {
1053						    self.$root.css('overflow', '');
1054						};
1055                    if (this.opts.showFunction) {
1056                        this.opts.showFunction.call(this, this.$root, complete);
1057                    } else {
1058                        this.$root.show(this.opts.showDuration, complete);
1059                    }
1060                    this.visibleSubMenus[0] = this.$root;
1061                }
1062            },
1063            refresh: function () {
1064                this.destroy(true);
1065                this.init(true);
1066            },
1067            rootKeyDown: function (e) {
1068                if (!this.handleEvents()) {
1069                    return;
1070                }
1071                switch (e.keyCode) {
1072                    case 27: // reset on Esc
1073                        var $activeTopItem = this.activatedItems[0];
1074                        if ($activeTopItem) {
1075                            this.menuHideAll();
1076                            $activeTopItem[0].focus();
1077                            var $sub = $activeTopItem.dataSM('sub');
1078                            if ($sub) {
1079                                this.menuHide($sub);
1080                            }
1081                        }
1082                        break;
1083                    case 32: // activate item's sub on Space
1084                        var $target = jQuery(e.target);
1085                        if ($target.is('a') && this.handleItemEvents($target)) {
1086                            var $sub = $target.dataSM('sub');
1087                            if ($sub && !$sub.is(':visible')) {
1088                                this.itemClick({ currentTarget: e.target });
1089                                e.preventDefault();
1090                            }
1091                        }
1092                        break;
1093                }
1094            },
1095            rootOut: function (e) {
1096                if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
1097                    return;
1098                }
1099                if (this.hideTimeout) {
1100                    clearTimeout(this.hideTimeout);
1101                    this.hideTimeout = 0;
1102                }
1103                if (!this.opts.showOnClick || !this.opts.hideOnClick) {
1104                    var self = this;
1105                    this.hideTimeout = setTimeout(function () { self.menuHideAll(); }, this.opts.hideTimeout);
1106                }
1107            },
1108            rootOver: function (e) {
1109                if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
1110                    return;
1111                }
1112                if (this.hideTimeout) {
1113                    clearTimeout(this.hideTimeout);
1114                    this.hideTimeout = 0;
1115                }
1116            },
1117            winResize: function (e) {
1118                if (!this.handleEvents()) {
1119                    // we still need to resize the disable overlay if it's visible
1120                    if (this.$disableOverlay) {
1121                        var pos = this.$root.offset();
1122                        this.$disableOverlay.css({
1123                            top: pos.top,
1124                            left: pos.left,
1125                            width: this.$root.outerWidth(),
1126                            height: this.$root.outerHeight()
1127                        });
1128                    }
1129                    return;
1130                }
1131                // hide sub menus on resize - on mobile do it only on orientation change
1132                if (!('onorientationchange' in window) || e.type == 'orientationchange') {
1133                    var isCollapsible = this.isCollapsible();
1134                    // if it was collapsible before resize and still is, don't do it
1135                    if (!(this.wasCollapsible && isCollapsible)) {
1136                        if (this.activatedItems.length) {
1137                            this.activatedItems[this.activatedItems.length - 1][0].blur();
1138                        }
1139                        this.menuHideAll();
1140                    }
1141                    this.wasCollapsible = isCollapsible;
1142                }
1143            }
1144        }
1145    });
1146
1147    jQuery.fn.dataSM = function (key, val) {
1148        if (val) {
1149            return this.data(key + '_smartmenus', val);
1150        }
1151        return this.data(key + '_smartmenus');
1152    }
1153
1154    jQuery.fn.removeDataSM = function (key) {
1155        return this.removeData(key + '_smartmenus');
1156    }
1157
1158    jQuery.fn.smartmenus = function (options) {
1159        if (typeof options == 'string') {
1160            var args = arguments,
1161				method = options;
1162            Array.prototype.shift.call(args);
1163            return this.each(function () {
1164                var smartmenus = jQuery(this).data('smartmenus');
1165                if (smartmenus && smartmenus[method]) {
1166                    smartmenus[method].apply(smartmenus, args);
1167                }
1168            });
1169        }
1170        var opts = jQuery.extend({}, jQuery.fn.smartmenus.defaults, options);
1171        return this.each(function () {
1172            new jQuery.SmartMenus(this, opts);
1173        });
1174    }
1175
1176    // default settings
1177    jQuery.fn.smartmenus.defaults = {
1178        isPopup: false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
1179        mainMenuSubOffsetX: 0,		// pixels offset from default position
1180        mainMenuSubOffsetY: 0,		// pixels offset from default position
1181        subMenusSubOffsetX: 0,		// pixels offset from default position
1182        subMenusSubOffsetY: 0,		// pixels offset from default position
1183        subMenusMinWidth: '10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
1184        subMenusMaxWidth: '20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
1185        subIndicators: true,		// create sub menu indicators - creates a SPAN and inserts it in the A
1186        subIndicatorsPos: 'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
1187        subIndicatorsText: '',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
1188        scrollStep: 30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
1189        scrollAccelerate: true,		// accelerate scrolling or use a fixed step
1190        showTimeout: 250,		// timeout before showing the sub menus
1191        hideTimeout: 500,		// timeout before hiding the sub menus
1192        showDuration: 0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
1193        showFunction: null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
1194        // don't forget to call complete() at the end of whatever you do
1195        // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
1196        hideDuration: 0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
1197        hideFunction: function ($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
1198        // don't forget to call complete() at the end of whatever you do
1199        // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
1200        collapsibleShowDuration: 0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
1201        collapsibleShowFunction: function ($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
1202        // (i.e. when mobile styles are used to make the sub menus collapsible)
1203        collapsibleHideDuration: 0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
1204        collapsibleHideFunction: function ($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
1205        // (i.e. when mobile styles are used to make the sub menus collapsible)
1206        showOnClick: false,		// show the first-level sub menus onclick instead of onmouseover (i.e. mimic desktop app menus) (matters only for mouse input)
1207        hideOnClick: true,		// hide the sub menus on click/tap anywhere on the page
1208        noMouseOver: false,		// disable sub menus activation onmouseover (i.e. behave like in touch mode - use just mouse clicks) (matters only for mouse input)
1209        keepInViewport: true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
1210        keepHighlighted: true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
1211        markCurrentItem: true,		// automatically add the 'current' class to the A element of the item linking to the current URL
1212        markCurrentTree: true,		// add the 'current' class also to the A elements of all ancestor items of the current item
1213        rightToLeftSubMenus: false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
1214        bottomToTopSubMenus: false,		// bottom to top display of the sub menus
1215        overlapControlsInIE: true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
1216    };
1217
1218    return jQuery;
1219}(jQuery);

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.