PageSourceSearch

https://donate.k9sforwarriors.org/sites/default/files/js/js_c4qEqz1Tt-6zr--Bz1R_Fc3ly10lPobnb0OaHeHPUak.js

js k9sforwarriors.org collected 2026-09-25 02:55:52 UTC 119,520 bytes, 3,734 lines download raw bytes

1/*!
2 * SmartMenus jQuery Plugin - v1.0.0 - January 27, 2016
3 * http://www.smartmenus.org/
4 *
5 * Copyright Vasil Dinkov, Vadikom Web Ltd.
6 * http://vadikom.com
7 *
8 * Licensed MIT
9 */
10
11(function(factory) {
12	if (typeof define === 'function' && define.amd) {
13		// AMD
14		define(['jquery'], factory);
15	} else if (typeof module === 'object' && typeof module.exports === 'object') {
16		// CommonJS
17		module.exports = factory(require('jquery'));
18	} else {
19		// Global jQuery
20		factory(jQuery);
21	}
22} (function($) {
23
24	var menuTrees = [],
25		IE = !!window.createPopup, // detect it for the iframe shim
26		mouse = false, // optimize for touch by default - we will detect for mouse input
27		touchEvents = 'ontouchstart' in window, // we use this just to choose between toucn and pointer events, not for touch screen detection
28		mouseDetectionEnabled = false,
29		requestAnimationFrame = window.requestAnimationFrame || function(callback) { return setTimeout(callback, 1000 / 60); },
30		cancelAnimationFrame = window.cancelAnimationFrame || function(id) { clearTimeout(id); };
31
32	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
33	function initMouseDetection(disable) {
34		var eNS = '.smartmenus_mouse';
35		if (!mouseDetectionEnabled && !disable) {
36			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
37			// 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)
38			var firstTime = true,
39				lastMove = null;
40			$(document).bind(getEventsNS([
41				['mousemove', function(e) {
42					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
43					if (lastMove) {
44						var deltaX = Math.abs(lastMove.x - thisMove.x),
45							deltaY = Math.abs(lastMove.y - thisMove.y);
46	 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
47							mouse = true;
48							// 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
49							if (firstTime) {
50								var $a = $(e.target).closest('a');
51								if ($a.is('a')) {
52									$.each(menuTrees, function() {
53										if ($.contains(this.$root[0], $a[0])) {
54											this.itemEnter({ currentTarget: $a[0] });
55											return false;
56										}
57									});
58								}
59								firstTime = false;
60							}
61						}
62					}
63					lastMove = thisMove;
64				}],
65				[touchEvents ? 'touchstart' : 'pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut', function(e) {
66					if (isTouchEvent(e.originalEvent)) {
67						mouse = false;
68					}
69				}]
70			], eNS));
71			mouseDetectionEnabled = true;
72		} else if (mouseDetectionEnabled && disable) {
73			$(document).unbind(eNS);
74			mouseDetectionEnabled = false;
75		}
76	}
77
78	function isTouchEvent(e) {
79		return !/^(4|mouse)$/.test(e.pointerType);
80	}
81
82	// returns a jQuery bind() ready object
83	function getEventsNS(defArr, eNS) {
84		if (!eNS) {
85			eNS = '';
86		}
87		var obj = {};
88		$.each(defArr, function(index, value) {
89			obj[value[0].split(' ').join(eNS + ' ') + eNS] = value[1];
90		});
91		return obj;
92	}
93
94	$.SmartMenus = function(elm, options) {
95		this.$root = $(elm);
96		this.opts = options;
97		this.rootId = ''; // internal
98		this.accessIdPrefix = '';
99		this.$subArrow = null;
100		this.activatedItems = []; // stores last activated A's for each level
101		this.visibleSubMenus = []; // stores visible sub menus UL's (might be in no particular order)
102		this.showTimeout = 0;
103		this.hideTimeout = 0;
104		this.scrollTimeout = 0;
105		this.clickActivated = false;
106		this.focusActivated = false;
107		this.zIndexInc = 0;
108		this.idInc = 0;
109		this.$firstLink = null; // we'll use these for some tests
110		this.$firstSub = null; // at runtime so we'll cache them
111		this.disabled = false;
112		this.$disableOverlay = null;
113		this.$touchScrollingSub = null;
114		this.cssTransforms3d = 'perspective' in elm.style || 'webkitPerspective' in elm.style;
115		this.wasCollapsible = false;
116		this.init();
117	};
118
119	$.extend($.SmartMenus, {
120		hideAll: function() {
121			$.each(menuTrees, function() {
122				this.menuHideAll();
123			});
124		},
125		destroy: function() {
126			while (menuTrees.length) {
127				menuTrees[0].destroy();
128			}
129			initMouseDetection(true);
130		},
131		prototype: {
132			init: function(refresh) {
133				var self = this;
134
135				if (!refresh) {
136					menuTrees.push(this);
137
138					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
139					this.accessIdPrefix = 'sm-' + this.rootId + '-';
140
141					if (this.$root.hasClass('sm-rtl')) {
142						this.opts.rightToLeftSubMenus = true;
143					}
144
145					// init root (main menu)
146					var eNS = '.smartmenus';
147					this.$root
148						.data('smartmenus', this)
149						.attr('data-smartmenus-id', this.rootId)
150						.dataSM('level', 1)
151						.bind(getEventsNS([
152							['mouseover focusin', $.proxy(this.rootOver, this)],
153							['mouseout focusout', $.proxy(this.rootOut, this)],
154							['keydown', $.proxy(this.rootKeyDown, this)]
155						], eNS))
156						.delegate('a', getEventsNS([
157							['mouseenter', $.proxy(this.itemEnter, this)],
158							['mouseleave', $.proxy(this.itemLeave, this)],
159							['mousedown', $.proxy(this.itemDown, this)],
160							['focus', $.proxy(this.itemFocus, this)],
161							['blur', $.proxy(this.itemBlur, this)],
162							['click', $.proxy(this.itemClick, this)]
163						], eNS));
164
165					// hide menus on tap or click outside the root UL
166					eNS += this.rootId;
167					if (this.opts.hideOnClick) {
168						$(document).bind(getEventsNS([
169							['touchstart', $.proxy(this.docTouchStart, this)],
170							['touchmove', $.proxy(this.docTouchMove, this)],
171							['touchend', $.proxy(this.docTouchEnd, this)],
172							// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
173							['click', $.proxy(this.docClick, this)]
174						], eNS));
175					}
176					// hide sub menus on resize
177					$(window).bind(getEventsNS([['resize orientationchange', $.proxy(this.winResize, this)]], eNS));
178
179					if (this.opts.subIndicators) {
180						this.$subArrow = $('<span/>').addClass('sub-arrow');
181						if (this.opts.subIndicatorsText) {
182							this.$subArrow.html(this.opts.subIndicatorsText);
183						}
184					}
185
186					// make sure mouse detection is enabled
187					initMouseDetection();
188				}
189
190				// init sub menus
191				this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0);
192
193				this.$firstLink = this.$root.find('a').eq(0);
194
195				// find current item
196				if (this.opts.markCurrentItem) {
197					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
198						reHash = /#.*/,
199						locHref = window.location.href.replace(reDefaultDoc, ''),
200						locHrefNoHash = locHref.replace(reHash, '');
201					this.$root.find('a').each(function() {
202						var href = this.href.replace(reDefaultDoc, ''),
203							$this = $(this);
204						if (href == locHref || href == locHrefNoHash) {
205							$this.addClass('current');
206							if (self.opts.markCurrentTree) {
207								$this.parentsUntil('[data-smartmenus-id]', 'ul').each(function() {
208									$(this).dataSM('parent-a').addClass('current');
209								});
210							}
211						}
212					});
213				}
214
215				// save initial state
216				this.wasCollapsible = this.isCollapsible();
217			},
218			destroy: function(refresh) {
219				if (!refresh) {
220					var eNS = '.smartmenus';
221					this.$root
222						.removeData('smartmenus')
223						.removeAttr('data-smartmenus-id')
224						.removeDataSM('level')
225						.unbind(eNS)
226						.undelegate(eNS);
227					eNS += this.rootId;
228					$(document).unbind(eNS);
229					$(window).unbind(eNS);
230					if (this.opts.subIndicators) {
231						this.$subArrow = null;
232					}
233				}
234				this.menuHideAll();
235				var self = this;
236				this.$root.find('ul').each(function() {
237						var $this = $(this);
238						if ($this.dataSM('scroll-arrows')) {
239							$this.dataSM('scroll-arrows').remove();
240						}
241						if ($this.dataSM('shown-before')) {
242							if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
243								$this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
244							}
245							if ($this.dataSM('scroll-arrows')) {
246								$this.dataSM('scroll-arrows').remove();
247							}
248							$this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
249						}
250						if (($this.attr('id') || '').indexOf(self.accessIdPrefix) == 0) {
251							$this.removeAttr('id');
252						}
253					})
254					.removeDataSM('in-mega')
255					.removeDataSM('shown-before')
256					.removeDataSM('ie-shim')
257					.removeDataSM('scroll-arrows')
258					.removeDataSM('parent-a')
259					.removeDataSM('level')
260					.removeDataSM('beforefirstshowfired')
261					.removeAttr('role')
262					.removeAttr('aria-hidden')
263					.removeAttr('aria-labelledby')
264					.removeAttr('aria-expanded');
265				this.$root.find('a.has-submenu').each(function() {
266						var $this = $(this);
267						if ($this.attr('id').indexOf(self.accessIdPrefix) == 0) {
268							$this.removeAttr('id');
269						}
270					})
271					.removeClass('has-submenu')
272					.removeDataSM('sub')
273					.removeAttr('aria-haspopup')
274					.removeAttr('aria-controls')
275					.removeAttr('aria-expanded')
276					.closest('li').removeDataSM('sub');
277				if (this.opts.subIndicators) {
278					this.$root.find('span.sub-arrow').remove();
279				}
280				if (this.opts.markCurrentItem) {
281					this.$root.find('a.current').removeClass('current');
282				}
283				if (!refresh) {
284					this.$root = null;
285					this.$firstLink = null;
286					this.$firstSub = null;
287					if (this.$disableOverlay) {
288						this.$disableOverlay.remove();
289						this.$disableOverlay = null;
290					}
291					menuTrees.splice($.inArray(this, menuTrees), 1);
292				}
293			},
294			disable: function(noOverlay) {
295				if (!this.disabled) {
296					this.menuHideAll();
297					// display overlay over the menu to prevent interaction
298					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
299						var pos = this.$root.offset();
300						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
301							position: 'absolute',
302							top: pos.top,
303							left: pos.left,
304							width: this.$root.outerWidth(),
305							height: this.$root.outerHeight(),
306							zIndex: this.getStartZIndex(true),
307							opacity: 0
308						}).appendTo(document.body);
309					}
310					this.disabled = true;
311				}
312			},
313			docClick: function(e) {
314				if (this.$touchScrollingSub) {
315					this.$touchScrollingSub = null;
316					return;
317				}
318				// hide on any click outside the menu or on a menu link
319				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
320					this.menuHideAll();
321				}
322			},
323			docTouchEnd: function(e) {
324				if (!this.lastTouch) {
325					return;
326				}
327				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 || !$.contains(this.$root[0], this.lastTouch.target))) {
328					if (this.hideTimeout) {
329						clearTimeout(this.hideTimeout);
330						this.hideTimeout = 0;
331					}
332					// hide with a delay to prevent triggering accidental unwanted click on some page element
333					var self = this;
334					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, 350);
335				}
336				this.lastTouch = null;
337			},
338			docTouchMove: function(e) {
339				if (!this.lastTouch) {
340					return;
341				}
342				var touchPoint = e.originalEvent.touches[0];
343				this.lastTouch.x2 = touchPoint.pageX;
344				this.lastTouch.y2 = touchPoint.pageY;
345			},
346			docTouchStart: function(e) {
347				var touchPoint = e.originalEvent.touches[0];
348				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
349			},
350			enable: function() {
351				if (this.disabled) {
352					if (this.$disableOverlay) {
353						this.$disableOverlay.remove();
354						this.$disableOverlay = null;
355					}
356					this.disabled = false;
357				}
358			},
359			getClosestMenu: function(elm) {
360				var $closestMenu = $(elm).closest('ul');
361				while ($closestMenu.dataSM('in-mega')) {
362					$closestMenu = $closestMenu.parent().closest('ul');
363				}
364				return $closestMenu[0] || null;
365			},
366			getHeight: function($elm) {
367				return this.getOffset($elm, true);
368			},
369			// returns precise width/height float values
370			getOffset: function($elm, height) {
371				var old;
372				if ($elm.css('display') == 'none') {
373					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
374					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
375				}
376				var box = $elm[0].getBoundingClientRect && $elm[0].getBoundingClientRect(),
377					val = box && (height ? box.height || box.bottom - box.top : box.width || box.right - box.left);
378				if (!val && val !== 0) {
379					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
380				}
381				if (old) {
382					$elm.hide().css(old);
383				}
384				return val;
385			},
386			getStartZIndex: function(root) {
387				var zIndex = parseInt(this[root ? '$root' : '$firstSub'].css('z-index'));
388				if (!root && isNaN(zIndex)) {
389					zIndex = parseInt(this.$root.css('z-index'));
390				}
391				return !isNaN(zIndex) ? zIndex : 1;
392			},
393			getTouchPoint: function(e) {
394				return e.touches && e.touches[0] || e.changedTouches && e.changedTouches[0] || e;
395			},
396			getViewport: function(height) {
397				var name = height ? 'Height' : 'Width',
398					val = document.documentElement['client' + name],
399					val2 = window['inner' + name];
400				if (val2) {
401					val = Math.min(val, val2);
402				}
403				return val;
404			},
405			getViewportHeight: function() {
406				return this.getViewport(true);
407			},
408			getViewportWidth: function() {
409				return this.getViewport();
410			},
411			getWidth: function($elm) {
412				return this.getOffset($elm);
413			},
414			handleEvents: function() {
415				return !this.disabled && this.isCSSOn();
416			},
417			handleItemEvents: function($a) {
418				return this.handleEvents() && !this.isLinkInMegaMenu($a);
419			},
420			isCollapsible: function() {
421				return this.$firstSub.css('position') == 'static';
422			},
423			isCSSOn: function() {
424				return this.$firstLink.css('display') == 'block';
425			},
426			isFixed: function() {
427				var isFixed = this.$root.css('position') == 'fixed';
428				if (!isFixed) {
429					this.$root.parentsUntil('body').each(function() {
430						if ($(this).css('position') == 'fixed') {
431							isFixed = true;
432							return false;
433						}
434					});
435				}
436				return isFixed;
437			},
438			isLinkInMegaMenu: function($a) {
439				return $(this.getClosestMenu($a[0])).hasClass('mega-menu');
440			},
441			isTouchMode: function() {
442				return !mouse || this.opts.noMouseOver || this.isCollapsible();
443			},
444			itemActivate: function($a, focus) {
445				var $ul = $a.closest('ul'),
446					level = $ul.dataSM('level');
447				// 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
448				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
449					var self = this;
450					$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() {
451						self.itemActivate($(this).dataSM('parent-a'));
452					});
453				}
454				// hide any visible deeper level sub menus
455				if (!this.isCollapsible() || focus) {
456					this.menuHideSubMenus(!this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level);
457				}
458				// save new active item for this level
459				this.activatedItems[level - 1] = $a;
460				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
461					return;
462				}
463				// show the sub menu if this item has one
464				var $sub = $a.dataSM('sub');
465				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
466					this.menuShow($sub);
467				}
468			},
469			itemBlur: function(e) {
470				var $a = $(e.currentTarget);
471				if (!this.handleItemEvents($a)) {
472					return;
473				}
474				this.$root.triggerHandler('blur.smapi', $a[0]);
475			},
476			itemClick: function(e) {
477				var $a = $(e.currentTarget);
478				if (!this.handleItemEvents($a)) {
479					return;
480				}
481				if (this.$touchScrollingSub && this.$touchScrollingSub[0] == $a.closest('ul')[0]) {
482					this.$touchScrollingSub = null;
483					e.stopPropagation();
484					return false;
485				}
486				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
487					return false;
488				}
489				var subArrowClicked = $(e.target).is('span.sub-arrow'),
490					$sub = $a.dataSM('sub'),
491					firstLevelSub = $sub ? $sub.dataSM('level') == 2 : false;
492				// if the sub is not visible
493				if ($sub && !$sub.is(':visible')) {
494					if (this.opts.showOnClick && firstLevelSub) {
495						this.clickActivated = true;
496					}
497					// try to activate the item and show the sub
498					this.itemActivate($a);
499					// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
500					// if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded
501					if ($sub.is(':visible')) {
502						this.focusActivated = true;
503						return false;
504					}
505				} else if (this.isCollapsible() && subArrowClicked) {
506					this.itemActivate($a);
507					this.menuHide($sub);
508					return false;
509				}
510				if (this.opts.showOnClick && firstLevelSub || $a.hasClass('disabled') || this.$root.triggerHandler('select.smapi', $a[0]) === false) {
511					return false;
512				}
513			},
514			itemDown: function(e) {
515				var $a = $(e.currentTarget);
516				if (!this.handleItemEvents($a)) {
517					return;
518				}
519				$a.dataSM('mousedown', true);
520			},
521			itemEnter: function(e) {
522				var $a = $(e.currentTarget);
523				if (!this.handleItemEvents($a)) {
524					return;
525				}
526				if (!this.isTouchMode()) {
527					if (this.showTimeout) {
528						clearTimeout(this.showTimeout);
529						this.showTimeout = 0;
530					}
531					var self = this;
532					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.closest('ul').dataSM('level') == 1 ? 1 : this.opts.showTimeout);
533				}
534				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
535			},
536			itemFocus: function(e) {
537				var $a = $(e.currentTarget);
538				if (!this.handleItemEvents($a)) {
539					return;
540				}
541				// 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
542				if (this.focusActivated && (!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
543					this.itemActivate($a, true);
544				}
545				this.$root.triggerHandler('focus.smapi', $a[0]);
546			},
547			itemLeave: function(e) {
548				var $a = $(e.currentTarget);
549				if (!this.handleItemEvents($a)) {
550					return;
551				}
552				if (!this.isTouchMode()) {
553					$a[0].blur();
554					if (this.showTimeout) {
555						clearTimeout(this.showTimeout);
556						this.showTimeout = 0;
557					}
558				}
559				$a.removeDataSM('mousedown');
560				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
561			},
562			menuHide: function($sub) {
563				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
564					return;
565				}
566				$sub.stop(true, true);
567				if ($sub.css('display') != 'none') {
568					var complete = function() {
569						// unset z-index
570						$sub.css('z-index', '');
571					};
572					// if sub is collapsible (mobile view)
573					if (this.isCollapsible()) {
574						if (this.opts.collapsibleHideFunction) {
575							this.opts.collapsibleHideFunction.call(this, $sub, complete);
576						} else {
577							$sub.hide(this.opts.collapsibleHideDuration, complete);
578						}
579					} else {
580						if (this.opts.hideFunction) {
581							this.opts.hideFunction.call(this, $sub, complete);
582						} else {
583							$sub.hide(this.opts.hideDuration, complete);
584						}
585					}
586					// remove IE iframe shim
587					if ($sub.dataSM('ie-shim')) {
588						$sub.dataSM('ie-shim').remove().css({ '-webkit-transform': '', transform: '' });
589					}
590					// deactivate scrolling if it is activated for this sub
591					if ($sub.dataSM('scroll')) {
592						this.menuScrollStop($sub);
593						$sub.css({ 'touch-action': '', '-ms-touch-action': '', '-webkit-transform': '', transform: '' })
594							.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
595					}
596					// unhighlight parent item + accessibility
597					$sub.dataSM('parent-a').removeClass('highlighted').attr('aria-expanded', 'false');
598					$sub.attr({
599						'aria-expanded': 'false',
600						'aria-hidden': 'true'
601					});
602					var level = $sub.dataSM('level');
603					this.activatedItems.splice(level - 1, 1);
604					this.visibleSubMenus.splice($.inArray($sub, this.visibleSubMenus), 1);
605					this.$root.triggerHandler('hide.smapi', $sub[0]);
606				}
607			},
608			menuHideAll: function() {
609				if (this.showTimeout) {
610					clearTimeout(this.showTimeout);
611					this.showTimeout = 0;
612				}
613				// hide all subs
614				// if it's a popup, this.visibleSubMenus[0] is the root UL
615				var level = this.opts.isPopup ? 1 : 0;
616				for (var i = this.visibleSubMenus.length - 1; i >= level; i--) {
617					this.menuHide(this.visibleSubMenus[i]);
618				}
619				// hide root if it's popup
620				if (this.opts.isPopup) {
621					this.$root.stop(true, true);
622					if (this.$root.is(':visible')) {
623						if (this.opts.hideFunction) {
624							this.opts.hideFunction.call(this, this.$root);
625						} else {
626							this.$root.hide(this.opts.hideDuration);
627						}
628						// remove IE iframe shim
629						if (this.$root.dataSM('ie-shim')) {
630							this.$root.dataSM('ie-shim').remove();
631						}
632					}
633				}
634				this.activatedItems = [];
635				this.visibleSubMenus = [];
636				this.clickActivated = false;
637				this.focusActivated = false;
638				// reset z-index increment
639				this.zIndexInc = 0;
640				this.$root.triggerHandler('hideAll.smapi');
641			},
642			menuHideSubMenus: function(level) {
643				for (var i = this.activatedItems.length - 1; i >= level; i--) {
644					var $sub = this.activatedItems[i].dataSM('sub');
645					if ($sub) {
646						this.menuHide($sub);
647					}
648				}
649			},
650			menuIframeShim: function($ul) {
651				// create iframe shim for the menu
652				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
653					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
654						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
655					);
656				}
657			},
658			menuInit: function($ul) {
659				if (!$ul.dataSM('in-mega')) {
660					// mark UL's in mega drop downs (if any) so we can neglect them
661					if ($ul.hasClass('mega-menu')) {
662						$ul.find('ul').dataSM('in-mega', true);
663					}
664					// get level (much faster than, for example, using parentsUntil)
665					var level = 2,
666						par = $ul[0];
667					while ((par = par.parentNode.parentNode) != this.$root[0]) {
668						level++;
669					}
670					// cache stuff for quick access
671					var $a = $ul.prevAll('a').eq(-1);
672					// if the link is nested (e.g. in a heading)
673					if (!$a.length) {
674						$a = $ul.prevAll().find('a').eq(-1);
675					}
676					$a.addClass('has-submenu').dataSM('sub', $ul);
677					$ul.dataSM('parent-a', $a)
678						.dataSM('level', level)
679						.parent().dataSM('sub', $ul);
680					// accessibility
681					var aId = $a.attr('id') || this.accessIdPrefix + (++this.idInc),
682						ulId = $ul.attr('id') || this.accessIdPrefix + (++this.idInc);
683					$a.attr({
684						id: aId,
685						'aria-haspopup': 'true',
686						'aria-controls': ulId,
687						'aria-expanded': 'false'
688					});
689					$ul.attr({
690						id: ulId,
691						'role': 'group',
692						'aria-hidden': 'true',
693						'aria-labelledby': aId,
694						'aria-expanded': 'false'
695					});
696					// add sub indicator to parent item
697					if (this.opts.subIndicators) {
698						$a[this.opts.subIndicatorsPos](this.$subArrow.clone());
699					}
700				}
701			},
702			menuPosition: function($sub) {
703				var $a = $sub.dataSM('parent-a'),
704					$li = $a.closest('li'),
705					$ul = $li.parent(),
706					level = $sub.dataSM('level'),
707					subW = this.getWidth($sub),
708					subH = this.getHeight($sub),
709					itemOffset = $a.offset(),
710					itemX = itemOffset.left,
711					itemY = itemOffset.top,
712					itemW = this.getWidth($a),
713					itemH = this.getHeight($a),
714					$win = $(window),
715					winX = $win.scrollLeft(),
716					winY = $win.scrollTop(),
717					winW = this.getViewportWidth(),
718					winH = this.getViewportHeight(),
719					horizontalParent = $ul.parent().is('[data-sm-horizontal-sub]') || level == 2 && !$ul.hasClass('sm-vertical'),
720					rightToLeft = this.opts.rightToLeftSubMenus && !$li.is('[data-sm-reverse]') || !this.opts.rightToLeftSubMenus && $li.is('[data-sm-reverse]'),
721					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
722					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
723					x, y;
724				if (horizontalParent) {
725					x = rightToLeft ? itemW - subW - subOffsetX : subOffsetX;
726					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
727				} else {
728					x = rightToLeft ? subOffsetX - subW : itemW - subOffsetX;
729					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
730				}
731				if (this.opts.keepInViewport) {
732					var absX = itemX + x,
733						absY = itemY + y;
734					if (rightToLeft && absX < winX) {
735						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
736					} else if (!rightToLeft && absX + subW > winX + winW) {
737						x = horizontalParent ? winX + winW - subW - absX + x : subOffsetX - subW;
738					}
739					if (!horizontalParent) {
740						if (subH < winH && absY + subH > winY + winH) {
741							y += winY + winH - subH - absY;
742						} else if (subH >= winH || absY < winY) {
743							y += winY - absY;
744						}
745					}
746					// do we need scrolling?
747					// 0.49 used for better precision when dealing with float values
748					if (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49) {
749						var self = this;
750						if (!$sub.dataSM('scroll-arrows')) {
751							$sub.dataSM('scroll-arrows', $([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], $('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]])
752								.bind({
753									mouseenter: function() {
754										$sub.dataSM('scroll').up = $(this).hasClass('scroll-up');
755										self.menuScroll($sub);
756									},
757									mouseleave: function(e) {
758										self.menuScrollStop($sub);
759										self.menuScrollOut($sub, e);
760									},
761									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
762								})
763								.insertAfter($sub)
764							);
765						}
766						// bind scroll events and save scroll data for this sub
767						var eNS = '.smartmenus_scroll';
768						$sub.dataSM('scroll', {
769								y: this.cssTransforms3d ? 0 : y - itemH,
770								step: 1,
771								// cache stuff for faster recalcs later
772								itemH: itemH,
773								subH: subH,
774								arrowDownH: this.getHeight($sub.dataSM('scroll-arrows').eq(1))
775							})
776							.bind(getEventsNS([
777								['mouseover', function(e) { self.menuScrollOver($sub, e); }],
778								['mouseout', function(e) { self.menuScrollOut($sub, e); }],
779								['mousewheel DOMMouseScroll', function(e) { self.menuScrollMousewheel($sub, e); }]
780							], eNS))
781							.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') })
782								.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
783						// when a menu tree is fixed positioned we allow scrolling via touch too
784						// since there is no other way to access such long sub menus if no mouse is present
785						if (this.isFixed()) {
786							$sub.css({ 'touch-action': 'none', '-ms-touch-action': 'none' })
787								.bind(getEventsNS([
788									[touchEvents ? 'touchstart touchmove touchend' : 'pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp', function(e) {
789										self.menuScrollTouch($sub, e);
790									}]
791								], eNS));
792						}
793					}
794				}
795				$sub.css({ top: 'auto', left: '0', marginLeft: x, marginTop: y - itemH });
796				// IE iframe shim
797				this.menuIframeShim($sub);
798				if ($sub.dataSM('ie-shim')) {
799					$sub.dataSM('ie-shim').css({ zIndex: $sub.css('z-index'), width: subW, height: subH, marginLeft: x, marginTop: y - itemH });
800				}
801			},
802			menuScroll: function($sub, once, step) {
803				var data = $sub.dataSM('scroll'),
804					$arrows = $sub.dataSM('scroll-arrows'),
805					end = data.up ? data.upEnd : data.downEnd,
806					diff;
807				if (!once && data.momentum) {
808					data.momentum *= 0.92;
809					diff = data.momentum;
810					if (diff < 0.5) {
811						this.menuScrollStop($sub);
812						return;
813					}
814				} else {
815					diff = step || (once || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor(data.step));
816				}
817				// hide any visible deeper level sub menus
818				var level = $sub.dataSM('level');
819				if (this.activatedItems[level - 1] && this.activatedItems[level - 1].dataSM('sub') && this.activatedItems[level - 1].dataSM('sub').is(':visible')) {
820					this.menuHideSubMenus(level - 1);
821				}
822				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);
823				$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 });
824				// show opposite arrow if appropriate
825				if (mouse && (data.up && data.y > data.downEnd || !data.up && data.y < data.upEnd)) {
826					$arrows.eq(data.up ? 1 : 0).show();
827				}
828				// if we've reached the end
829				if (data.y == end) {
830					if (mouse) {
831						$arrows.eq(data.up ? 0 : 1).hide();
832					}
833					this.menuScrollStop($sub);
834				} else if (!once) {
835					if (this.opts.scrollAccelerate && data.step < this.opts.scrollStep) {
836						data.step += 0.2;
837					}
838					var self = this;
839					this.scrollTimeout = requestAnimationFrame(function() { self.menuScroll($sub); });
840				}
841			},
842			menuScrollMousewheel: function($sub, e) {
843				if (this.getClosestMenu(e.target) == $sub[0]) {
844					e = e.originalEvent;
845					var up = (e.wheelDelta || -e.detail) > 0;
846					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
847						$sub.dataSM('scroll').up = up;
848						this.menuScroll($sub, true);
849					}
850				}
851				e.preventDefault();
852			},
853			menuScrollOut: function($sub, e) {
854				if (mouse) {
855					if (!/^scroll-(up|down)/.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || this.getClosestMenu(e.relatedTarget) != $sub[0])) {
856						$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
857					}
858				}
859			},
860			menuScrollOver: function($sub, e) {
861				if (mouse) {
862					if (!/^scroll-(up|down)/.test(e.target.className) && this.getClosestMenu(e.target) == $sub[0]) {
863						this.menuScrollRefreshData($sub);
864						var data = $sub.dataSM('scroll'),
865							upEnd = $(window).scrollTop() - $sub.dataSM('parent-a').offset().top - data.itemH;
866						$sub.dataSM('scroll-arrows').eq(0).css('margin-top', upEnd).end()
867							.eq(1).css('margin-top', upEnd + this.getViewportHeight() - data.arrowDownH).end()
868							.css('visibility', 'visible');
869					}
870				}
871			},
872			menuScrollRefreshData: function($sub) {
873				var data = $sub.dataSM('scroll'),
874					upEnd = $(window).scrollTop() - $sub.dataSM('parent-a').offset().top - data.itemH;
875				if (this.cssTransforms3d) {
876					upEnd = -(parseFloat($sub.css('margin-top')) - upEnd);
877				}
878				$.extend(data, {
879					upEnd: upEnd,
880					downEnd: upEnd + this.getViewportHeight() - data.subH
881				});
882			},
883			menuScrollStop: function($sub) {
884				if (this.scrollTimeout) {
885					cancelAnimationFrame(this.scrollTimeout);
886					this.scrollTimeout = 0;
887					$sub.dataSM('scroll').step = 1;
888					return true;
889				}
890			},
891			menuScrollTouch: function($sub, e) {
892				e = e.originalEvent;
893				if (isTouchEvent(e)) {
894					var touchPoint = this.getTouchPoint(e);
895					// neglect event if we touched a visible deeper level sub menu
896					if (this.getClosestMenu(touchPoint.target) == $sub[0]) {
897						var data = $sub.dataSM('scroll');
898						if (/(start|down)$/i.test(e.type)) {
899							if (this.menuScrollStop($sub)) {
900								// if we were scrolling, just stop and don't activate any link on the first touch
901								e.preventDefault();
902								this.$touchScrollingSub = $sub;
903							} else {
904								this.$touchScrollingSub = null;
905							}
906							// update scroll data since the user might have zoomed, etc.
907							this.menuScrollRefreshData($sub);
908							// extend it with the touch properties
909							$.extend(data, {
910								touchStartY: touchPoint.pageY,
911								touchStartTime: e.timeStamp
912							});
913						} else if (/move$/i.test(e.type)) {
914							var prevY = data.touchY !== undefined ? data.touchY : data.touchStartY;
915							if (prevY !== undefined && prevY != touchPoint.pageY) {
916								this.$touchScrollingSub = $sub;
917								var up = prevY < touchPoint.pageY;
918								// changed direction? reset...
919								if (data.up !== undefined && data.up != up) {
920									$.extend(data, {
921										touchStartY: touchPoint.pageY,
922										touchStartTime: e.timeStamp
923									});
924								}
925								$.extend(data, {
926									up: up,
927									touchY: touchPoint.pageY
928								});
929								this.menuScroll($sub, true, Math.abs(touchPoint.pageY - prevY));
930							}
931							e.preventDefault();
932						} else { // touchend/pointerup
933							if (data.touchY !== undefined) {
934								if (data.momentum = Math.pow(Math.abs(touchPoint.pageY - data.touchStartY) / (e.timeStamp - data.touchStartTime), 2) * 15) {
935									this.menuScrollStop($sub);
936									this.menuScroll($sub);
937									e.preventDefault();
938								}
939								delete data.touchY;
940							}
941						}
942					}
943				}
944			},
945			menuShow: function($sub) {
946				if (!$sub.dataSM('beforefirstshowfired')) {
947					$sub.dataSM('beforefirstshowfired', true);
948					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
949						return;
950					}
951				}
952				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
953					return;
954				}
955				$sub.dataSM('shown-before', true)
956					.stop(true, true);
957				if (!$sub.is(':visible')) {
958					// highlight parent item
959					var $a = $sub.dataSM('parent-a');
960					if (this.opts.keepHighlighted || this.isCollapsible()) {
961						$a.addClass('highlighted');
962					}
963					if (this.isCollapsible()) {
964						$sub.removeClass('sm-nowrap').css({ zIndex: '', width: 'auto', minWidth: '', maxWidth: '', top: '', left: '', marginLeft: '', marginTop: '' });
965					} else {
966						// set z-index
967						$sub.css('z-index', this.zIndexInc = (this.zIndexInc || this.get
967StartZIndex()) + 1);
968						// min/max-width fix - no way to rely purely on CSS as all UL's are nested
969						if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
970							$sub.css({ width: 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
971							if (this.opts.subMenusMinWidth) {
972							 	$sub.css('min-width', this.opts.subMenusMinWidth);
973							}
974							if (this.opts.subMenusMaxWidth) {
975							 	var noMaxWidth = this.getWidth($sub);
976							 	$sub.css('max-width', this.opts.subMenusMaxWidth);
977								if (noMaxWidth > this.getWidth($sub)) {
978									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
979								}
980							}
981						}
982						this.menuPosition($sub);
983						// insert IE iframe shim
984						if ($sub.dataSM('ie-shim')) {
985							$sub.dataSM('ie-shim').insertBefore($sub);
986						}
987					}
988					var complete = function() {
989						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
990						$sub.css('overflow', '');
991					};
992					// if sub is collapsible (mobile view)
993					if (this.isCollapsible()) {
994						if (this.opts.collapsibleShowFunction) {
995							this.opts.collapsibleShowFunction.call(this, $sub, complete);
996						} else {
997							$sub.show(this.opts.collapsibleShowDuration, complete);
998						}
999					} else {
1000						if (this.opts.showFunction) {
1001							this.opts.showFunction.call(this, $sub, complete);
1002						} else {
1003							$sub.show(this.opts.showDuration, complete);
1004						}
1005					}
1006					// accessibility
1007					$a.attr('aria-expanded', 'true');
1008					$sub.attr({
1009						'aria-expanded': 'true',
1010						'aria-hidden': 'false'
1011					});
1012					// store sub menu in visible array
1013					this.visibleSubMenus.push($sub);
1014					this.$root.triggerHandler('show.smapi', $sub[0]);
1015				}
1016			},
1017			popupHide: function(noHideTimeout) {
1018				if (this.hideTimeout) {
1019					clearTimeout(this.hideTimeout);
1020					this.hideTimeout = 0;
1021				}
1022				var self = this;
1023				this.hideTimeout = setTimeout(function() {
1024					self.menuHideAll();
1025				}, noHideTimeout ? 1 : this.opts.hideTimeout);
1026			},
1027			popupShow: function(left, top) {
1028				if (!this.opts.isPopup) {
1029					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
1030					return;
1031				}
1032				if (this.hideTimeout) {
1033					clearTimeout(this.hideTimeout);
1034					this.hideTimeout = 0;
1035				}
1036				this.$root.dataSM('shown-before', true)
1037					.stop(true, true);
1038				if (!this.$root.is(':visible')) {
1039					this.$root.css({ left: left, top: top });
1040					// IE iframe shim
1041					this.menuIframeShim(this.$root);
1042					if (this.$root.dataSM('ie-shim')) {
1043						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left: left, top: top }).insertBefore(this.$root);
1044					}
1045					// show menu
1046					var self = this,
1047						complete = function() {
1048							self.$root.css('overflow', '');
1049						};
1050					if (this.opts.showFunction) {
1051						this.opts.showFunction.call(this, this.$root, complete);
1052					} else {
1053						this.$root.show(this.opts.showDuration, complete);
1054					}
1055					this.visibleSubMenus[0] = this.$root;
1056				}
1057			},
1058			refresh: function() {
1059				this.destroy(true);
1060				this.init(true);
1061			},
1062			rootKeyDown: function(e) {
1063				if (!this.handleEvents()) {
1064					return;
1065				}
1066				switch (e.keyCode) {
1067					case 27: // reset on Esc
1068						var $activeTopItem = this.activatedItems[0];
1069						if ($activeTopItem) {
1070							this.menuHideAll();
1071							$activeTopItem[0].focus();
1072							var $sub = $activeTopItem.dataSM('sub');
1073							if ($sub) {
1074								this.menuHide($sub);
1075							}
1076						}
1077						break;
1078					case 32: // activate item's sub on Space
1079						var $target = $(e.target);
1080						if ($target.is('a') && this.handleItemEvents($target)) {
1081							var $sub = $target.dataSM('sub');
1082							if ($sub && !$sub.is(':visible')) {
1083								this.itemClick({ currentTarget: e.target });
1084								e.preventDefault();
1085							}
1086						}
1087						break;
1088				}
1089			},
1090			rootOut: function(e) {
1091				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
1092					return;
1093				}
1094				if (this.hideTimeout) {
1095					clearTimeout(this.hideTimeout);
1096					this.hideTimeout = 0;
1097				}
1098				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
1099					var self = this;
1100					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
1101				}
1102			},
1103			rootOver: function(e) {
1104				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
1105					return;
1106				}
1107				if (this.hideTimeout) {
1108					clearTimeout(this.hideTimeout);
1109					this.hideTimeout = 0;
1110				}
1111			},
1112			winResize: function(e) {
1113				if (!this.handleEvents()) {
1114					// we still need to resize the disable overlay if it's visible
1115					if (this.$disableOverlay) {
1116						var pos = this.$root.offset();
1117	 					this.$disableOverlay.css({
1118							top: pos.top,
1119							left: pos.left,
1120							width: this.$root.outerWidth(),
1121							height: this.$root.outerHeight()
1122						});
1123					}
1124					return;
1125				}
1126				// hide sub menus on resize - on mobile do it only on orientation change
1127				if (!('onorientationchange' in window) || e.type == 'orientationchange') {
1128					var isCollapsible = this.isCollapsible();
1129					// if it was collapsible before resize and still is, don't do it
1130					if (!(this.wasCollapsible && isCollapsible)) { 
1131						if (this.activatedItems.length) {
1132							this.activatedItems[this.activatedItems.length - 1][0].blur();
1133						}
1134						this.menuHideAll();
1135					}
1136					this.wasCollapsible = isCollapsible;
1137				}
1138			}
1139		}
1140	});
1141
1142	$.fn.dataSM = function(key, val) {
1143		if (val) {
1144			return this.data(key + '_smartmenus', val);
1145		}
1146		return this.data(key + '_smartmenus');
1147	}
1148
1149	$.fn.removeDataSM = function(key) {
1150		return this.removeData(key + '_smartmenus');
1151	}
1152
1153	$.fn.smartmenus = function(options) {
1154		if (typeof options == 'string') {
1155			var args = arguments,
1156				method = options;
1157			Array.prototype.shift.call(args);
1158			return this.each(function() {
1159				var smartmenus = $(this).data('smartmenus');
1160				if (smartmenus && smartmenus[method]) {
1161					smartmenus[method].apply(smartmenus, args);
1162				}
1163			});
1164		}
1165		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
1166		return this.each(function() {
1167			new $.SmartMenus(this, opts);
1168		});
1169	}
1170
1171	// default settings
1172	$.fn.smartmenus.defaults = {
1173		isPopup:		false,		// is this a popup menu (can be shown via the popupS
1173how/popupHide methods) or a permanent menu bar
1174		mainMenuSubOffsetX:	0,		// pixels offset from default position
1175		mainMenuSubOffsetY:	0,		// pixels offset from default position
1176		subMenusSubOffsetX:	0,		// pixels offset from default position
1177		subMenusSubOffsetY:	0,		// pixels offset from default position
1178		subMenusMinWidth:	'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
1179		subMenusMaxWidth:	'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
1180		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
1181		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
1182		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
1183		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
1184		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
1185		showTimeout:		250,		// timeout before showing the sub menus
1186		hideTimeout:		500,		// timeout before hiding the sub menus
1187		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
1188		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
1189							// don't forget to call complete() at the end of whatever you do
1190							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
1191		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
1192		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
1193							// don't forget to call complete() at the end of whatever you do
1194							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
1195		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
1196		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
1197							// (i.e. when mobile styles are used to make the sub menus collapsible)
1198		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
1199		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
1200							// (i.e. when mobile styles are used to make the sub menus collapsible)
1201		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (i.e. mimic desktop app menus) (matters only for mouse input)
1202		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
1203		noMouseOver:		false,		// disable sub menus activation onmouseover (i.e. behave like in touch mode - use just mouse clicks) (matters only for mouse input)
1204		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
1205		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
1206		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
1207		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
1208		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
1209		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
1210		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
1211	};
1212
1213	return $;
1214}));;
1215/*!
1216 * SmartMenus jQuery Plugin Bootstrap Addon - v0.3.0 - January 27, 2016
1217 * http://www.smartmenus.org/
1218 *
1219 * Copyright Vasil Dinkov, Vadikom Web Ltd.
1220 * http://vadikom.com
1221 *
1222 * Licensed MIT
1223 */
1224
1225(function(factory) {
1226	if (typeof define === 'function' && define.amd) {
1227		// AMD
1228		define(['jquery', 'jquery.smartmenus'], factory);
1229	} else if (typeof module === 'object' && typeof module.exports === 'object') {
1230		// CommonJS
1231		module.exports = factory(require('jquery'));
1232	} else {
1233		// Global jQuery
1234		factory(jQuery);
1235	}
1236} (function($) {
1237
1238	$.extend($.SmartMenus.Bootstrap = {}, {
1239		keydownFix: false,
1240		init: function() {
1241			// init all navbars that don't have the "data-sm-skip" attribute set
1242			var $navbars = $('ul.navbar-nav:not([data-sm-skip])');
1243			$navbars.each(function() {
1244				var $this = $(this),
1245					obj = $this.data('smartmenus');
1246				// if this navbar is not initialized
1247				if (!obj) {
1248					$this.smartmenus({
1249
1250							// these are some good default options that should work for all
1251							// you can, of course, tweak these as you like
1252							subMenusSubOffsetX: 2,
1253							subMenusSubOffsetY: -6,
1254							subIndicators: false,
1255							collapsibleShowFunction: null,
1256							collapsibleHideFunction: null,
1257							rightToLeftSubMenus: $this.hasClass('navbar-right'),
1258							bottomToTopSubMenus: $this.closest('.navbar').hasClass('navbar-fixed-bottom')
1259						})
1260						.bind({
1261							// set/unset proper Bootstrap classes for some menu elements
1262							'show.smapi': function(e, menu) {
1263								var $menu = $(menu),
1264									$scrollArrows = $menu.dataSM('scroll-arrows');
1265								if ($scrollArrows) {
1266									// they inherit border-color from body, so we can use its background-color too
1267									$scrollArrows.css('background-color', $(document.body).css('background-color'));
1268								}
1269								$menu.parent().addClass('open');
1270							},
1271							'hide.smapi': function(e, menu) {
1272								$(menu).parent().removeClass('open');
1273							}
1274						});
1275
1276					function onInit() {
1277						// set Bootstrap's "active" class to SmartMenus "current" items (should someone decide to enable markCurrentItem: true)
1278						$this.find('a.current').parent().addClass('active');
1279						// remove any Bootstrap required attributes that might cause conflicting issues with the SmartMenus script
1280						$this.find('a.has-submenu').each(function() {
1281							var $this = $(this);
1282							if ($this.is('[data-toggle="dropdown"]')) {
1283								$this.dataSM('bs-data-toggle-dropdown', true).removeAttr('data-toggle');
1284							}
1285							if ($this.is('[role="button"]')) {
1286								$this.dataSM('bs-role-button', true).removeAttr('role');
1287							}
1288						});
1289					}
1290
1291					onInit();
1292
1293					function onBeforeDestroy() {
1294						$this.find('a.current').parent().removeClass('active');
1295						$this.find('a.has-submenu').each(function() {
1296							var $this = $(this);
1297							if ($this.dataSM('bs-data-toggle-dropdown')) {
1298								$this.attr('data-toggle', 'dropdown').removeDataSM('bs-data-toggle-dropdown');
1299							}
1300							if ($this.dataSM('bs-role-button')) {
1301								$this.attr('role', 'button').removeDataSM('bs-role-button');
1302							}
1303						});
1304					}
1305
1306					obj = $this.data('smartmenus');
1307
1308					// custom "isCollapsible" method for Bootstrap
1309					obj.isCollapsible = function() {
1310						return !/^(left|right)$/.test(this.$firstLink.parent().css('float'));
1311					};
1312
1313					// custom "refresh" method for Bootstrap
1314					obj.refresh = function() {
1315						$.SmartMenus.prototype.refresh.call(this);
1316						onInit();
1317						// update collapsible detection
1318						detectCollapsible(true);
1319					}
1320
1321					// custom "destroy" method for Bootstrap
1322					obj.destroy = function(refresh) {
1323						onBeforeDestroy();
1324						$.SmartMenus.prototype.destroy.call(this, refresh);
1325					}
1326
1327					// keep Bootstrap's default behavior for parent items when the "data-sm-skip-collapsible-behavior" attribute is set to the ul.navbar-nav
1328					// i.e. use the whole item area just as a sub menu toggle and don't customize the carets
1329					if ($this.is('[data-sm-skip-collapsible-behavior]')) {
1330						$this.bind({
1331							// click the parent item to toggle the sub menus (and reset deeper levels and other branches on click)
1332							'click.smapi': function(e, item) {
1333								if (obj.isCollapsible()) {
1334									var $item = $(item),
1335										$sub = $item.parent().dataSM('sub');
1336									if ($sub && $sub.dataSM('shown-before') && $sub.is(':visible')) {
1337										obj.itemActivate($item);
1338										obj.menuHide($sub);
1339										return false;
1340									}
1341								}
1342							}
1343						});
1344					}
1345
1346					// onresize detect when the navbar becomes collapsible and add it the "sm-collapsible" class
1347					var winW;
1348					function detectCollapsible(force) {
1349						var newW = obj.getViewportWidth();
1350						if (newW != winW || force) {
1351							var $carets = $this.find('.caret');
1352							if (obj.isCollapsible()) {
1353								$this.addClass('sm-collapsible');
1354								// set "navbar-toggle" class to carets (so they look like a button) if the "data-sm-skip-collapsible-behavior" attribute is not set to the ul.navbar-nav
1355								if (!$this.is('[data-sm-skip-collapsible-behavior]')) {
1356									$carets.addClass('navbar-toggle sub-arrow');
1357								}
1358							} else {
1359								$this.removeClass('sm-collapsible');
1360								if (!$this.is('[data-sm-skip-collapsible-behavior]')) {
1361									$carets.removeClass('navbar-toggle sub-arrow');
1362								}
1363							}
1364							winW = newW;
1365						}
1366					};
1367					detectCollapsible();
1368					$(window).bind('resize.smartmenus' + obj.rootId, detectCollapsible);
1369				}
1370			});
1371			// keydown fix for Bootstrap 3.3.5+ conflict
1372			if ($navbars.length && !$.SmartMenus.Bootstrap.keydownFix) {
1373				// unhook BS keydown handler for all dropdowns
1374				$(document).off('keydown.bs.dropdown.data-api', '.dropdown-menu');
1375				// restore BS keydown handler for dropdowns that are not inside SmartMenus navbars
1376				if ($.fn.dropdown && $.fn.dropdown.Constructor) {
1377					$(document).on('keydown.bs.dropdown.data-api', '.dropdown-menu:not([id^="sm-"])', $.fn.dropdown.Constructor.prototype.keydown);
1378				}
1379				$.SmartMenus.Bootstrap.keydownFix = true;
1380			}
1381		}
1382	});
1383
1384	// init ondomready
1385	$($.SmartMenus.Bootstrap.init);
1386
1387	return $;
1388}));;
1389/* ========================================================================
1390 * Bootstrap: affix.js v3.3.5
1391 * http://getbootstrap.com/javascript/#affix
1392 * ========================================================================
1393 * Copyright 2011-2015 Twitter, Inc.
1394 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1395 * ======================================================================== */
1396
1397
1398+function ($) {
1399  'use strict';
1400
1401  // AFFIX CLASS DEFINITION
1402  // ======================
1403
1404  var Affix = function (element, options) {
1405    this.options = $.extend({}, Affix.DEFAULTS, options)
1406
1407    this.$target = $(this.options.target)
1408      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
1409      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
1410
1411    this.$element     = $(element)
1412    this.affixed      = null
1413    this.unpin        = null
1414    this.pinnedOffset = null
1415
1416    this.checkPosition()
1417  }
1418
1419  Affix.VERSION  = '3.3.5'
1420
1421  Affix.RESET    = 'affix affix-top affix-bottom'
1422
1423  Affix.DEFAULTS = {
1424    offset: 0,
1425    target: window
1426  }
1427
1428  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
1429    var scrollTop    = this.$target.scrollTop()
1430    var position     = this.$element.offset()
1431    var targetHeight = this.$target.height()
1432
1433    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
1434
1435    if (this.affixed == 'bottom') {
1436      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
1437      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
1438    }
1439
1440    var initializing   = this.affixed == null
1441    var colliderTop    = initializing ? scrollTop : position.top
1442    var colliderHeight = initializing ? targetHeight : height
1443
1444    if (offsetTop != null && scrollTop <= offsetTop) return 'top'
1445    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
1446
1447    return false
1448  }
1449
1450  Affix.prototype.getPinnedOffset = function () {
1451    if (this.pinnedOffset) return this.pinnedOffset
1452    this.$element.removeClass(Affix.RESET).addClass('affix')
1453    var scrollTop = this.$target.scrollTop()
1454    var position  = this.$element.offset()
1455    return (this.pinnedOffset = position.top - scrollTop)
1456  }
1457
1458  Affix.prototype.checkPositionWithEventLoop = function () {
1459    setTimeout($.proxy(this.checkPosition, this), 1)
1460  }
1461
1462  Affix.prototype.checkPosition = function () {
1463    if (!this.$element.is(':visible')) return
1464
1465    var height       = this.$element.height()
1466    var offset       = this.options.offset
1467    var offsetTop    = offset.top
1468    var offsetBottom = offset.bottom
1469    var scrollHeight = Math.max($(document).height(), $(document.body).height())
1470
1471    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
1472    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
1473    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
1474
vendor: 35,367 bytes, lines 1475-2721
1475    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
1476
1477    if (this.affixed != affix) {
1478      if (this.unpin != null) this.$element.css('top', '')
1479
1480      var affixType = 'affix' + (affix ? '-' + affix : '')
1481      var e         = $.Event(affixType + '.bs.affix')
1482
1483      this.$element.trigger(e)
1484
1485      if (e.isDefaultPrevented()) return
1486
1487      this.affixed = affix
1488      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
1489
1490      this.$element
1491        .removeClass(Affix.RESET)
1492        .addClass(affixType)
1493        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
1494    }
1495
1496    if (affix == 'bottom') {
1497      this.$element.offset({
1498        top: scrollHeight - height - offsetBottom
1499      })
1500    }
1501  }
1502
1503
1504  // AFFIX PLUGIN DEFINITION
1505  // =======================
1506
1507  function Plugin(option) {
1508    return this.each(function () {
1509      var $this   = $(this)
1510      var data    = $this.data('bs.affix')
1511      var options = typeof option == 'object' && option
1512
1513      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
1514      if (typeof option == 'string') data[option]()
1515    })
1516  }
1517
1518  var old = $.fn.affix
1519
1520  $.fn.affix             = Plugin
1521  $.fn.affix.Constructor = Affix
1522
1523
1524  // AFFIX NO CONFLICT
1525  // =================
1526
1527  $.fn.affix.noConflict = function () {
1528    $.fn.affix = old
1529    return this
1530  }
1531
1532
1533  // AFFIX DATA-API
1534  // ==============
1535
1536  $(window).on('load', function () {
1537    $('[data-spy="affix"]').each(function () {
1538      var $spy = $(this)
1539      var data = $spy.data()
1540
1541      data.offset = data.offset || {}
1542
1543      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
1544      if (data.offsetTop    != null) data.offset.top    = data.offsetTop
1545
1546      Plugin.call($spy, data)
1547    })
1548  })
1549
1550}(jQuery);
1551;
1552/* ========================================================================
1553 * Bootstrap: alert.js v3.3.5
1554 * http://getbootstrap.com/javascript/#alerts
1555 * ========================================================================
1556 * Copyright 2011-2015 Twitter, Inc.
1557 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1558 * ======================================================================== */
1559
1560
1561+function ($) {
1562  'use strict';
1563
1564  // ALERT CLASS DEFINITION
1565  // ======================
1566
1567  var dismiss = '[data-dismiss="alert"]'
1568  var Alert   = function (el) {
1569    $(el).on('click', dismiss, this.close)
1570  }
1571
1572  Alert.VERSION = '3.3.5'
1573
1574  Alert.TRANSITION_DURATION = 150
1575
1576  Alert.prototype.close = function (e) {
1577    var $this    = $(this)
1578    var selector = $this.attr('data-target')
1579
1580    if (!selector) {
1581      selector = $this.attr('href')
1582      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
1583    }
1584
1585    var $parent = $(selector)
1586
1587    if (e) e.preventDefault()
1588
1589    if (!$parent.length) {
1590      $parent = $this.closest('.alert')
1591    }
1592
1593    $parent.trigger(e = $.Event('close.bs.alert'))
1594
1595    if (e.isDefaultPrevented()) return
1596
1597    $parent.removeClass('in')
1598
1599    function removeElement() {
1600      // detach from parent, fire event then clean up data
1601      $parent.detach().trigger('closed.bs.alert').remove()
1602    }
1603
1604    $.support.transition && $parent.hasClass('fade') ?
1605      $parent
1606        .one('bsTransitionEnd', removeElement)
1607        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
1608      removeElement()
1609  }
1610
1611
1612  // ALERT PLUGIN DEFINITION
1613  // =======================
1614
1615  function Plugin(option) {
1616    return this.each(function () {
1617      var $this = $(this)
1618      var data  = $this.data('bs.alert')
1619
1620      if (!data) $this.data('bs.alert', (data = new Alert(this)))
1621      if (typeof option == 'string') data[option].call($this)
1622    })
1623  }
1624
1625  var old = $.fn.alert
1626
1627  $.fn.alert             = Plugin
1628  $.fn.alert.Constructor = Alert
1629
1630
1631  // ALERT NO CONFLICT
1632  // =================
1633
1634  $.fn.alert.noConflict = function () {
1635    $.fn.alert = old
1636    return this
1637  }
1638
1639
1640  // ALERT DATA-API
1641  // ==============
1642
1643  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
1644
1645}(jQuery);
1646;
1647/* ========================================================================
1648 * Bootstrap: button.js v3.3.5
1649 * http://getbootstrap.com/javascript/#buttons
1650 * ========================================================================
1651 * Copyright 2011-2015 Twitter, Inc.
1652 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1653 * ======================================================================== */
1654
1655
1656+function ($) {
1657  'use strict';
1658
1659  // BUTTON PUBLIC CLASS DEFINITION
1660  // ==============================
1661
1662  var Button = function (element, options) {
1663    this.$element  = $(element)
1664    this.options   = $.extend({}, Button.DEFAULTS, options)
1665    this.isLoading = false
1666  }
1667
1668  Button.VERSION  = '3.3.5'
1669
1670  Button.DEFAULTS = {
1671    loadingText: 'loading...'
1672  }
1673
1674  Button.prototype.setState = function (state) {
1675    var d    = 'disabled'
1676    var $el  = this.$element
1677    var val  = $el.is('input') ? 'val' : 'html'
1678    var data = $el.data()
1679
1680    state += 'Text'
1681
1682    if (data.resetText == null) $el.data('resetText', $el[val]())
1683
1684    // push to event loop to allow forms to submit
1685    setTimeout($.proxy(function () {
1686      $el[val](data[state] == null ? this.options[state] : data[state])
1687
1688      if (state == 'loadingText') {
1689        this.isLoading = true
1690        $el.addClass(d).attr(d, d)
1691      } else if (this.isLoading) {
1692        this.isLoading = false
1693        $el.removeClass(d).removeAttr(d)
1694      }
1695    }, this), 0)
1696  }
1697
1698  Button.prototype.toggle = function () {
1699    var changed = true
1700    var $parent = this.$element.closest('[data-toggle="buttons"]')
1701
1702    if ($parent.length) {
1703      var $input = this.$element.find('input')
1704      if ($input.prop('type') == 'radio') {
1705        if ($input.prop('checked')) changed = false
1706        $parent.find('.active').removeClass('active')
1707        this.$element.addClass('active')
1708      } else if ($input.prop('type') == 'checkbox') {
1709        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
1710        this.$element.toggleClass('active')
1711      }
1712      $input.prop('checked', this.$element.hasClass('active'))
1713      if (changed) $input.trigger('change')
1714    } else {
1715      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
1716      this.$element.toggleClass('active')
1717    }
1718  }
1719
1720
1721  // BUTTON PLUGIN DEFINITION
1722  // ========================
1723
1724  function Plugin(option) {
1725    return this.each(function () {
1726      var $this   = $(this)
1727      var data    = $this.data('bs.button')
1728      var options = typeof option == 'object' && option
1729
1730      if (!data) $this.data('bs.button', (data = new Button(this, options)))
1731
1732      if (option == 'toggle') data.toggle()
1733      else if (option) data.setState(option)
1734    })
1735  }
1736
1737  var old = $.fn.button
1738
1739  $.fn.button             = Plugin
1740  $.fn.button.Constructor = Button
1741
1742
1743  // BUTTON NO CONFLICT
1744  // ==================
1745
1746  $.fn.button.noConflict = function () {
1747    $.fn.button = old
1748    return this
1749  }
1750
1751
1752  // BUTTON DATA-API
1753  // ===============
1754
1755  $(document)
1756    .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
1757      var $btn = $(e.target)
1758      if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
1759      Plugin.call($btn, 'toggle')
1760      if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
1761    })
1762    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
1763      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
1764    })
1765
1766}(jQuery);
1767;
1768/* ========================================================================
1769 * Bootstrap: carousel.js v3.3.5
1770 * http://getbootstrap.com/javascript/#carousel
1771 * ========================================================================
1772 * Copyright 2011-2015 Twitter, Inc.
1773 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1774 * ======================================================================== */
1775
1776
1777+function ($) {
1778  'use strict';
1779
1780  // CAROUSEL CLASS DEFINITION
1781  // =========================
1782
1783  var Carousel = function (element, options) {
1784    this.$element    = $(element)
1785    this.$indicators = this.$element.find('.carousel-indicators')
1786    this.options     = options
1787    this.paused      = null
1788    this.sliding     = null
1789    this.interval    = null
1790    this.$active     = null
1791    this.$items      = null
1792
1793    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
1794
1795    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
1796      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
1797      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
1798  }
1799
1800  Carousel.VERSION  = '3.3.5'
1801
1802  Carousel.TRANSITION_DURATION = 600
1803
1804  Carousel.DEFAULTS = {
1805    interval: 5000,
1806    pause: 'hover',
1807    wrap: true,
1808    keyboard: true
1809  }
1810
1811  Carousel.prototype.keydown = function (e) {
1812    if (/input|textarea/i.test(e.target.tagName)) return
1813    switch (e.which) {
1814      case 37: this.prev(); break
1815      case 39: this.next(); break
1816      default: return
1817    }
1818
1819    e.preventDefault()
1820  }
1821
1822  Carousel.prototype.cycle = function (e) {
1823    e || (this.paused = false)
1824
1825    this.interval && clearInterval(this.interval)
1826
1827    this.options.interval
1828      && !this.paused
1829      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
1830
1831    return this
1832  }
1833
1834  Carousel.prototype.getItemIndex = function (item) {
1835    this.$items = item.parent().children('.item')
1836    return this.$items.index(item || this.$active)
1837  }
1838
1839  Carousel.prototype.getItemForDirection = function (direction, active) {
1840    var activeIndex = this.getItemIndex(active)
1841    var willWrap = (direction == 'prev' && activeIndex === 0)
1842                || (direction == 'next' && activeIndex == (this.$items.length - 1))
1843    if (willWrap && !this.options.wrap) return active
1844    var delta = direction == 'prev' ? -1 : 1
1845    var itemIndex = (activeIndex + delta) % this.$items.length
1846    return this.$items.eq(itemIndex)
1847  }
1848
1849  Carousel.prototype.to = function (pos) {
1850    var that        = this
1851    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
1852
1853    if (pos > (this.$items.length - 1) || pos < 0) return
1854
1855    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
1856    if (activeIndex == pos) return this.pause().cycle()
1857
1858    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
1859  }
1860
1861  Carousel.prototype.pause = function (e) {
1862    e || (this.paused = true)
1863
1864    if (this.$element.find('.next, .prev').length && $.support.transition) {
1865      this.$element.trigger($.support.transition.end)
1866      this.cycle(true)
1867    }
1868
1869    this.interval = clearInterval(this.interval)
1870
1871    return this
1872  }
1873
1874  Carousel.prototype.next = function () {
1875    if (this.sliding) return
1876    return this.slide('next')
1877  }
1878
1879  Carousel.prototype.prev = function () {
1880    if (this.sliding) return
1881    return this.slide('prev')
1882  }
1883
1884  Carousel.prototype.slide = function (type, next) {
1885    var $active   = this.$element.find('.item.active')
1886    var $next     = next || this.getItemForDirection(type, $active)
1887    var isCycling = this.interval
1888    var direction = type == 'next' ? 'left' : 'right'
1889    var that      = this
1890
1891    if ($next.hasClass('active')) return (this.sliding = false)
1892
1893    var relatedTarget = $next[0]
1894    var slideEvent = $.Event('slide.bs.carousel', {
1895      relatedTarget: relatedTarget,
1896      direction: direction
1897    })
1898    this.$element.trigger(slideEvent)
1899    if (slideEvent.isDefaultPrevented()) return
1900
1901    this.sliding = true
1902
1903    isCycling && this.pause()
1904
1905    if (this.$indicators.length) {
1906      this.$indicators.find('.active').removeClass('active')
1907      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
1908      $nextIndicator && $nextIndicator.addClass('active')
1909    }
1910
1911    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
1912    if ($.support.transition && this.$element.hasClass('slide')) {
1913      $next.addClass(type)
1914      $next[0].offsetWidth // force reflow
1915      $active.addClass(direction)
1916      $next.addClass(direction)
1917      $active
1918        .one('bsTransitionEnd', function () {
1919          $next.removeClass([type, direction].join(' ')).addClass('active')
1920          $active.removeClass(['active', direction].join(' '))
1921          that.sliding = false
1922          setTimeout(function () {
1923            that.$element.trigger(slidEvent)
1924          }, 0)
1925        })
1926        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
1927    } else {
1928      $active.removeClass('active')
1929      $next.addClass('active')
1930      this.sliding = false
1931      this.$element.trigger(slidEvent)
1932    }
1933
1934    isCycling && this.cycle()
1935
1936    return this
1937  }
1938
1939
1940  // CAROUSEL PLUGIN DEFINITION
1941  // ==========================
1942
1943  function Plugin(option) {
1944    return this.each(function () {
1945      var $this   = $(this)
1946      var data    = $this.data('bs.carousel')
1947      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
1948      var action  = typeof option == 'string' ? option : options.slide
1949
1950      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
1951      if (typeof option == 'number') data.to(option)
1952      else if (action) data[action]()
1953      else if (options.interval) data.pause().cycle()
1954    })
1955  }
1956
1957  var old = $.fn.carousel
1958
1959  $.fn.carousel             = Plugin
1960  $.fn.carousel.Constructor = Carousel
1961
1962
1963  // CAROUSEL NO CONFLICT
1964  // ====================
1965
1966  $.fn.carousel.noConflict = function () {
1967    $.fn.carousel = old
1968    return this
1969  }
1970
1971
1972  // CAROUSEL DATA-API
1973  // =================
1974
1975  var clickHandler = function (e) {
1976    var href
1977    var $this   = $(this)
1978    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
1979    if (!$target.hasClass('carousel')) return
1980    var options = $.extend({}, $target.data(), $this.data())
1981    var slideIndex = $this.attr('data-slide-to')
1982    if (slideIndex) options.interval = false
1983
1984    Plugin.call($target, options)
1985
1986    if (slideIndex) {
1987      $target.data('bs.carousel').to(slideIndex)
1988    }
1989
1990    e.preventDefault()
1991  }
1992
1993  $(document)
1994    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
1995    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
1996
1997  $(window).on('load', function () {
1998    $('[data-ride="carousel"]').each(function () {
1999      var $carousel = $(this)
2000      Plugin.call($carousel, $carousel.data())
2001    })
2002  })
2003
2004}(jQuery);
2005;
2006/* ========================================================================
2007 * Bootstrap: collapse.js v3.3.5
2008 * http://getbootstrap.com/javascript/#collapse
2009 * ========================================================================
2010 * Copyright 2011-2015 Twitter, Inc.
2011 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2012 * ======================================================================== */
2013
2014
2015+function ($) {
2016  'use strict';
2017
2018  // COLLAPSE PUBLIC CLASS DEFINITION
2019  // ================================
2020
2021  var Collapse = function (element, options) {
2022    this.$element      = $(element)
2023    this.options       = $.extend({}, Collapse.DEFAULTS, options)
2024    this.$trigger      = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
2025                           '[data-toggle="collapse"][data-target="#' + element.id + '"]')
2026    this.transitioning = null
2027
2028    if (this.options.parent) {
2029      this.$parent = this.getParent()
2030    } else {
2031      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
2032    }
2033
2034    if (this.options.toggle) this.toggle()
2035  }
2036
2037  Collapse.VERSION  = '3.3.5'
2038
2039  Collapse.TRANSITION_DURATION = 350
2040
2041  Collapse.DEFAULTS = {
2042    toggle: true
2043  }
2044
2045  Collapse.prototype.dimension = function () {
2046    var hasWidth = this.$element.hasClass('width')
2047    return hasWidth ? 'width' : 'height'
2048  }
2049
2050  Collapse.prototype.show = function () {
2051    if (this.transitioning || this.$element.hasClass('in')) return
2052
2053    var activesData
2054    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
2055
2056    if (actives && actives.length) {
2057      activesData = actives.data('bs.collapse')
2058      if (activesData && activesData.transitioning) return
2059    }
2060
2061    var startEvent = $.Event('show.bs.collapse')
2062    this.$element.trigger(startEvent)
2063    if (startEvent.isDefaultPrevented()) return
2064
2065    if (actives && actives.length) {
2066      Plugin.call(actives, 'hide')
2067      activesData || actives.data('bs.collapse', null)
2068    }
2069
2070    var dimension = this.dimension()
2071
2072    this.$element
2073      .removeClass('collapse')
2074      .addClass('collapsing')[dimension](0)
2075      .attr('aria-expanded', true)
2076
2077    this.$trigger
2078      .removeClass('collapsed')
2079      .attr('aria-expanded', true)
2080
2081    this.transitioning = 1
2082
2083    var complete = function () {
2084      this.$element
2085        .removeClass('collapsing')
2086        .addClass('collapse in')[dimension]('')
2087      this.transitioning = 0
2088      this.$element
2089        .trigger('shown.bs.collapse')
2090    }
2091
2092    if (!$.support.transition) return complete.call(this)
2093
2094    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
2095
2096    this.$element
2097      .one('bsTransitionEnd', $.proxy(complete, this))
2098      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
2099  }
2100
2101  Collapse.prototype.hide = function () {
2102    if (this.transitioning || !this.$element.hasClass('in')) return
2103
2104    var startEvent = $.Event('hide.bs.collapse')
2105    this.$element.trigger(startEvent)
2106    if (startEvent.isDefaultPrevented()) return
2107
2108    var dimension = this.dimension()
2109
2110    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
2111
2112    this.$element
2113      .addClass('collapsing')
2114      .removeClass('collapse in')
2115      .attr('aria-expanded', false)
2116
2117    this.$trigger
2118      .addClass('collapsed')
2119      .attr('aria-expanded', false)
2120
2121    this.transitioning = 1
2122
2123    var complete = function () {
2124      this.transitioning = 0
2125      this.$element
2126        .removeClass('collapsing')
2127        .addClass('collapse')
2128        .trigger('hidden.bs.collapse')
2129    }
2130
2131    if (!$.support.transition) return complete.call(this)
2132
2133    this.$element
2134      [dimension](0)
2135      .one('bsTransitionEnd', $.proxy(complete, this))
2136      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
2137  }
2138
2139  Collapse.prototype.toggle = function () {
2140    this[this.$element.hasClass('in') ? 'hide' : 'show']()
2141  }
2142
2143  Collapse.prototype.getParent = function () {
2144    return $(this.options.parent)
2145      .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
2146      .each($.proxy(function (i, element) {
2147        var $element = $(element)
2148        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
2149      }, this))
2150      .end()
2151  }
2152
2153  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
2154    var isOpen = $element.hasClass('in')
2155
2156    $element.attr('aria-expanded', isOpen)
2157    $trigger
2158      .toggleClass('collapsed', !isOpen)
2159      .attr('aria-expanded', isOpen)
2160  }
2161
2162  function getTargetFromTrigger($trigger) {
2163    var href
2164    var target = $trigger.attr('data-target')
2165      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
2166
2167    return $(target)
2168  }
2169
2170
2171  // COLLAPSE PLUGIN DEFINITION
2172  // ==========================
2173
2174  function Plugin(option) {
2175    return this.each(function () {
2176      var $this   = $(this)
2177      var data    = $this.data('bs.collapse')
2178      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
2179
2180      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
2181      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
2182      if (typeof option == 'string') data[option]()
2183    })
2184  }
2185
2186  var old = $.fn.collapse
2187
2188  $.fn.collapse             = Plugin
2189  $.fn.collapse.Constructor = Collapse
2190
2191
2192  // COLLAPSE NO CONFLICT
2193  // ====================
2194
2195  $.fn.collapse.noConflict = function () {
2196    $.fn.collapse = old
2197    return this
2198  }
2199
2200
2201  // COLLAPSE DATA-API
2202  // =================
2203
2204  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
2205    var $this   = $(this)
2206
2207    if (!$this.attr('data-target')) e.preventDefault()
2208
2209    var $target = getTargetFromTrigger($this)
2210    var data    = $target.data('bs.collapse')
2211    var option  = data ? 'toggle' : $this.data()
2212
2213    Plugin.call($target, option)
2214  })
2215
2216}(jQuery);
2217;
2218/* ========================================================================
2219 * Bootstrap: dropdown.js v3.3.5
2220 * http://getbootstrap.com/javascript/#dropdowns
2221 * ========================================================================
2222 * Copyright 2011-2015 Twitter, Inc.
2223 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2224 * ======================================================================== */
2225
2226
2227+function ($) {
2228  'use strict';
2229
2230  // DROPDOWN CLASS DEFINITION
2231  // =========================
2232
2233  var backdrop = '.dropdown-backdrop'
2234  var toggle   = '[data-toggle="dropdown"]'
2235  var Dropdown = function (element) {
2236    $(element).on('click.bs.dropdown', this.toggle)
2237  }
2238
2239  Dropdown.VERSION = '3.3.5'
2240
2241  function getParent($this) {
2242    var selector = $this.attr('data-target')
2243
2244    if (!selector) {
2245      selector = $this.attr('href')
2246      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
2247    }
2248
2249    var $parent = selector && $(selector)
2250
2251    return $parent && $parent.length ? $parent : $this.parent()
2252  }
2253
2254  function clearMenus(e) {
2255    if (e && e.which === 3) return
2256    $(backdrop).remove()
2257    $(toggle).each(function () {
2258      var $this         = $(this)
2259      var $parent       = getParent($this)
2260      var relatedTarget = { relatedTarget: this }
2261
2262      if (!$parent.hasClass('open')) return
2263
2264      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
2265
2266      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
2267
2268      if (e.isDefaultPrevented()) return
2269
2270      $this.attr('aria-expanded', 'false')
2271      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
2272    })
2273  }
2274
2275  Dropdown.prototype.toggle = function (e) {
2276    var $this = $(this)
2277
2278    if ($this.is('.disabled, :disabled')) return
2279
2280    var $parent  = getParent($this)
2281    var isActive = $parent.hasClass('open')
2282
2283    clearMenus()
2284
2285    if (!isActive) {
2286      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
2287        // if mobile we use a backdrop because click events don't delegate
2288        $(document.createElement('div'))
2289          .addClass('dropdown-backdrop')
2290          .insertAfter($(this))
2291          .on('click', clearMenus)
2292      }
2293
2294      var relatedTarget = { relatedTarget: this }
2295      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
2296
2297      if (e.isDefaultPrevented()) return
2298
2299      $this
2300        .trigger('focus')
2301        .attr('aria-expanded', 'true')
2302
2303      $parent
2304        .toggleClass('open')
2305        .trigger('shown.bs.dropdown', relatedTarget)
2306    }
2307
2308    return false
2309  }
2310
2311  Dropdown.prototype.keydown = function (e) {
2312    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
2313
2314    var $this = $(this)
2315
2316    e.preventDefault()
2317    e.stopPropagation()
2318
2319    if ($this.is('.disabled, :disabled')) return
2320
2321    var $parent  = getParent($this)
2322    var isActive = $parent.hasClass('open')
2323
2324    if (!isActive && e.which != 27 || isActive && e.which == 27) {
2325      if (e.which == 27) $parent.find(toggle).trigger('focus')
2326      return $this.trigger('click')
2327    }
2328
2329    var desc = ' li:not(.disabled):visible a'
2330    var $items = $parent.find('.dropdown-menu' + desc)
2331
2332    if (!$items.length) return
2333
2334    var index = $items.index(e.target)
2335
2336    if (e.which == 38 && index > 0)                 index--         // up
2337    if (e.which == 40 && index < $items.length - 1) index++         // down
2338    if (!~index)                                    index = 0
2339
2340    $items.eq(index).trigger('focus')
2341  }
2342
2343
2344  // DROPDOWN PLUGIN DEFINITION
2345  // ==========================
2346
2347  function Plugin(option) {
2348    return this.each(function () {
2349      var $this = $(this)
2350      var data  = $this.data('bs.dropdown')
2351
2352      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
2353      if (typeof option == 'string') data[option].call($this)
2354    })
2355  }
2356
2357  var old = $.fn.dropdown
2358
2359  $.fn.dropdown             = Plugin
2360  $.fn.dropdown.Constructor = Dropdown
2361
2362
2363  // DROPDOWN NO CONFLICT
2364  // ====================
2365
2366  $.fn.dropdown.noConflict = function () {
2367    $.fn.dropdown = old
2368    return this
2369  }
2370
2371
2372  // APPLY TO STANDARD DROPDOWN ELEMENTS
2373  // ===================================
2374
2375  $(document)
2376    .on('click.bs.dropdown.data-api', clearMenus)
2377    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
2378    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
2379    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
2380    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
2381
2382}(jQuery);
2383;
2384/* ========================================================================
2385 * Bootstrap: modal.js v3.3.5
2386 * http://getbootstrap.com/javascript/#modals
2387 * ========================================================================
2388 * Copyright 2011-2015 Twitter, Inc.
2389 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2390 * ======================================================================== */
2391
2392
2393+function ($) {
2394  'use strict';
2395
2396  // MODAL CLASS DEFINITION
2397  // ======================
2398
2399  var Modal = function (element, options) {
2400    this.options             = options
2401    this.$body               = $(document.body)
2402    this.$element            = $(element)
2403    this.$dialog             = this.$element.find('.modal-dialog')
2404    this.$backdrop           = null
2405    this.isShown             = null
2406    this.originalBodyPad     = null
2407    this.scrollbarWidth      = 0
2408    this.ignoreBackdropClick = false
2409
2410    if (this.options.remote) {
2411      this.$element
2412        .find('.modal-content')
2413        .load(this.options.remote, $.proxy(function () {
2414          this.$element.trigger('loaded.bs.modal')
2415        }, this))
2416    }
2417  }
2418
2419  Modal.VERSION  = '3.3.5'
2420
2421  Modal.TRANSITION_DURATION = 300
2422  Modal.BACKDROP_TRANSITION_DURATION = 150
2423
2424  Modal.DEFAULTS = {
2425    backdrop: true,
2426    keyboard: true,
2427    show: true
2428  }
2429
2430  Modal.prototype.toggle = function (_relatedTarget) {
2431    return this.isShown ? this.hide() : this.show(_relatedTarget)
2432  }
2433
2434  Modal.prototype.show = function (_relatedTarget) {
2435    var that = this
2436    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
2437
2438    this.$element.trigger(e)
2439
2440    if (this.isShown || e.isDefaultPrevented()) return
2441
2442    this.isShown = true
2443
2444    this.checkScrollbar()
2445    this.setScrollbar()
2446    this.$body.addClass('modal-open')
2447
2448    this.escape()
2449    this.resize()
2450
2451    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
2452
2453    this.$dialog.on('mousedown.dismiss.bs.modal', function () {
2454      that.$element.one('mouseup.dismiss.bs.modal', function (e) {
2455        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
2456      })
2457    })
2458
2459    this.backdrop(function () {
2460      var transition = $.support.transition && that.$element.hasClass('fade')
2461
2462      if (!that.$element.parent().length) {
2463        that.$element.appendTo(that.$body) // don't move modals dom position
2464      }
2465
2466      that.$element
2467        .show()
2468        .scrollTop(0)
2469
2470      that.adjustDialog()
2471
2472      if (transition) {
2473        that.$element[0].offsetWidth // force reflow
2474      }
2475
2476      that.$element.addClass('in')
2477
2478      that.enforceFocus()
2479
2480      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
2481
2482      transition ?
2483        that.$dialog // wait for modal to slide in
2484          .one('bsTransitionEnd', function () {
2485            that.$element.trigger('focus').trigger(e)
2486          })
2487          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
2488        that.$element.trigger('focus').trigger(e)
2489    })
2490  }
2491
2492  Modal.prototype.hide = function (e) {
2493    if (e) e.preventDefault()
2494
2495    e = $.Event('hide.bs.modal')
2496
2497    this.$element.trigger(e)
2498
2499    if (!this.isShown || e.isDefaultPrevented()) return
2500
2501    this.isShown = false
2502
2503    this.escape()
2504    this.resize()
2505
2506    $(document).off('focusin.bs.modal')
2507
2508    this.$element
2509      .removeClass('in')
2510      .off('click.dismiss.bs.modal')
2511      .off('mouseup.dismiss.bs.modal')
2512
2513    this.$dialog.off('mousedown.dismiss.bs.modal')
2514
2515    $.support.transition && this.$element.hasClass('fade') ?
2516      this.$element
2517        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
2518        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
2519      this.hideModal()
2520  }
2521
2522  Modal.prototype.enforceFocus = function () {
2523    $(document)
2524      .off('focusin.bs.modal') // guard against infinite focus loop
2525      .on('focusin.bs.modal', $.proxy(function (e) {
2526        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
2527          this.$element.trigger('focus')
2528        }
2529      }, this))
2530  }
2531
2532  Modal.prototype.escape = function () {
2533    if (this.isShown && this.options.keyboard) {
2534      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
2535        e.which == 27 && this.hide()
2536      }, this))
2537    } else if (!this.isShown) {
2538      this.$element.off('keydown.dismiss.bs.modal')
2539    }
2540  }
2541
2542  Modal.prototype.resize = function () {
2543    if (this.isShown) {
2544      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
2545    } else {
2546      $(window).off('resize.bs.modal')
2547    }
2548  }
2549
2550  Modal.prototype.hideModal = function () {
2551    var that = this
2552    this.$element.hide()
2553    this.backdrop(function () {
2554      that.$body.removeClass('modal-open')
2555      that.resetAdjustments()
2556      that.resetScrollbar()
2557      that.$element.trigger('hidden.bs.modal')
2558    })
2559  }
2560
2561  Modal.prototype.removeBackdrop = function () {
2562    this.$backdrop && this.$backdrop.remove()
2563    this.$backdrop = null
2564  }
2565
2566  Modal.prototype.backdrop = function (callback) {
2567    var that = this
2568    var animate = this.$element.hasClass('fade') ? 'fade' : ''
2569
2570    if (this.isShown && this.options.backdrop) {
2571      var doAnimate = $.support.transition && animate
2572
2573      this.$backdrop = $(document.createElement('div'))
2574        .addClass('modal-backdrop ' + animate)
2575        .appendTo(this.$body)
2576
2577      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
2578        if (this.ignoreBackdropClick) {
2579          this.ignoreBackdropClick = false
2580          return
2581        }
2582        if (e.target !== e.currentTarget) return
2583        this.options.backdrop == 'static'
2584          ? this.$element[0].focus()
2585          : this.hide()
2586      }, this))
2587
2588      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
2589
2590      this.$backdrop.addClass('in')
2591
2592      if (!callback) return
2593
2594      doAnimate ?
2595        this.$backdrop
2596          .one('bsTransitionEnd', callback)
2597          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
2598        callback()
2599
2600    } else if (!this.isShown && this.$backdrop) {
2601      this.$backdrop.removeClass('in')
2602
2603      var callbackRemove = function () {
2604        that.removeBackdrop()
2605        callback && callback()
2606      }
2607      $.support.transition && this.$element.hasClass('fade') ?
2608        this.$backdrop
2609          .one('bsTransitionEnd', callbackRemove)
2610          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
2611        callbackRemove()
2612
2613    } else if (callback) {
2614      callback()
2615    }
2616  }
2617
2618  // these following methods are used to handle overflowing modals
2619
2620  Modal.prototype.handleUpdate = function () {
2621    this.adjustDialog()
2622  }
2623
2624  Modal.prototype.adjustDialog = function () {
2625    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
2626
2627    this.$element.css({
2628      paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
2629      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
2630    })
2631  }
2632
2633  Modal.prototype.resetAdjustments = function () {
2634    this.$element.css({
2635      paddingLeft: '',
2636      paddingRight: ''
2637    })
2638  }
2639
2640  Modal.prototype.checkScrollbar = function () {
2641    var fullWindowWidth = window.innerWidth
2642    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
2643      var documentElementRect = document.documentElement.getBoundingClientRect()
2644      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
2645    }
2646    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
2647    this.scrollbarWidth = this.measureScrollbar()
2648  }
2649
2650  Modal.prototype.setScrollbar = function () {
2651    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
2652    this.originalBodyPad = document.body.style.paddingRight || ''
2653    if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
2654  }
2655
2656  Modal.prototype.resetScrollbar = function () {
2657    this.$body.css('padding-right', this.originalBodyPad)
2658  }
2659
2660  Modal.prototype.measureScrollbar = function () { // thx walsh
2661    var scrollDiv = document.createElement('div')
2662    scrollDiv.className = 'modal-scrollbar-measure'
2663    this.$body.append(scrollDiv)
2664    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
2665    this.$body[0].removeChild(scrollDiv)
2666    return scrollbarWidth
2667  }
2668
2669
2670  // MODAL PLUGIN DEFINITION
2671  // =======================
2672
2673  function Plugin(option, _relatedTarget) {
2674    return this.each(function () {
2675      var $this   = $(this)
2676      var data    = $this.data('bs.modal')
2677      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
2678
2679      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
2680      if (typeof option == 'string') data[option](_relatedTarget)
2681      else if (options.show) data.show(_relatedTarget)
2682    })
2683  }
2684
2685  var old = $.fn.modal
2686
2687  $.fn.modal             = Plugin
2688  $.fn.modal.Constructor = Modal
2689
2690
2691  // MODAL NO CONFLICT
2692  // =================
2693
2694  $.fn.modal.noConflict = function () {
2695    $.fn.modal = old
2696    return this
2697  }
2698
2699
2700  // MODAL DATA-API
2701  // ==============
2702
2703  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
2704    var $this   = $(this)
2705    var href    = $this.attr('href')
2706    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
2707    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
2708
2709    if ($this.is('a')) e.preventDefault()
2710
2711    $target.one('show.bs.modal', function (showEvent) {
2712      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
2713      $target.one('hidden.bs.modal', function () {
2714        $this.is(':visible') && $this.trigger('focus')
2715      })
2716    })
2717    Plugin.call($target, option, this)
2718  })
2719
2720}(jQuery);
2721;
vendor: 16,346 bytes, lines 2721-3235
2721
2722/* ========================================================================
2723 * Bootstrap: tooltip.js v3.3.5
2724 * http://getbootstrap.com/javascript/#tooltip
2725 * Inspired by the original jQuery.tipsy by Jason Frame
2726 * ========================================================================
2727 * Copyright 2011-2015 Twitter, Inc.
2728 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2729 * ======================================================================== */
2730
2731
2732+function ($) {
2733  'use strict';
2734
2735  // TOOLTIP PUBLIC CLASS DEFINITION
2736  // ===============================
2737
2738  var Tooltip = function (element, options) {
2739    this.type       = null
2740    this.options    = null
2741    this.enabled    = null
2742    this.timeout    = null
2743    this.hoverState = null
2744    this.$element   = null
2745    this.inState    = null
2746
2747    this.init('tooltip', element, options)
2748  }
2749
2750  Tooltip.VERSION  = '3.3.5'
2751
2752  Tooltip.TRANSITION_DURATION = 150
2753
2754  Tooltip.DEFAULTS = {
2755    animation: true,
2756    placement: 'top',
2757    selector: false,
2758    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
2759    trigger: 'hover focus',
2760    title: '',
2761    delay: 0,
2762    html: false,
2763    container: false,
2764    viewport: {
2765      selector: 'body',
2766      padding: 0
2767    }
2768  }
2769
2770  Tooltip.prototype.init = function (type, element, options) {
2771    this.enabled   = true
2772    this.type      = type
2773    this.$element  = $(element)
2774    this.options   = this.getOptions(options)
2775    this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
2776    this.inState   = { click: false, hover: false, focus: false }
2777
2778    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
2779      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
2780    }
2781
2782    var triggers = this.options.trigger.split(' ')
2783
2784    for (var i = triggers.length; i--;) {
2785      var trigger = triggers[i]
2786
2787      if (trigger == 'click') {
2788        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
2789      } else if (trigger != 'manual') {
2790        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
2791        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
2792
2793        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
2794        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
2795      }
2796    }
2797
2798    this.options.selector ?
2799      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
2800      this.fixTitle()
2801  }
2802
2803  Tooltip.prototype.getDefaults = function () {
2804    return Tooltip.DEFAULTS
2805  }
2806
2807  Tooltip.prototype.getOptions = function (options) {
2808    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
2809
2810    if (options.delay && typeof options.delay == 'number') {
2811      options.delay = {
2812        show: options.delay,
2813        hide: options.delay
2814      }
2815    }
2816
2817    return options
2818  }
2819
2820  Tooltip.prototype.getDelegateOptions = function () {
2821    var options  = {}
2822    var defaults = this.getDefaults()
2823
2824    this._options && $.each(this._options, function (key, value) {
2825      if (defaults[key] != value) options[key] = value
2826    })
2827
2828    return options
2829  }
2830
2831  Tooltip.prototype.enter = function (obj) {
2832    var self = obj instanceof this.constructor ?
2833      obj : $(obj.currentTarget).data('bs.' + this.type)
2834
2835    if (!self) {
2836      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
2837      $(obj.currentTarget).data('bs.' + this.type, self)
2838    }
2839
2840    if (obj instanceof $.Event) {
2841      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
2842    }
2843
2844    if (self.tip().hasClass('in') || self.hoverState == 'in') {
2845      self.hoverState = 'in'
2846      return
2847    }
2848
2849    clearTimeout(self.timeout)
2850
2851    self.hoverState = 'in'
2852
2853    if (!self.options.delay || !self.options.delay.show) return self.show()
2854
2855    self.timeout = setTimeout(function () {
2856      if (self.hoverState == 'in') self.show()
2857    }, self.options.delay.show)
2858  }
2859
2860  Tooltip.prototype.isInStateTrue = function () {
2861    for (var key in this.inState) {
2862      if (this.inState[key]) return true
2863    }
2864
2865    return false
2866  }
2867
2868  Tooltip.prototype.leave = function (obj) {
2869    var self = obj instanceof this.constructor ?
2870      obj : $(obj.currentTarget).data('bs.' + this.type)
2871
2872    if (!self) {
2873      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
2874      $(obj.currentTarget).data('bs.' + this.type, self)
2875    }
2876
2877    if (obj instanceof $.Event) {
2878      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
2879    }
2880
2881    if (self.isInStateTrue()) return
2882
2883    clearTimeout(self.timeout)
2884
2885    self.hoverState = 'out'
2886
2887    if (!self.options.delay || !self.options.delay.hide) return self.hide()
2888
2889    self.timeout = setTimeout(function () {
2890      if (self.hoverState == 'out') self.hide()
2891    }, self.options.delay.hide)
2892  }
2893
2894  Tooltip.prototype.show = function () {
2895    var e = $.Event('show.bs.' + this.type)
2896
2897    if (this.hasContent() && this.enabled) {
2898      this.$element.trigger(e)
2899
2900      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
2901      if (e.isDefaultPrevented() || !inDom) return
2902      var that = this
2903
2904      var $tip = this.tip()
2905
2906      var tipId = this.getUID(this.type)
2907
2908      this.setContent()
2909      $tip.attr('id', tipId)
2910      this.$element.attr('aria-describedby', tipId)
2911
2912      if (this.options.animation) $tip.addClass('fade')
2913
2914      var placement = typeof this.options.placement == 'function' ?
2915        this.options.placement.call(this, $tip[0], this.$element[0]) :
2916        this.options.placement
2917
2918      var autoToken = /\s?auto?\s?/i
2919      var autoPlace = autoToken.test(placement)
2920      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
2921
2922      $tip
2923        .detach()
2924        .css({ top: 0, left: 0, display: 'block' })
2925        .addClass(placement)
2926        .data('bs.' + this.type, this)
2927
2928      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
2929      this.$element.trigger('inserted.bs.' + this.type)
2930
2931      var pos          = this.getPosition()
2932      var actualWidth  = $tip[0].offsetWidth
2933      var actualHeight = $tip[0].offsetHeight
2934
2935      if (autoPlace) {
2936        var orgPlacement = placement
2937        var viewportDim = this.getPosition(this.$viewport)
2938
2939        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :
2940                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :
2941                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :
2942                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :
2943                    placement
2944
2945        $tip
2946          .removeClass(orgPlacement)
2947          .addClass(placement)
2948      }
2949
2950      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
2951
2952      this.applyPlacement(calculatedOffset, placement)
2953
2954      var complete = function () {
2955        var prevHoverState = that.hoverState
2956        that.$element.trigger('shown.bs.' + that.type)
2957        that.hoverState = null
2958
2959        if (prevHoverState == 'out') that.leave(that)
2960      }
2961
2962      $.support.transition && this.$tip.hasClass('fade') ?
2963        $tip
2964          .one('bsTransitionEnd', complete)
2965          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
2966        complete()
2967    }
2968  }
2969
2970  Tooltip.prototype.applyPlacement = function (offset, placement) {
2971    var $tip   = this.tip()
2972    var width  = $tip[0].offsetWidth
2973    var height = $tip[0].offsetHeight
2974
2975    // manually read margins because getBoundingClientRect includes difference
2976    var marginTop = parseInt($tip.css('margin-top'), 10)
2977    var marginLeft = parseInt($tip.css('margin-left'), 10)
2978
2979    // we must check for NaN for ie 8/9
2980    if (isNaN(marginTop))  marginTop  = 0
2981    if (isNaN(marginLeft)) marginLeft = 0
2982
2983    offset.top  += marginTop
2984    offset.left += marginLeft
2985
2986    // $.fn.offset doesn't round pixel values
2987    // so we use setOffset directly with our own function B-0
2988    $.offset.setOffset($tip[0], $.extend({
2989      using: function (props) {
2990        $tip.css({
2991          top: Math.round(props.top),
2992          left: Math.round(props.left)
2993        })
2994      }
2995    }, offset), 0)
2996
2997    $tip.addClass('in')
2998
2999    // check to see if placing tip in new offset caused the tip to resize itself
3000    var actualWidth  = $tip[0].offsetWidth
3001    var actualHeight = $tip[0].offsetHeight
3002
3003    if (placement == 'top' && actualHeight != height) {
3004      offset.top = offset.top + height - actualHeight
3005    }
3006
3007    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
3008
3009    if (delta.left) offset.left += delta.left
3010    else offset.top += delta.top
3011
3012    var isVertical          = /top|bottom/.test(placement)
3013    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
3014    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
3015
3016    $tip.offset(offset)
3017    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
3018  }
3019
3020  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
3021    this.arrow()
3022      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
3023      .css(isVertical ? 'top' : 'left', '')
3024  }
3025
3026  Tooltip.prototype.setContent = function () {
3027    var $tip  = this.tip()
3028    var title = this.getTitle()
3029
3030    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
3031    $tip.removeClass('fade in top bottom left right')
3032  }
3033
3034  Tooltip.prototype.hide = function (callback) {
3035    var that = this
3036    var $tip = $(this.$tip)
3037    var e    = $.Event('hide.bs.' + this.type)
3038
3039    function complete() {
3040      if (that.hoverState != 'in') $tip.detach()
3041      that.$element
3042        .removeAttr('aria-describedby')
3043        .trigger('hidden.bs.' + that.type)
3044      callback && callback()
3045    }
3046
3047    this.$element.trigger(e)
3048
3049    if (e.isDefaultPrevented()) return
3050
3051    $tip.removeClass('in')
3052
3053    $.support.transition && $tip.hasClass('fade') ?
3054      $tip
3055        .one('bsTransitionEnd', complete)
3056        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
3057      complete()
3058
3059    this.hoverState = null
3060
3061    return this
3062  }
3063
3064  Tooltip.prototype.fixTitle = function () {
3065    var $e = this.$element
3066    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
3067      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
3068    }
3069  }
3070
3071  Tooltip.prototype.hasContent = function () {
3072    return this.getTitle()
3073  }
3074
3075  Tooltip.prototype.getPosition = function ($element) {
3076    $element   = $element || this.$element
3077
3078    var el     = $element[0]
3079    var isBody = el.tagName == 'BODY'
3080
3081    var elRect    = el.getBoundingClientRect()
3082    if (elRect.width == null) {
3083      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
3084      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
3085    }
3086    var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()
3087    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
3088    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
3089
3090    return $.extend({}, elRect, scroll, outerDims, elOffset)
3091  }
3092
3093  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
3094    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
3095           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
3096           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
3097        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
3098
3099  }
3100
3101  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
3102    var delta = { top: 0, left: 0 }
3103    if (!this.$viewport) return delta
3104
3105    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
3106    var viewportDimensions = this.getPosition(this.$viewport)
3107
3108    if (/right|left/.test(placement)) {
3109      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
3110      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
3111      if (topEdgeOffset < viewportDimensions.top) { // top overflow
3112        delta.top = viewportDimensions.top - topEdgeOffset
3113      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
3114        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
3115      }
3116    } else {
3117      var leftEdgeOffset  = pos.left - viewportPadding
3118      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
3119      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
3120        delta.left = viewportDimensions.left - leftEdgeOffset
3121      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
3122        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
3123      }
3124    }
3125
3126    return delta
3127  }
3128
3129  Tooltip.prototype.getTitle = function () {
3130    var title
3131    var $e = this.$element
3132    var o  = this.options
3133
3134    title = $e.attr('data-original-title')
3135      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
3136
3137    return title
3138  }
3139
3140  Tooltip.prototype.getUID = function (prefix) {
3141    do prefix += ~~(Math.random() * 1000000)
3142    while (document.getElementById(prefix))
3143    return prefix
3144  }
3145
3146  Tooltip.prototype.tip = function () {
3147    if (!this.$tip) {
3148      this.$tip = $(this.options.template)
3149      if (this.$tip.length != 1) {
3150        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
3151      }
3152    }
3153    return this.$tip
3154  }
3155
3156  Tooltip.prototype.arrow = function () {
3157    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
3158  }
3159
3160  Tooltip.prototype.enable = function () {
3161    this.enabled = true
3162  }
3163
3164  Tooltip.prototype.disable = function () {
3165    this.enabled = false
3166  }
3167
3168  Tooltip.prototype.toggleEnabled = function () {
3169    this.enabled = !this.enabled
3170  }
3171
3172  Tooltip.prototype.toggle = function (e) {
3173    var self = this
3174    if (e) {
3175      self = $(e.currentTarget).data('bs.' + this.type)
3176      if (!self) {
3177        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
3178        $(e.currentTarget).data('bs.' + this.type, self)
3179      }
3180    }
3181
3182    if (e) {
3183      self.inState.click = !self.inState.click
3184      if (self.isInStateTrue()) self.enter(self)
3185      else self.leave(self)
3186    } else {
3187      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
3188    }
3189  }
3190
3191  Tooltip.prototype.destroy = function () {
3192    var that = this
3193    clearTimeout(this.timeout)
3194    this.hide(function () {
3195      that.$element.off('.' + that.type).removeData('bs.' + that.type)
3196      if (that.$tip) {
3197        that.$tip.detach()
3198      }
3199      that.$tip = null
3200      that.$arrow = null
3201      that.$viewport = null
3202    })
3203  }
3204
3205
3206  // TOOLTIP PLUGIN DEFINITION
3207  // =========================
3208
3209  function Plugin(option) {
3210    return this.each(function () {
3211      var $this   = $(this)
3212      var data    = $this.data('bs.tooltip')
3213      var options = typeof option == 'object' && option
3214
3215      if (!data && /destroy|hide/.test(option)) return
3216      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
3217      if (typeof option == 'string') data[option]()
3218    })
3219  }
3220
3221  var old = $.fn.tooltip
3222
3223  $.fn.tooltip             = Plugin
3224  $.fn.tooltip.Constructor = Tooltip
3225
3226
3227  // TOOLTIP NO CONFLICT
3228  // ===================
3229
3230  $.fn.tooltip.noConflict = function () {
3231    $.fn.tooltip = old
3232    return this
3233  }
3234
3235}(jQuery);
vendor: 12,250 bytes, lines 3236-3686
3236;
3237/* ========================================================================
3238 * Bootstrap: popover.js v3.3.5
3239 * http://getbootstrap.com/javascript/#popovers
3240 * ========================================================================
3241 * Copyright 2011-2015 Twitter, Inc.
3242 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
3243 * ======================================================================== */
3244
3245
3246+function ($) {
3247  'use strict';
3248
3249  // POPOVER PUBLIC CLASS DEFINITION
3250  // ===============================
3251
3252  var Popover = function (element, options) {
3253    this.init('popover', element, options)
3254  }
3255
3256  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
3257
3258  Popover.VERSION  = '3.3.5'
3259
3260  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
3261    placement: 'right',
3262    trigger: 'click',
3263    content: '',
3264    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
3265  })
3266
3267
3268  // NOTE: POPOVER EXTENDS tooltip.js
3269  // ================================
3270
3271  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
3272
3273  Popover.prototype.constructor = Popover
3274
3275  Popover.prototype.getDefaults = function () {
3276    return Popover.DEFAULTS
3277  }
3278
3279  Popover.prototype.setContent = function () {
3280    var $tip    = this.tip()
3281    var title   = this.getTitle()
3282    var content = this.getContent()
3283
3284    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
3285    $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
3286      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
3287    ](content)
3288
3289    $tip.removeClass('fade top bottom left right in')
3290
3291    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
3292    // this manually by checking the contents.
3293    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
3294  }
3295
3296  Popover.prototype.hasContent = function () {
3297    return this.getTitle() || this.getContent()
3298  }
3299
3300  Popover.prototype.getContent = function () {
3301    var $e = this.$element
3302    var o  = this.options
3303
3304    return $e.attr('data-content')
3305      || (typeof o.content == 'function' ?
3306            o.content.call($e[0]) :
3307            o.content)
3308  }
3309
3310  Popover.prototype.arrow = function () {
3311    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
3312  }
3313
3314
3315  // POPOVER PLUGIN DEFINITION
3316  // =========================
3317
3318  function Plugin(option) {
3319    return this.each(function () {
3320      var $this   = $(this)
3321      var data    = $this.data('bs.popover')
3322      var options = typeof option == 'object' && option
3323
3324      if (!data && /destroy|hide/.test(option)) return
3325      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
3326      if (typeof option == 'string') data[option]()
3327    })
3328  }
3329
3330  var old = $.fn.popover
3331
3332  $.fn.popover             = Plugin
3333  $.fn.popover.Constructor = Popover
3334
3335
3336  // POPOVER NO CONFLICT
3337  // ===================
3338
3339  $.fn.popover.noConflict = function () {
3340    $.fn.popover = old
3341    return this
3342  }
3343
3344}(jQuery);
3345;
3346/* ========================================================================
3347 * Bootstrap: scrollspy.js v3.3.5
3348 * http://getbootstrap.com/javascript/#scrollspy
3349 * ========================================================================
3350 * Copyright 2011-2015 Twitter, Inc.
3351 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
3352 * ======================================================================== */
3353
3354
3355+function ($) {
3356  'use strict';
3357
3358  // SCROLLSPY CLASS DEFINITION
3359  // ==========================
3360
3361  function ScrollSpy(element, options) {
3362    this.$body          = $(document.body)
3363    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
3364    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
3365    this.selector       = (this.options.target || '') + ' .nav li > a'
3366    this.offsets        = []
3367    this.targets        = []
3368    this.activeTarget   = null
3369    this.scrollHeight   = 0
3370
3371    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
3372    this.refresh()
3373    this.process()
3374  }
3375
3376  ScrollSpy.VERSION  = '3.3.5'
3377
3378  ScrollSpy.DEFAULTS = {
3379    offset: 10
3380  }
3381
3382  ScrollSpy.prototype.getScrollHeight = function () {
3383    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
3384  }
3385
3386  ScrollSpy.prototype.refresh = function () {
3387    var that          = this
3388    var offsetMethod  = 'offset'
3389    var offsetBase    = 0
3390
3391    this.offsets      = []
3392    this.targets      = []
3393    this.scrollHeight = this.getScrollHeight()
3394
3395    if (!$.isWindow(this.$scrollElement[0])) {
3396      offsetMethod = 'position'
3397      offsetBase   = this.$scrollElement.scrollTop()
3398    }
3399
3400    this.$body
3401      .find(this.selector)
3402      .map(function () {
3403        var $el   = $(this)
3404        var href  = $el.data('target') || $el.attr('href')
3405        var $href = /^#./.test(href) && $(href)
3406
3407        return ($href
3408          && $href.length
3409          && $href.is(':visible')
3410          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
3411      })
3412      .sort(function (a, b) { return a[0] - b[0] })
3413      .each(function () {
3414        that.offsets.push(this[0])
3415        that.targets.push(this[1])
3416      })
3417  }
3418
3419  ScrollSpy.prototype.process = function () {
3420    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
3421    var scrollHeight = this.getScrollHeight()
3422    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
3423    var offsets      = this.offsets
3424    var targets      = this.targets
3425    var activeTarget = this.activeTarget
3426    var i
3427
3428    if (this.scrollHeight != scrollHeight) {
3429      this.refresh()
3430    }
3431
3432    if (scrollTop >= maxScroll) {
3433      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
3434    }
3435
3436    if (activeTarget && scrollTop < offsets[0]) {
3437      this.activeTarget = null
3438      return this.clear()
3439    }
3440
3441    for (i = offsets.length; i--;) {
3442      activeTarget != targets[i]
3443        && scrollTop >= offsets[i]
3444        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
3445        && this.activate(targets[i])
3446    }
3447  }
3448
3449  ScrollSpy.prototype.activate = function (target) {
3450    this.activeTarget = target
3451
3452    this.clear()
3453
3454    var selector = this.selector +
3455      '[data-target="' + target + '"],' +
3456      this.selector + '[href="' + target + '"]'
3457
3458    var active = $(selector)
3459      .parents('li')
3460      .addClass('active')
3461
3462    if (active.parent('.dropdown-menu').length) {
3463      active = active
3464        .closest('li.dropdown')
3465        .addClass('active')
3466    }
3467
3468    active.trigger('activate.bs.scrollspy')
3469  }
3470
3471  ScrollSpy.prototype.clear = function () {
3472    $(this.selector)
3473      .parentsUntil(this.options.target, '.active')
3474      .removeClass('active')
3475  }
3476
3477
3478  // SCROLLSPY PLUGIN DEFINITION
3479  // ===========================
3480
3481  function Plugin(option) {
3482    return this.each(function () {
3483      var $this   = $(this)
3484      var data    = $this.data('bs.scrollspy')
3485      var options = typeof option == 'object' && option
3486
3487      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
3488      if (typeof option == 'string') data[option]()
3489    })
3490  }
3491
3492  var old = $.fn.scrollspy
3493
3494  $.fn.scrollspy             = Plugin
3495  $.fn.scrollspy.Constructor = ScrollSpy
3496
3497
3498  // SCROLLSPY NO CONFLICT
3499  // =====================
3500
3501  $.fn.scrollspy.noConflict = function () {
3502    $.fn.scrollspy = old
3503    return this
3504  }
3505
3506
3507  // SCROLLSPY DATA-API
3508  // ==================
3509
3510  $(window).on('load.bs.scrollspy.data-api', function () {
3511    $('[data-spy="scroll"]').each(function () {
3512      var $spy = $(this)
3513      Plugin.call($spy, $spy.data())
3514    })
3515  })
3516
3517}(jQuery);
3518;
3519/* ========================================================================
3520 * Bootstrap: tab.js v3.3.5
3521 * http://getbootstrap.com/javascript/#tabs
3522 * ========================================================================
3523 * Copyright 2011-2015 Twitter, Inc.
3524 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
3525 * ======================================================================== */
3526
3527
3528+function ($) {
3529  'use strict';
3530
3531  // TAB CLASS DEFINITION
3532  // ====================
3533
3534  var Tab = function (element) {
3535    // jscs:disable requireDollarBeforejQueryAssignment
3536    this.element = $(element)
3537    // jscs:enable requireDollarBeforejQueryAssignment
3538  }
3539
3540  Tab.VERSION = '3.3.5'
3541
3542  Tab.TRANSITION_DURATION = 150
3543
3544  Tab.prototype.show = function () {
3545    var $this    = this.element
3546    var $ul      = $this.closest('ul:not(.dropdown-menu)')
3547    var selector = $this.data('target')
3548
3549    if (!selector) {
3550      selector = $this.attr('href')
3551      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
3552    }
3553
3554    if ($this.parent('li').hasClass('active')) return
3555
3556    var $previous = $ul.find('.active:last a')
3557    var hideEvent = $.Event('hide.bs.tab', {
3558      relatedTarget: $this[0]
3559    })
3560    var showEvent = $.Event('show.bs.tab', {
3561      relatedTarget: $previous[0]
3562    })
3563
3564    $previous.trigger(hideEvent)
3565    $this.trigger(showEvent)
3566
3567    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
3568
3569    var $target = $(selector)
3570
3571    this.activate($this.closest('li'), $ul)
3572    this.activate($target, $target.parent(), function () {
3573      $previous.trigger({
3574        type: 'hidden.bs.tab',
3575        relatedTarget: $this[0]
3576      })
3577      $this.trigger({
3578        type: 'shown.bs.tab',
3579        relatedTarget: $previous[0]
3580      })
3581    })
3582  }
3583
3584  Tab.prototype.activate = function (element, container, callback) {
3585    var $active    = container.find('> .active')
3586    var transition = callback
3587      && $.support.transition
3588      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
3589
3590    function next() {
3591      $active
3592        .removeClass('active')
3593        .find('> .dropdown-menu > .active')
3594          .removeClass('active')
3595        .end()
3596        .find('[data-toggle="tab"]')
3597          .attr('aria-expanded', false)
3598
3599      element
3600        .addClass('active')
3601        .find('[data-toggle="tab"]')
3602          .attr('aria-expanded', true)
3603
3604      if (transition) {
3605        element[0].offsetWidth // reflow for transition
3606        element.addClass('in')
3607      } else {
3608        element.removeClass('fade')
3609      }
3610
3611      if (element.parent('.dropdown-menu').length) {
3612        element
3613          .closest('li.dropdown')
3614            .addClass('active')
3615          .end()
3616          .find('[data-toggle="tab"]')
3617            .attr('aria-expanded', true)
3618      }
3619
3620      callback && callback()
3621    }
3622
3623    $active.length && transition ?
3624      $active
3625        .one('bsTransitionEnd', next)
3626        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
3627      next()
3628
3629    $active.removeClass('in')
3630  }
3631
3632
3633  // TAB PLUGIN DEFINITION
3634  // =====================
3635
3636  function Plugin(option) {
3637    return this.each(function () {
3638      var $this = $(this)
3639      var data  = $this.data('bs.tab')
3640
3641      if (!data) $this.data('bs.tab', (data = new Tab(this)))
3642      if (typeof option == 'string') data[option]()
3643    })
3644  }
3645
3646  var old = $.fn.tab
3647
3648  $.fn.tab             = Plugin
3649  $.fn.tab.Constructor = Tab
3650
3651
3652  // TAB NO CONFLICT
3653  // ===============
3654
3655  $.fn.tab.noConflict = function () {
3656    $.fn.tab = old
3657    return this
3658  }
3659
3660
3661  // TAB DATA-API
3662  // ============
3663
3664  var clickHandler = function (e) {
3665    e.preventDefault()
3666    Plugin.call($(this), 'show')
3667  }
3668
3669  $(document)
3670    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
3671    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
3672
3673}(jQuery);
3674;
3675/* ========================================================================
3676 * Bootstrap: transition.js v3.3.5
3677 * http://getbootstrap.com/javascript/#transitions
3678 * ========================================================================
3679 * Copyright 2011-2015 Twitter, Inc.
3680 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
3681 * ======================================================================== */
3682
3683
3684+function ($) {
3685  'use strict';
3686
vendor: 1,366 bytes, lines 3687-3734
3687  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
3688  // ============================================================
3689
3690  function transitionEnd() {
3691    var el = document.createElement('bootstrap')
3692
3693    var transEndEventNames = {
3694      WebkitTransition : 'webkitTransitionEnd',
3695      MozTransition    : 'transitionend',
3696      OTransition      : 'oTransitionEnd otransitionend',
3697      transition       : 'transitionend'
3698    }
3699
3700    for (var name in transEndEventNames) {
3701      if (el.style[name] !== undefined) {
3702        return { end: transEndEventNames[name] }
3703      }
3704    }
3705
3706    return false // explicit for ie8 (  ._.)
3707  }
3708
3709  // http://blog.alexmaccaw.com/css-transitions
3710  $.fn.emulateTransitionEnd = function (duration) {
3711    var called = false
3712    var $el = this
3713    $(this).one('bsTransitionEnd', function () { called = true })
3714    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
3715    setTimeout(callback, duration)
3716    return this
3717  }
3718
3719  $(function () {
3720    $.support.transition = transitionEnd()
3721
3722    if (!$.support.transition) return
3723
3724    $.event.special.bsTransitionEnd = {
3725      bindType: $.support.transition.end,
3726      delegateType: $.support.transition.end,
3727      handle: function (e) {
3728        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
3729      }
3730    }
3731  })
3732
3733}(jQuery);
3734;

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.