PageSourceSearch

https://hpj.com/wp-content/themes/highplainsjourna/js/jquery.main.js?ver=7.1.2

js hpj.com collected 2026-10-02 02:50:29 UTC 36,809 bytes, 1,265 lines download raw bytes

1jQuery(function () {
2	initMobileNav();
3	initTouchNav();
4	initOpenClose();
5	initStickyScrollBlock();
6	initDropDownClasses();
7});
8
9// mobile menu init
10function initMobileNav() {
11	jQuery('body').mobileNav({
12		menuActiveClass: 'nav-active',
13		menuOpener: '.nav-opener'
14	});
15}
16
17// handle dropdowns on mobile devices
18function initTouchNav() {
19	jQuery('#nav').each(function() {
20		new TouchNav({
21			navBlock: this,
22			menuDrop: '.drop'
23		});
24	});
25}
26
27// open-close init
28function initOpenClose() {
29	jQuery('.footer-link-wrap .col').openClose({
30		activeClass: 'active',
31		opener: '.title',
32		slider: '.menu',
33		animSpeed: 400,
34		effect: 'slide'
35	});
36}
37
38// add classes if item has dropdown
39function initDropDownClasses() {
40	jQuery('#nav li').each(function() {
41		var item = jQuery(this);
42		var drop = item.find('.drop');
43		var link = item.find('a').eq(0);
44		if (drop.length) {
45			item.addClass('has-drop-down');
46			if (link.length) link.addClass('has-drop-down-a');
47		}
48	});
49}
50
51// initialize fixed blocks on scroll
52function initStickyScrollBlock() {
53	ResponsiveHelper.addRange({
54		'768..': {
55			on: function() {
56				jQuery('.block-share-link').stickyScrollBlock({
57					setBoxHeight: false,
58					activeClass: 'fixed-position',
59					container: '.content-wrap',
60					positionType: 'fixed',
61					extraTop: function() {
62						var totalHeight = 0;
63						jQuery('0').each(function() {
64							totalHeight += jQuery(this).outerHeight();
65						});
66						return totalHeight;
67					}
68				});
69			},
70			off: function() {
71				jQuery('.block-share-link').stickyScrollBlock('destroy');
72			}
73		}
74	});
75}
76
77/*
78 * jQuery sticky box plugin 
79 */
80;(function($, $win) {
81	'use strict';
82
83	function StickyScrollBlock($stickyBox, options) {
84		this.options = options;
85		this.$stickyBox = $stickyBox;
86		this.init();
87	}
88
89	var StickyScrollBlockPrototype = {
90		init: function() {
91			this.findElements();
92			this.attachEvents();
93			this.makeCallback('onInit');
94		},
95
96		findElements: function() {
97			// find parent container in which will be box move 
98			this.$container = this.$stickyBox.closest(this.options.container);
99			// define box wrap flag
100			this.isWrap = this.options.positionType === 'fixed' && this.options.setBoxHeight;
101			// define box move flag
102			this.moveInContainer = !!this.$container.length;
103			// wrapping box to set place in content
104			if (this.isWrap) {
105				this.$stickyBoxWrap = this.$stickyBox.wrap('<div class="' + this.getWrapClass() + '"/>').parent();
106			}
107			//define block to add active class
108			this.parentForActive = this.getParentForActive();
109			this.isInit = true;
110		},
111
112		attachEvents: function() {
113			var self = this;
114
115			// bind events
116			this.onResize = function() {
117				if (!self.isInit) return;
118				self.resetState();
119				self.recalculateOffsets();
120				self.checkStickyPermission();
121				self.scrollHandler();
122			};
123
124			this.onScroll = function() {
125				self.scrollHandler();
126			};
127
128			// initial handler call
129			this.onResize();
130
131			// handle events
132			$win.on('load resize orientationchange', this.onResize)
133				.on('scroll', this.onScroll);
134		},
135
136		defineExtraTop: function() {
137			// define box's extra top dimension
138			var extraTop;
139
140			if (typeof this.options.extraTop === 'number') {
141				extraTop = this.options.extraTop;
142			} else if (typeof this.options.extraTop === 'function') {
143				extraTop = this.options.extraTop();
144			}
145
146			this.extraTop = this.options.positionType === 'absolute' ?
147				extraTop :
148				Math.min(this.winParams.height - this.data.boxFullHeight, extraTop);
149		},
150
151		checkStickyPermission: function() {
152			// check the permission to set sticky
153			this.isStickyEnabled = this.moveInContainer ?
154				this.data.containerOffsetTop + this.data.containerHeight > this.data.boxFullHeight + this.data.boxOffsetTop + this.options.extraBottom :
155				true;
156		},
157
158		getParentForActive: function() {
159			if (this.isWrap) {
160				return this.$stickyBoxWrap;
161			}
162
163			if (this.$container.length) {
164				return this.$container;
165			}
166
167			return this.$stickyBox;
168		},
169
170		getWrapClass: function() {
171			// get set of container classes
172			try {
173				return this.$stickyBox.attr('class').split(' ').map(function(name) {
174					return 'sticky-wrap-' + name;
175				}).join(' ');
176			} catch (err) {
177				return 'sticky-wrap';
178			}
179		},
180
181		resetState: function() {
182			// reset dimensions and state
183			this.stickyFlag = false;
184			this.$stickyBox.css({
185				'-webkit-transition': '',
186				'-webkit-transform': '',
187				transition: '',
188				transform: '',
189				position: '',
190				width: '',
191				left: '',
192				top: ''
193			}).removeClass(this.options.activeClass);
194
195			if (this.isWrap) {
196				this.$stickyBoxWrap.removeClass(this.options.activeClass).removeAttr('style');
197			}
198
199			if (this.moveInContainer) {
200				this.$container.removeClass(this.options.activeClass);
201			}
202		},
203
204		recalculateOffsets: function() {
205			// define box and container dimensions
206			this.winParams = this.getWindowParams();
207
208			this.data = $.extend(
209				this.getBoxOffsets(),
210				this.getContainerOffsets()
211			);
212
213			this.defineExtraTop();
214		},
215
216		getBoxOffsets: function() {
217			function offetTop(obj){
218				obj.top = 0;
219				return obj
220			}
221			var boxOffset = this.$stickyBox.css('position') ==='fixed' ? offetTop(this.$stickyBox.offset()) : this.$stickyBox.offset();
222			var boxPosition = this.$stickyBox.position();
223
224			return {
225				// sticky box offsets
226				boxOffsetLeft: boxOffset.left,
227				boxOffsetTop: boxOffset.top,
228				// sticky box positions
229				boxTopPosition: boxPosition.top,
230				boxLeftPosition: boxPosition.left,
231				// sticky box width/height
232				boxFullHeight: this.$stickyBox.outerHeight(true),
233				boxHeight: this.$stickyBox.outerHeight(),
234				boxWidth: this.$stickyBox.outerWidth()
235			};
236		},
237
238		getContainerOffsets: function() {
239			var containerOffset = this.moveInContainer ? this.$container.offset() : null;
240
241			return containerOffset ? {
242				// container offsets
243				containerOffsetLeft: containerOffset.left,
244				containerOffsetTop: containerOffset.top,
245				// container height
246				containerHeight: this.$container.outerHeight()
247			} : {};
248		},
249
250		getWindowParams: function() {
251			return {
252				height: window.innerHeight || document.documentElement.clientHeight
253			};
254		},
255
256		makeCallback: function(name) {
257			if (typeof this.options[name] === 'function') {
258				var args = Array.prototype.slice.call(arguments);
259				args.shift();
260				this.options[name].apply(this, args);
261			}
262		},
263
264		destroy: function() {
265			this.isInit = false;
266			// remove event handlers and styles
267			$win.off('load resize orientationchange', this.onResize)
268				.off('scroll', this.onScroll);
269			this.resetState();
270			this.$stickyBox.removeData('StickyScrollBlock');
271			if (this.isWrap) {
272				this.$stickyBox.unwrap();
273			}
274			this.makeCallback('onDestroy');
275		}
276	};
277
278	var stickyMethods = {
279		fixed: {
280			scrollHandler: function() {
281				this.winScrollTop = $win.scrollTop();
282				var isActiveSticky = this.winScrollTop -
283					(this.options.showAfterScrolled ? this.extraTop : 0) -
284					(this.options.showAfterScrolled ? this.data.boxHeight + this.extraTop : 0) >
285					this.data.boxOffsetTop - this.extraTop;
286
287				if (isActiveSticky) {
288					this.isStickyEnabled && this.stickyOn();
289				} else {
290					this.stickyOff();
291				}
292			},
293
294			stickyOn: function() {
295				if (!this.stickyFlag) {
296					this.stickyFlag = true;
297					this.parentForActive.addClass(this.options.activeClass);
298					this.$stickyBox.css({
299						width: this.data.boxWidth,
300						position: this.options.positionType
301					});
302					if (this.isWrap) {
303						this.$stickyBoxWrap.css({
304							height: this.data.boxFullHeight
305						});
306					}
307					this.makeCallback('fixedOn');
308				}
309				this.setDynamicPosition();
310			},
311
312			stickyOff: function() {
313				if (this.stickyFlag) {
314					this.stickyFlag = false;
315					this.resetState();
316					this.makeCallback('fixedOff');
317				}
318			},
319
320			setDynamicPosition: function() {
321				this.$stickyBox.css({
322					top: this.getTopPosition(),
323					left: this.data.boxOffsetLeft - $win.scrollLeft()
324				});
325			},
326
327			getTopPosition: function() {
328				if (this.moveInContainer) {
329					var currScrollTop = this.winScrollTop + this.data.boxHeight + this.options.extraBottom;
330
331					return Math.min(this.extraTop, (this.data.containerHeight + this.data.containerOffsetTop) - currScrollTop);
332				} else {
333					return this.extraTop;
334				}
335			}
336		},
337		absolute: {
338			scrollHandler: function() {
339				this.winScrollTop = $win.scrollTop();
340				var isActiveSticky = this.winScrollTop > this.data.boxOffsetTop - this.extraTop;
341
342				if (isActiveSticky) {
343					this.isStickyEnabled && this.stickyOn();
344				} else {
345					this.stickyOff();
346				}
347			},
348
349			stickyOn: function() {
350				if (!this.stickyFlag) {
351					this.stickyFlag = true;
352					this.parentForActive.addClass(this.options.activeClass);
353					this.$stickyBox.css({
354						width: this.data.boxWidth,
355						transition: 'transform ' + this.options.animSpeed + 's ease',
356						'-webkit-transition': 'transform ' + this.options.animSpeed + 's ease',
357					});
358
359					if (this.isWrap) {
360						this.$stickyBoxWrap.css({
361							height: this.data.boxFullHeight
362						});
363					}
364
365					this.makeCallback('fixedOn');
366				}
367
368				this.clearTimer();
369				this.timer = setTimeout(function() {
370					this.setDynamicPosition();
371				}.bind(this), this.options.animDelay * 1000);
372			},
373
374			stickyOff: function() {
375				if (this.stickyFlag) {
376					this.clearTimer();
377					this.stickyFlag = false;
378
379					this.timer = setTimeout(function() {
380						this.setDynamicPosition();
381						setTimeout(function() {
382							this.resetState();
383						}.bind(this), this.options.animSpeed * 1000);
384					}.bind(this), this.options.animDelay * 1000);
385					this.makeCallback('fixedOff');
386				}
387			},
388
389			clearTimer: function() {
390				clearTimeout(this.timer);
391			},
392
393			setDynamicPosition: function() {
394				var topPosition = Math.max(0, this.getTopPosition());
395
396				this.$stickyBox.css({
397					transform: 'translateY(' + topPosition + 'px)',
398					'-webkit-transform': 'translateY(' + topPosition + 'px)'
399				});
400			},
401
402			getTopPosition: function() {
403				var currTopPosition = this.winScrollTop - this.data.boxOffsetTop + this.extraTop;
404
405				if (this.moveInContainer) {
406					var currScrollTop = this.winScrollTop + this.data.boxHeight + this.options.extraBottom;
407					var diffOffset = Math.abs(Math.min(0, (this.data.containerHeight + this.data.containerOffsetTop) - currScrollTop - this.extraTop));
408
409					return currTopPosition - diffOffset;
410				} else {
411					return currTopPosition;
412				}
413			}
414		}
415	};
416
417	// jQuery plugin interface
418	$.fn.stickyScrollBlock = function(opt) {
419		var args = Array.prototype.slice.call(arguments);
420		var method = args[0];
421
422		var options = $.extend({
423			container: null,
424			positionType: 'fixed', // 'fixed' or 'absolute'
425			activeClass: 'fixed-position',
426			setBoxHeight: true,
427			showAfterScrolled: false,
428			extraTop: 0,
429			extraBottom: 0,
430			animDelay: 0.1,
431			animSpeed: 0.2
432		}, opt);
433
434		return this.each(function() {
435			var $stickyBox = jQuery(this);
436			var instance = $stickyBox.data('StickyScrollBlock');
437
438			if (typeof opt === 'object' || typeof opt === 'undefined') {
439				StickyScrollBlock.prototype = $.extend(stickyMethods[options.positionType], StickyScrollBlockPrototype);
440				$stickyBox.data('StickyScrollBlock', new StickyScrollBlock($stickyBox, options));
441			} else if (typeof method === 'string' && instance) {
442				if (typeof instance[method] === 'function') {
443					args.shift();
444					instance[method].apply(instance, args);
445				}
446			}
447		});
448	};
449
450	// module exports
451	window.StickyScrollBlock = StickyScrollBlock;
452}(jQuery, jQuery(window)));
453
454/*
455 * Responsive Layout helper
456 */
457window.ResponsiveHelper = (function($){
458	// init variables
459	var handlers = [],
460		prevWinWidth,
461		win = $(window),
462		nativeMatchMedia = false;
463
464	// detect match media support
465	if(window.matchMedia) {
466		if(window.Window && window.matchMedia === Window.prototype.matchMedia) {
467			nativeMatchMedia = true;
468		} else if(window.matchMedia.toString().indexOf('native') > -1) {
469			nativeMatchMedia = true;
470		}
471	}
472
473	// prepare resize handler
474	function resizeHandler() {
475		var winWidth = win.width();
476		if(winWidth !== prevWinWidth) {
477			prevWinWidth = winWidth;
478
479			// loop through range groups
480			$.each(handlers, function(index, rangeObject){
481				// disable current active area if needed
482				$.each(rangeObject.data, function(property, item) {
483					if(item.currentActive && !matchRange(item.range[0], item.range[1])) {
484						item.currentActive = false;
485						if(typeof item.disableCallback === 'function') {
486							item.disableCallback();
487						}
488					}
489				});
490
491				// enable areas that match current width
492				$.each(rangeObject.data, function(property, item) {
493					if(!item.currentActive && matchRange(item.range[0], item.range[1])) {
494						// make callback
495						item.currentActive = true;
496						if(typeof item.enableCallback === 'function') {
497							item.enableCallback();
498						}
499					}
500				});
501			});
502		}
503	}
504	win.bind('load resize orientationchange', resizeHandler);
505
506	// test range
507	function matchRange(r1, r2) {
508		var mediaQueryString = '';
509		if(r1 > 0) {
510			mediaQueryString += '(min-width: ' + r1 + 'px)';
511		}
512		if(r2 < Infinity) {
513			mediaQueryString += (mediaQueryString ? ' and ' : '') + '(max-width: ' + r2 + 'px)';
514		}
515		return matchQuery(mediaQueryString, r1, r2);
516	}
517
518	// media query function
519	function matchQuery(query, r1, r2) {
520		if(window.matchMedia && nativeMatchMedia) {
521			return matchMedia(query).matches;
522		} else if(window.styleMedia) {
523			return styleMedia.matchMedium(query);
524		} else if(window.media) {
525			return media.matchMedium(query);
526		} else {
527			return prevWinWidth >= r1 && prevWinWidth <= r2;
528		}
529	}
530
531	// range parser
532	function parseRange(rangeStr) {
533		var rangeData = rangeStr.split('..');
534		var x1 = parseInt(rangeData[0], 10) || -Infinity;
535		var x2 = parseInt(rangeData[1], 10) || Infinity;
536		return [x1, x2].sort(function(a, b){
537			return a - b;
538		});
539	}
540
541	// export public functions
542	return {
543		addRange: function(ranges) {
544			// parse data and add items to collection
545			var result = {data:{}};
546			$.each(ranges, function(property, data){
547				result.data[property] = {
548					range: parseRange(property),
549					enableCallback: data.on,
550					disableCallback: data.off
551				};
552			});
553			handlers.push(result);
554
555			// call resizeHandler to recalculate all events
556			prevWinWidth = null;
557			resizeHandler();
558		}
559	};
560}(jQuery));
561
562/*
563 * Simple Mobile Navigation
564 */
565; (function ($) {
566	function MobileNav(options) {
567		this.options = $.extend({
568			container: null,
569			hideOnClickOutside: false,
570			menuActiveClass: 'nav-active',
571			menuOpener: '.nav-opener',
572			menuDrop: '.nav-drop',
573			toggleEvent: 'click',
574			outsideClickEvent: 'click touchstart pointerdown MSPointerDown'
575		}, options);
576		this.initStructure();
577		this.attachEvents();
578	}
579	MobileNav.prototype = {
580		initStructure: function () {
581			this.page = $('html');
582			this.container = $(this.options.container);
583			this.opener = this.container.find(this.options.menuOpener);
584			this.drop = this.container.find(this.options.menuDrop);
585		},
586		attachEvents: function () {
587			var self = this;
588
589			if (activateResizeHandler) {
590				activateResizeHandler();
591				activateResizeHandler = null;
592			}
593
594			this.outsideClickHandler = function (e) {
595				if (self.isOpened()) {
596					var target = $(e.target);
597					if (!target.closest(self.opener).length && !target.closest(self.drop).length) {
598						self.hide();
599					}
600				}
601			};
602
603			this.openerClickHandler = function (e) {
604				e.preventDefault();
605				self.toggle();
606			};
607
608			this.opener.on(this.options.toggleEvent, this.openerClickHandler);
609		},
610		isOpened: function () {
611			return this.container.hasClass(this.options.menuActiveClass);
612		},
613		show: function () {
614			this.container.addClass(this.options.menuActiveClass);
615			if (this.options.hideOnClickOutside) {
616				this.page.on(this.options.outsideClickEvent, this.outsideClickHandler);
617			}
618		},
619		hide: function () {
620			this.container.removeClass(this.options.menuActiveClass);
621			if (this.options.hideOnClickOutside) {
622				this.page.off(this.options.outsideClickEvent, this.outsideClickHandler);
623			}
624		},
625		toggle: function () {
626			if (this.isOpened()) {
627				this.hide();
628			} else {
629				this.show();
630			}
631		},
632		destroy: function () {
633			this.container.removeClass(this.options.menuActiveClass);
634			this.opener.off(this.options.toggleEvent, this.clickHandler);
635			this.page.off(this.options.outsideClickEvent, this.outsideClickHandler);
636		}
637	};
638
639	var activateResizeHandler = function () {
640		var win = $(window),
641			doc = $('html'),
642			resizeClass = 'resize-active',
643			flag, timer;
644		var removeClassHandler = function () {
645			flag = false;
646			doc.removeClass(resizeClass);
647		};
648		var resizeHandler = function () {
649			if (!flag) {
650				flag = true;
651				doc.addClass(resizeClass);
652			}
653			clearTimeout(timer);
654			timer = setTimeout(removeClassHandler, 500);
655		};
656		win.on('resize orientationchange', resizeHandler);
657	};
658
659	$.fn.mobileNav = function (opt) {
660		var args = Array.prototype.slice.call(arguments);
661		var method = args[0];
662
663		return this.each(function () {
664			var $container = jQuery(this);
665			var instance = $container.data('MobileNav');
666
667			if (typeof opt === 'object' || typeof opt === 'undefined') {
668				$container.data('MobileNav', new MobileNav($.extend({
669					container: this
670				}, opt)));
671			} else if (typeof method === 'string' && instance) {
672				if (typeof instance[method] === 'function') {
673					args.shift();
674					instance[method].apply(instance, args);
675				}
676			}
677		});
678	};
679}(jQuery));
680
681// navigation accesibility module
682function TouchNav(opt) {
683    this.options = {
684        hoverClass: 'hover',
685        menuItems: 'li',
686        menuOpener: 'a',
687        menuDrop: 'ul',
688        navBlock: null,
689        destroy: null
690    };
691    for (var p in opt) {
692        if (opt.hasOwnProperty(p)) {
693            this.options[p] = opt[p];
694        }
695    }
696    // console.log(this)
697    this.init();
698}
699
700
701TouchNav.isActiveOn = function (elem) {
702	return elem && elem.touchNavActive;
703};
704
705
706TouchNav.prototype = {
707    init: function () {
708        if (typeof this.options.navBlock === 'string') {
709            this.menu = document.getElementById(this.options.navBlock);
710        } else if (typeof this.options.navBlock === 'object') {
711            this.menu = this.options.navBlock;
712        }
713        if (this.menu) {
714            this.hanldeEvents();
715        }
716    },
717    hanldeEvents: function () {
718        // attach event handlers
719        var self = this;
720        var touchEvent = (navigator.pointerEnabled && 'pointerdown') || (navigator.msPointerEnabled && 'MSPointerDown') || (this.isTouchDevice && 'touchstart');
721        this.menuItems = lib.queryElementsBySelector(this.options.menuItems, this.menu);
722
723        var initMenuItem = function (item) {
724            var currentDrop = lib.queryElementsBySelector(self.options.menuDrop, item)[0],
725                currentOpener = lib.queryElementsBySelector(self.options.menuOpener, item)[0];
726
727            // only for touch input devices
728            if (currentDrop && currentOpener && (self.isTouchDevice || self.isPointerDevice)) {
729                if (!self.options.destroy) {
730                    lib.event.add(currentOpener, 'click', lib.bind(self.clickHandler, self));
731                    lib.event.add(currentOpener, 'mousedown', lib.bind(self.mousedownHandler, self));
732                    lib.event.add(currentOpener, touchEvent, function (e) {
733                        if (!self.isTouchPointerEvent(e)) {
734                            self.preventCurrentClick = false;
735                            return;
736                        }
737                        self.touchFlag = true;
738                        self.currentItem = item;
739                        self.currentLink = currentOpener;
740                        self.pressHandler.apply(self, arguments);
741                    });
742                } else {
743                    lib.event.remove(currentOpener, 'click');
744                    lib.event.remove(currentOpener, 'mousedown');
745                    lib.event.remove(currentOpener, touchEvent);
746                }
747            }
748            if (!self.options.destroy) {
749                // for desktop computers and touch devices
750                jQuery(item).bind('mouseenter', function () {
751                    if (!self.touchFlag) {
752                        self.currentItem = item;
753                        self.mouseoverHandler();
754                    }
755                });
756                jQuery(item).bind('mouseleave', function () {
757                    if (!self.touchFlag) {
758                        self.currentItem = item;
759                        self.mouseoutHandler();
760                    }
761                });
762                item.touchNavActive = true;
763
764            } else {
765                jQuery(item).unbind('mouseenter');
766                jQuery(item).unbind('mouseleave');
767
768                item.touchNavActive = false;
769
770            }
771
772        };
773
774        // addd handlers for all menu items
775        for (var i = 0; i < this.menuItems.length; i++) {
776            initMenuItem(self.menuItems[i]);
777        }
778
779        // hide dropdowns when clicking outside navigation
780        if (this.isTouchDevice || this.isPointerDevice) {
781            lib.event.add(document.documentElement, 'mousedown', lib.bind(this.clickOutsideHandler, this));
782            lib.event.add(document.documentElement, touchEvent, lib.bind(this.clickOutsideHandler, this));
783        }
784    },
785    mousedownHandler: function (e) {
786        if (this.touchFlag) {
787            e.preventDefault();
788            this.touchFlag = false;
789            this.preventCurrentClick = false;
790        }
791    },
792    mouseoverHandler: function () {
793        lib.addClass(this.currentItem, this.options.hoverClass);
794        /**/
795        // jQuery(this.currentItem).trigger('itemhover');
796        /**/
797    },
798    mouseoutHandler: function () {
799        lib.removeClass(this.currentItem, this.options.hoverClass);
800        /**/
801        // jQuery(this.currentItem).trigger('itemleave');
802        /**/
803    },
804    hideActiveDropdown: function () {
805        for (var i = 0; i < this.menuItems.length; i++) {
806            if (lib.hasClass(this.menuItems[i], this.options.hoverClass)) {
807                lib.removeClass(this.menuItems[i], this.options.hoverClass);
808                /**/
809                // jQuery(this.menuItems[i]).trigger('itemleave');
810                /**/
811            }
812        }
813        this.activeParent = null;
814    },
815    pressHandler: function (e) {
816        // hide previous drop (if active)
817        if (this.currentItem !== this.activeParent) {
818            if (this.activeParent && this.currentItem.parentNode === this.activeParent.parentNode) {
819                lib.removeClass(this.activeParent, this.options.hoverClass);
820            } else if (!this.isParent(this.activeParent, this.currentLink)) {
821                this.hideActiveDropdown();
822            }
823        }
824        // handle current drop
825        this.activeParent = this.currentItem;
826        if (lib.hasClass(this.currentItem, this.options.hoverClass)) {
827            this.preventCurrentClick = false;
828        } else {
829            e.preventDefault();
830            this.preventCurrentClick = true;
831            lib.addClass(this.currentItem, this.options.hoverClass);
832            /**/
833            // jQuery(this.currentItem).trigger('itemhover');
834            /**/
835        }
836    },
837    clickHandler: function (e) {
838        // prevent first click on link
839        if (this.preventCurrentClick) {
840            e.preventDefault();
841        }
842    },
843    clickOutsideHandler: function (event) {
844        var e = event.changedTouches ? event.changedTouches[0] : event;
845        if (this.activeParent && !this.isParent(this.menu, e.target)) {
846            this.hideActiveDropdown();
847            this.touchFlag = false;
848        }
849    },
850    isParent: function (parent, child) {
851        while (child.parentNode) {
852            if (child.parentNode == parent) {
853                return true;
854            }
855            child = child.parentNode;
856        }
857        return false;
858    },
859
860    isTouchPointerEvent: function (e) {
861        return (e.type.indexOf('touch') > -1) ||
862            (navigator.pointerEnabled && e.pointerType === 'touch') ||
863            (navigator.msPointerEnabled && e.pointerType == e.MSPOINTER_TYPE_TOUCH);
864    },
865    isPointerDevice: (function () {
866        return !!(navigator.pointerEnabled || navigator.msPointerEnabled);
867    }()),
868    isTouchDevice: (function () {
869        return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
870    }())
871};
872
873/*
874 * Utility module
875 */
876lib = {
877	hasClass: function(el,cls) {
878		return el && el.className ? el.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')) : false;
879	},
880	addClass: function(el,cls) {
881		if (el && !this.hasClass(el,cls)) el.className += " "+cls;
882	},
883	removeClass: function(el,cls) {
884		if (el && this.hasClass(el,cls)) {el.className=el.className.replace(new RegExp('(\\s|^)'+cls+'(\\s|$)'),' ');}
885	},
886	extend: function(obj) {
887		for(var i = 1; i < arguments.length; i++) {
888			for(var p in arguments[i]) {
889				if(arguments[i].hasOwnProperty(p)) {
890					obj[p] = arguments[i][p];
891				}
892			}
893		}
894		return obj;
895	},
896	each: function(obj, callback) {
897		var property, len;
898		if(typeof obj.length === 'number') {
899			for(property = 0, len = obj.length; property < len; property++) {
900				if(callback.call(obj[property], property, obj[property]) === false) {
901					break;
902				}
903			}
904		} else {
905			for(property in obj) {
906				if(obj.hasOwnProperty(property)) {
907					if(callback.call(obj[property], property, obj[property]) === false) {
908						break;
909					}
910				}
911			}
912		}
913	},
914	event: (function() {
915		var fixEvent = function(e) {
916			e = e || window.event;
917			if(e.isFixed) return e; else e.isFixed = true;
918			if(!e.target) e.target = e.srcElement;
919			e.preventDefault = e.preventDefault || function() {this.returnValue = false;};
920			e.stopPropagation = e.stopPropagation || function() {this.cancelBubble = true;};
921			return e;
922		};
923		return {
924			add: function(elem, event, handler) {
925				if(!elem.events) {
926					elem.events = {};
927					elem.handle = function(e) {
928						var ret, handlers = elem.events[e.type];
929						e = fixEvent(e);
930						for(var i = 0, len = handlers.length; i < len; i++) {
931							if(handlers[i]) {
932								ret = handlers[i].call(elem, e);
933								if(ret === false) {
934									e.preventDefault();
935									e.stopPropagation();
936								}
937							}
938						}
939					};
940				}
941				if(!elem.events[event]) {
942					elem.events[event] = [];
943					if(elem.addEventListener) elem.addEventListener(event, elem.handle, false);
944					else if(elem.attachEvent) elem.attachEvent('on'+event, elem.handle);
945				}
946				elem.events[event].push(handler);
947			},
948			remove: function(elem, event, handler) {
949				var handlers = elem.events[event];
950				for(var i = handlers.length - 1; i >= 0; i--) {
951					if(handlers[i] === handler) {
952						handlers.splice(i,1);
953					}
954				}
955				if(!handlers.length) {
956					delete elem.events[event];
957					if(elem.removeEventListener) elem.removeEventListener(event, elem.handle, false);
958					else if(elem.detachEvent) elem.detachEvent('on'+event, elem.handle);
959				}
960			}
961		};
962	}()),
963	queryElementsBySelector: function(selector, scope) {
964		scope = scope || document;
965		if(!selector) return [];
966		if(selector === '>*') return scope.children;
967		if(typeof document.querySelectorAll === 'function') {
968			return scope.querySelectorAll(selector);
969		}
970		var selectors = selector.split(',');
971		var resultList = [];
972		for(var s = 0; s < selectors.length; s++) {
973			var currentContext = [scope || document];
974			var tokens = selectors[s].replace(/^\s+/,'').replace(/\s+$/,'').split(' ');
975			for (var i = 0; i < tokens.length; i++) {
976				token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');
977				if (token.indexOf('#') > -1) {
978					var bits = token.split('#'), tagName = bits[0], id = bits[1];
979					var element = document.getElementById(id);
980					if (element && tagName && element.nodeName.toLowerCase() != tagName) {
981						return [];
982					}
983					currentContext = element ? [element] : [];
984					continue;
985				}
986				if (token.indexOf('.') > -1) {
987					var bits = token.split('.'), tagName = bits[0] || '*', className = bits[1], found = [], foundCount = 0;
988					for (var h = 0; h < currentContext.length; h++) {
989						var elements;
990						if (tagName == '*') {
991							elements = currentContext[h].getElementsByTagName('*');
992						} else {
993							elements = currentContext[h].getElementsByTagName(tagName);
994						}
995						for (var j = 0; j < elements.length; j++) {
996							found[foundCount++] = elements[j];
997						}
998					}
999					currentContext = [];
1000					var currentContextIndex = 0;
1001					for (var k = 0; k < found.length; k++) {
1002						if (found[k].className && found[k].className.match(new RegExp('(\\s|^)'+className+'(\\s|$)'))) {
1003							currentContext[currentContextIndex++] = found[k];
1004						}
1005					}
1006					continue;
1007				}
1008				if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
1009					var tagName = RegExp.$1 || '*', attrName = RegExp.$2, attrOperator = RegExp.$3, attrValue = RegExp.$4;
1010					if(attrName.toLowerCase() == 'for' && this.browser.msie && this.browser.version < 8) {
1011						attrName = 'htmlFor';
1012					}
1013					var found = [], foundCount = 0;
1014					for (var h = 0; h < currentContext.length; h++) {
1015						var elements;
1016						if (tagName == '*') {
1017							elements = currentContext[h].getElementsByTagName('*');
1018						} else {
1019							elements = currentContext[h].getElementsByTagName(tagName);
1020						}
1021						for (var j = 0; elements[j]; j++) {
1022							found[foundCount++] = elements[j];
1023						}
1024					}
1025					currentContext = [];
1026					var currentContextIndex = 0, checkFunction;
1027					switch (attrOperator) {
1028						case '=': checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue) }; break;
1029						case '~': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('(\\s|^)'+attrValue+'(\\s|$)'))) }; break;
1030						case '|': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))) }; break;
1031						case '^': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0) }; break;
1032						case '$': checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length) }; break;
1033						case '*': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1) }; break;
1034						default : checkFunction = function(e) { return e.getAttribute(attrName) };
1035					}
1036					currentContext = [];
1037					var currentContextIndex = 0;
1038					for (var k = 0; k < found.length; k++) {
1039						if (checkFunction(found[k])) {
1040							currentContext[currentContextIndex++] = found[k];
1041						}
1042					}
1043					continue;
1044				}
1045				tagName = token;
1046				var found = [], foundCount = 0;
1047				for (var h = 0; h < currentContext.length; h++) {
1048					var elements = currentContext[h].getElementsByTagName(tagName);
1049					for (var j = 0; j < elements.length; j++) {
1050						found[foundCount++] = elements[j];
1051					}
1052				}
1053				currentContext = found;
1054			}
1055			resultList = [].concat(resultList,currentContext);
1056		}
1057		return resultList;
1058	},
1059	trim: function (str) {
1060		return str.replace(/^\s+/, '').replace(/\s+$/, '');
1061	},
1062	bind: function(f, scope, forceArgs){
1063		return function() {return f.apply(scope, typeof forceArgs !== 'undefined' ? [forceArgs] : arguments);};
1064	}
1065};
1066
1067/*
1068 * jQuery Open/Close plugin
1069 */
1070;(function($) {
1071	function OpenClose(options) {
1072		this.options = $.extend({
1073			addClassBeforeAnimation: true,
1074			hideOnClickOutside: false,
1075			activeClass: 'active',
1076			opener: '.opener',
1077			slider: '.slide',
1078			animSpeed: 400,
1079			effect: 'fade',
1080			event: 'click'
1081		}, options);
1082		this.init();
1083	}
1084	OpenClose.prototype = {
1085		init: function() {
1086			if (this.options.holder) {
1087				this.findElements();
1088				this.attachEvents();
1089				this.makeCallback('onInit', this);
1090			}
1091		},
1092		findElements: function() {
1093			this.holder = $(this.options.holder);
1094			this.opener = this.holder.find(this.options.opener);
1095			this.slider = this.holder.find(this.options.slider);
1096		},
1097		attachEvents: function() {
1098			// add handler
1099			var self = this;
1100			this.eventHandler = function(e) {
1101				e.preventDefault();
1102				if (self.slider.hasClass(slideHiddenClass)) {
1103					self.showSlide();
1104				} else {
1105					self.hideSlide();
1106				}
1107			};
1108      self.slider.attr('aria-hidden', 'true');
1109      self.opener.attr('aria-expanded', 'false');
1110			self.opener.on(self.options.event, this.eventHandler);
1111
1112			// hover mode handler
1113			if (self.options.event === 'hover') {
1114				self.opener.on('mouseenter', function() {
1115					if (!self.holder.hasClass(self.options.activeClass)) {
1116						self.showSlide();
1117					}
1118				});
1119				self.holder.on('mouseleave', function() {
1120					self.hideSlide();
1121				});
1122			}
1123
1124			// outside click handler
1125			self.outsideClickHandler = function(e) {
1126				if (self.options.hideOnClickOutside) {
1127					var target = $(e.target);
1128					if (!target.is(self.holder) && !target.closest(self.holder).length) {
1129						self.hideSlide();
1130					}
1131				}
1132			};
1133
1134			// set initial styles
1135			if (this.holder.hasClass(this.options.activeClass)) {
1136				$(document).on('click touchstart', self.outsideClickHandler);
1137			} else {
1138				this.slider.addClass(slideHiddenClass);
1139			}
1140		},
1141		showSlide: function() {
1142			var self = this;
1143			if (self.options.addClassBeforeAnimation) {
1144				self.holder.addClass(self.options.activeClass);
1145			}
1146      self.slider.attr('aria-hidden', 'false');
1147      self.opener.attr('aria-expanded', 'true');
1148			self.slider.removeClass(slideHiddenClass);
1149			$(document).on('click touchstart', self.outsideClickHandler);
1150
1151			self.makeCallback('animStart', true);
1152			toggleEffects[self.options.effect].show({
1153				box: self.slider,
1154				speed: self.options.animSpeed,
1155				complete: function() {
1156					if (!self.options.addClassBeforeAnimation) {
1157						self.holder.addClass(self.options.activeClass);
1158					}
1159					self.makeCallback('animEnd', true);
1160				}
1161			});
1162		},
1163		hideSlide: function() {
1164			var self = this;
1165			if (self.options.addClassBeforeAnimation) {
1166				self.holder.removeClass(self.options.activeClass);
1167			}
1168			$(document).off('click touchstart', self.outsideClickHandler);
1169
1170			self.makeCallback('animStart', false);
1171			toggleEffects[self.options.effect].hide({
1172				box: self.slider,
1173				speed: self.options.animSpeed,
1174				complete: function() {
1175					if (!self.options.addClassBeforeAnimation) {
1176						self.holder.removeClass(self.options.activeClass);
1177					}
1178					self.slider.addClass(slideHiddenClass);
1179          self.slider.attr('aria-hidden', 'true');
1180          self.opener.attr('aria-expanded', 'false');
1181					self.makeCallback('animEnd', false);
1182				}
1183			});
1184		},
1185		destroy: function() {
1186			this.slider.removeClass(slideHiddenClass).css({
1187				display: ''
1188			});
1189			this.opener.off(this.options.event, this.eventHandler);
1190			this.holder.removeClass(this.options.activeClass).removeData('OpenClose');
1191			$(document).off('click touchstart', this.outsideClickHandler);
1192		},
1193		makeCallback: function(name) {
1194			if (typeof this.options[name] === 'function') {
1195				var args = Array.prototype.slice.call(arguments);
1196				args.shift();
1197				this.options[name].apply(this, args);
1198			}
1199		}
1200	};
1201
1202	// add stylesheet for slide on DOMReady
1203	var slideHiddenClass = 'js-slide-hidden';
1204	(function() {
1205		var tabStyleSheet = $('<style type="text/css">')[0];
1206		var tabStyleRule = '.' + slideHiddenClass;
1207		tabStyleRule += '{position:absolute !important;left:-9999px !important;top:-9999px !important;display:block !important}';
1208		if (tabStyleSheet.styleSheet) {
1209			tabStyleSheet.styleSheet.cssText = tabStyleRule;
1210		} else {
1211			tabStyleSheet.appendChild(document.createTextNode(tabStyleRule));
1212		}
1213		$('head').append(tabStyleSheet);
1214	}());
1215
1216	// animation effects
1217	var toggleEffects = {
1218		slide: {
1219			show: function(o) {
1220				o.box.stop(true).hide().slideDown(o.speed, o.complete);
1221			},
1222			hide: function(o) {
1223				o.box.stop(true).slideUp(o.speed, o.complete);
1224			}
1225		},
1226		fade: {
1227			show: function(o) {
1228				o.box.stop(true).hide().fadeIn(o.speed, o.complete);
1229			},
1230			hide: function(o) {
1231				o.box.stop(true).fadeOut(o.speed, o.complete);
1232			}
1233		},
1234		none: {
1235			show: function(o) {
1236				o.box.hide().show(0, o.complete);
1237			},
1238			hide: function(o) {
1239				o.box.hide(0, o.complete);
1240			}
1241		}
1242	};
1243
1244	// jQuery plugin interface
1245	$.fn.openClose = function(opt) {
1246		var args = Array.prototype.slice.call(arguments);
1247		var method = args[0];
1248
1249		return this.each(function() {
1250			var $holder = jQuery(this);
1251			var instance = $holder.data('OpenClose');
1252
1253			if (typeof opt === 'object' || typeof opt === 'undefined') {
1254				$holder.data('OpenClose', new OpenClose($.extend({
1255					holder: this
1256				}, opt)));
1257			} else if (typeof method === 'string' && instance) {
1258				if (typeof instance[method] === 'function') {
1259					args.shift();
1260					instance[method].apply(instance, args);
1261				}
1262			}
1263		});
1264	};
1265}(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.