PageSourceSearch

https://naober.nl/site/templates/scripts/vendor.min.js?v=7ca1bb8f

js naober.nl collected 2026-10-02 13:28:25 UTC 821,137 bytes, 27,941 lines download raw bytes

vendor: 42,881 bytes, lines 1-1589
1/*!
2 * jQuery JavaScript Library v3.3.1
3 * https://jquery.com/
4 *
5 * Includes Sizzle.js
6 * https://sizzlejs.com/
7 *
8 * Copyright JS Foundation and other contributors
9 * Released under the MIT license
10 * https://jquery.org/license
11 *
12 * Date: 2018-01-20T17:24Z
13 */
14( function( global, factory ) {
15
16	"use strict";
17
18	if ( typeof module === "object" && typeof module.exports === "object" ) {
19
20		// For CommonJS and CommonJS-like environments where a proper `window`
21		// is present, execute the factory and get jQuery.
22		// For environments that do not have a `window` with a `document`
23		// (such as Node.js), expose a factory as module.exports.
24		// This accentuates the need for the creation of a real `window`.
25		// e.g. var jQuery = require("jquery")(window);
26		// See ticket #14549 for more info.
27		module.exports = global.document ?
28			factory( global, true ) :
29			function( w ) {
30				if ( !w.document ) {
31					throw new Error( "jQuery requires a window with a document" );
32				}
33				return factory( w );
34			};
35	} else {
36		factory( global );
37	}
38
39// Pass this if window is not defined yet
40} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
41
42// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
43// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
44// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
45// enough that all such attempts are guarded in a try block.
46"use strict";
47
48var arr = [];
49
50var document = window.document;
51
52var getProto = Object.getPrototypeOf;
53
54var slice = arr.slice;
55
56var concat = arr.concat;
57
58var push = arr.push;
59
60var indexOf = arr.indexOf;
61
62var class2type = {};
63
64var toString = class2type.toString;
65
66var hasOwn = class2type.hasOwnProperty;
67
68var fnToString = hasOwn.toString;
69
70var ObjectFunctionString = fnToString.call( Object );
71
72var support = {};
73
74var isFunction = function isFunction( obj ) {
75
76      // Support: Chrome <=57, Firefox <=52
77      // In some browsers, typeof returns "function" for HTML <object> elements
78      // (i.e., `typeof document.createElement( "object" ) === "function"`).
79      // We don't want to classify *any* DOM node as a function.
80      return typeof obj === "function" && typeof obj.nodeType !== "number";
81  };
82
83
84var isWindow = function isWindow( obj ) {
85		return obj != null && obj === obj.window;
86	};
87
88
89
90
91	var preservedScriptAttributes = {
92		type: true,
93		src: true,
94		noModule: true
95	};
96
97	function DOMEval( code, doc, node ) {
98		doc = doc || document;
99
100		var i,
101			script = doc.createElement( "script" );
102
103		script.text = code;
104		if ( node ) {
105			for ( i in preservedScriptAttributes ) {
106				if ( node[ i ] ) {
107					script[ i ] = node[ i ];
108				}
109			}
110		}
111		doc.head.appendChild( script ).parentNode.removeChild( script );
112	}
113
114
115function toType( obj ) {
116	if ( obj == null ) {
117		return obj + "";
118	}
119
120	// Support: Android <=2.3 only (functionish RegExp)
121	return typeof obj === "object" || typeof obj === "function" ?
122		class2type[ toString.call( obj ) ] || "object" :
123		typeof obj;
124}
125/* global Symbol */
126// Defining this global in .eslintrc.json would create a danger of using the global
127// unguarded in another place, it seems safer to define global only for this module
128
129
130
131var
132	version = "3.3.1",
133
134	// Define a local copy of jQuery
135	jQuery = function( selector, context ) {
136
137		// The jQuery object is actually just the init constructor 'enhanced'
138		// Need init if jQuery is called (just allow error to be thrown if not included)
139		return new jQuery.fn.init( selector, context );
140	},
141
142	// Support: Android <=4.0 only
143	// Make sure we trim BOM and NBSP
144	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
145
146jQuery.fn = jQuery.prototype = {
147
148	// The current version of jQuery being used
149	jquery: version,
150
151	constructor: jQuery,
152
153	// The default length of a jQuery object is 0
154	length: 0,
155
156	toArray: function() {
157		return slice.call( this );
158	},
159
160	// Get the Nth element in the matched element set OR
161	// Get the whole matched element set as a clean array
162	get: function( num ) {
163
164		// Return all the elements in a clean array
165		if ( num == null ) {
166			return slice.call( this );
167		}
168
169		// Return just the one element from the set
170		return num < 0 ? this[ num + this.length ] : this[ num ];
171	},
172
173	// Take an array of elements and push it onto the stack
174	// (returning the new matched element set)
175	pushStack: function( elems ) {
176
177		// Build a new jQuery matched element set
178		var ret = jQuery.merge( this.constructor(), elems );
179
180		// Add the old object onto the stack (as a reference)
181		ret.prevObject = this;
182
183		// Return the newly-formed element set
184		return ret;
185	},
186
187	// Execute a callback for every element in the matched set.
188	each: function( callback ) {
189		return jQuery.each( this, callback );
190	},
191
192	map: function( callback ) {
193		return this.pushStack( jQuery.map( this, function( elem, i ) {
194			return callback.call( elem, i, elem );
195		} ) );
196	},
197
198	slice: function() {
199		return this.pushStack( slice.apply( this, arguments ) );
200	},
201
202	first: function() {
203		return this.eq( 0 );
204	},
205
206	last: function() {
207		return this.eq( -1 );
208	},
209
210	eq: function( i ) {
211		var len = this.length,
212			j = +i + ( i < 0 ? len : 0 );
213		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
214	},
215
216	end: function() {
217		return this.prevObject || this.constructor();
218	},
219
220	// For internal use only.
221	// Behaves like an Array's method, not like a jQuery method.
222	push: push,
223	sort: arr.sort,
224	splice: arr.splice
225};
226
227jQuery.extend = jQuery.fn.extend = function() {
228	var options, name, src, copy, copyIsArray, clone,
229		target = arguments[ 0 ] || {},
230		i = 1,
231		length = arguments.length,
232		deep = false;
233
234	// Handle a deep copy situation
235	if ( typeof target === "boolean" ) {
236		deep = target;
237
238		// Skip the boolean and the target
239		target = arguments[ i ] || {};
240		i++;
241	}
242
243	// Handle case when target is a string or something (possible in deep copy)
244	if ( typeof target !== "object" && !isFunction( target ) ) {
245		target = {};
246	}
247
248	// Extend jQuery itself if only one argument is passed
249	if ( i === length ) {
250		target = this;
251		i--;
252	}
253
254	for ( ; i < length; i++ ) {
255
256		// Only deal with non-null/undefined values
257		if ( ( options = arguments[ i ] ) != null ) {
258
259			// Extend the base object
260			for ( name in options ) {
261				src = target[ name ];
262				copy = options[ name ];
263
264				// Prevent never-ending loop
265				if ( target === copy ) {
266					continue;
267				}
268
269				// Recurse if we're merging plain objects or arrays
270				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
271					( copyIsArray = Array.isArray( copy ) ) ) ) {
272
273					if ( copyIsArray ) {
274						copyIsArray = false;
275						clone = src && Array.isArray( src ) ? src : [];
276
277					} else {
278						clone = src && jQuery.isPlainObject( src ) ? src : {};
279					}
280
281					// Never move original objects, clone them
282					target[ name ] = jQuery.extend( deep, clone, copy );
283
284				// Don't bring in undefined values
285				} else if ( copy !== undefined ) {
286					target[ name ] = copy;
287				}
288			}
289		}
290	}
291
292	// Return the modified object
293	return target;
294};
295
296jQuery.extend( {
297
298	// Unique for each copy of jQuery on the page
299	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
300
301	// Assume jQuery is ready without the ready module
302	isReady: true,
303
304	error: function( msg ) {
305		throw new Error( msg );
306	},
307
308	noop: function() {},
309
310	isPlainObject: function( obj ) {
311		var proto, Ctor;
312
313		// Detect obvious negatives
314		// Use toString instead of jQuery.type to catch host objects
315		if ( !obj || toString.call( obj ) !== "[object Object]" ) {
316			return false;
317		}
318
319		proto = getProto( obj );
320
321		// Objects with no prototype (e.g., `Object.create( null )`) are plain
322		if ( !proto ) {
323			return true;
324		}
325
326		// Objects with prototype are plain iff they were constructed by a global Object function
327		Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
328		return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
329	},
330
331	isEmptyObject: function( obj ) {
332
333		/* eslint-disable no-unused-vars */
334		// See https://github.com/eslint/eslint/issues/6125
335		var name;
336
337		for ( name in obj ) {
338			return false;
339		}
340		return true;
341	},
342
343	// Evaluates a script in a global context
344	globalEval: function( code ) {
345		DOMEval( code );
346	},
347
348	each: function( obj, callback ) {
349		var length, i = 0;
350
351		if ( isArrayLike( obj ) ) {
352			length = obj.length;
353			for ( ; i < length; i++ ) {
354				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
355					break;
356				}
357			}
358		} else {
359			for ( i in obj ) {
360				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
361					break;
362				}
363			}
364		}
365
366		return obj;
367	},
368
369	// Support: Android <=4.0 only
370	trim: function( text ) {
371		return text == null ?
372			"" :
373			( text + "" ).replace( rtrim, "" );
374	},
375
376	// results is for internal usage only
377	makeArray: function( arr, results ) {
378		var ret = results || [];
379
380		if ( arr != null ) {
381			if ( isArrayLike( Object( arr ) ) ) {
382				jQuery.merge( ret,
383					typeof arr === "string" ?
384					[ arr ] : arr
385				);
386			} else {
387				push.call( ret, arr );
388			}
389		}
390
391		return ret;
392	},
393
394	inArray: function( elem, arr, i ) {
395		return arr == null ? -1 : indexOf.call( arr, elem, i );
396	},
397
398	// Support: Android <=4.0 only, PhantomJS 1 only
399	// push.apply(_, arraylike) throws on ancient WebKit
400	merge: function( first, second ) {
401		var len = +second.length,
402			j = 0,
403			i = first.length;
404
405		for ( ; j < len; j++ ) {
406			first[ i++ ] = second[ j ];
407		}
408
409		first.length = i;
410
411		return first;
412	},
413
414	grep: function( elems, callback, invert ) {
415		var callbackInverse,
416			matches = [],
417			i = 0,
418			length = elems.length,
419			callbackExpect = !invert;
420
421		// Go through the array, only saving the items
422		// that pass the validator function
423		for ( ; i < length; i++ ) {
424			callbackInverse = !callback( elems[ i ], i );
425			if ( callbackInverse !== callbackExpect ) {
426				matches.push( elems[ i ] );
427			}
428		}
429
430		return matches;
431	},
432
433	// arg is for internal usage only
434	map: function( elems, callback, arg ) {
435		var length, value,
436			i = 0,
437			ret = [];
438
439		// Go through the array, translating each of the items to their new values
440		if ( isArrayLike( elems ) ) {
441			length = elems.length;
442			for ( ; i < length; i++ ) {
443				value = callback( elems[ i ], i, arg );
444
445				if ( value != null ) {
446					ret.push( value );
447				}
448			}
449
450		// Go through every key on the object,
451		} else {
452			for ( i in elems ) {
453				value = callback( elems[ i ], i, arg );
454
455				if ( value != null ) {
456					ret.push( value );
457				}
458			}
459		}
460
461		// Flatten any nested arrays
462		return concat.apply( [], ret );
463	},
464
465	// A global GUID counter for objects
466	guid: 1,
467
468	// jQuery.support is not used in Core but other projects attach their
469	// properties to it so it needs to exist.
470	support: support
471} );
472
473if ( typeof Symbol === "function" ) {
474	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
475}
476
477// Populate the class2type map
478jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
479function( i, name ) {
480	class2type[ "[object " + name + "]" ] = name.toLowerCase();
481} );
482
483function isArrayLike( obj ) {
484
485	// Support: real iOS 8.2 only (not reproducible in simulator)
486	// `in` check used to prevent JIT error (gh-2145)
487	// hasOwn isn't used here due to false negatives
488	// regarding Nodelist length in IE
489	var length = !!obj && "length" in obj && obj.length,
490		type = toType( obj );
491
492	if ( isFunction( obj ) || isWindow( obj ) ) {
493		return false;
494	}
495
496	return type === "array" || length === 0 ||
497		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
498}
499var Sizzle =
500/*!
501 * Sizzle CSS Selector Engine v2.3.3
502 * https://sizzlejs.com/
503 *
504 * Copyright jQuery Foundation and other contributors
505 * Released under the MIT license
506 * http://jquery.org/license
507 *
508 * Date: 2016-08-08
509 */
510(function( window ) {
511
512var i,
513	support,
514	Expr,
515	getText,
516	isXML,
517	tokenize,
518	compile,
519	select,
520	outermostContext,
521	sortInput,
522	hasDuplicate,
523
524	// Local document vars
525	setDocument,
526	document,
527	docElem,
528	documentIsHTML,
529	rbuggyQSA,
530	rbuggyMatches,
531	matches,
532	contains,
533
534	// Instance-specific data
535	expando = "sizzle" + 1 * new Date(),
536	preferredDoc = window.document,
537	dirruns = 0,
538	done = 0,
539	classCache = createCache(),
540	tokenCache = createCache(),
541	compilerCache = createCache(),
542	sortOrder = function( a, b ) {
543		if ( a === b ) {
544			hasDuplicate = true;
545		}
546		return 0;
547	},
548
549	// Instance methods
550	hasOwn = ({}).hasOwnProperty,
551	arr = [],
552	pop = arr.pop,
553	push_native = arr.push,
554	push = arr.push,
555	slice = arr.slice,
556	// Use a stripped-down indexOf as it's faster than native
557	// https://jsperf.com/thor-indexof-vs-for/5
558	indexOf = function( list, elem ) {
559		var i = 0,
560			len = list.length;
561		for ( ; i < len; i++ ) {
562			if ( list[i] === elem ) {
563				return i;
564			}
565		}
566		return -1;
567	},
568
569	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
570
571	// Regular expressions
572
573	// http://www.w3.org/TR/css3-selectors/#whitespace
574	whitespace = "[\\x20\\t\\r\\n\\f]",
575
576	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
577	identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
578
579	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
580	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
581		// Operator (capture 2)
582		"*([*^$|!~]?=)" + whitespace +
583		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
584		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
585		"*\\]",
586
587	pseudos = ":(" + identifier + ")(?:\\((" +
588		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
589		// 1. quoted (capture 3; capture 4 or capture 5)
590		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
591		// 2. simple (capture 6)
592		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
593		// 3. anything else (capture 2)
594		".*" +
595		")\\)|)",
596
597	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
598	rwhitespace = new RegExp( whitespace + "+", "g" ),
599	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
600
601	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
602	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
603
604	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
605
606	rpseudo = new RegExp( pseudos ),
607	ridentifier = new RegExp( "^" + identifier + "$" ),
608
609	matchExpr = {
610		"ID": new RegExp( "^#(" + identifier + ")" ),
611		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
612		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
613		"ATTR": new RegExp( "^" + attributes ),
614		"PSEUDO": new RegExp( "^" + pseudos ),
615		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
616			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
617			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
618		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
619		// For use in libraries implementing .is()
620		// We use this for POS matching in `select`
621		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
622			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
623	},
624
625	rinputs = /^(?:input|select|textarea|button)$/i,
626	rheader = /^h\d$/i,
627
628	rnative = /^[^{]+\{\s*\[native \w/,
629
630	// Easily-parseable/retrievable ID or TAG or CLASS selectors
631	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
632
633	rsibling = /[+~]/,
634
635	// CSS escapes
636	// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
637	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
638	funescape = function( _, escaped, escapedWhitespace ) {
639		var high = "0x" + escaped - 0x10000;
640		// NaN means non-codepoint
641		// Support: Firefox<24
642		// Workaround erroneous numeric interpretation of +"0x"
643		return high !== high || escapedWhitespace ?
644			escaped :
645			high < 0 ?
646				// BMP codepoint
647				String.fromCharCode( high + 0x10000 ) :
648				// Supplemental Plane codepoint (surrogate pair)
649				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
650	},
651
652	// CSS string/identifier serialization
653	// https://drafts.csswg.org/cssom/#common-serializing-idioms
654	rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
655	fcssescape = function( ch, asCodePoint ) {
656		if ( asCodePoint ) {
657
658			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
659			if ( ch === "\0" ) {
660				return "\uFFFD";
661			}
662
663			// Control characters and (dependent upon position) numbers get escaped as code points
664			return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
665		}
666
667		// Other potentially-special ASCII characters get backslash-escaped
668		return "\\" + ch;
669	},
670
671	// Used for iframes
672	// See setDocument()
673	// Removing the function wrapper causes a "Permission Denied"
674	// error in IE
675	unloadHandler = function() {
676		setDocument();
677	},
678
679	disabledAncestor = addCombinator(
680		function( elem ) {
681			return elem.disabled === true && ("form" in elem || "label" in elem);
682		},
683		{ dir: "parentNode", next: "legend" }
684	);
685
686// Optimize for push.apply( _, NodeList )
687try {
688	push.apply(
689		(arr = slice.call( preferredDoc.childNodes )),
690		preferredDoc.childNodes
691	);
692	// Support: Android<4.0
693	// Detect silently failing push.apply
694	arr[ preferredDoc.childNodes.length ].nodeType;
695} catch ( e ) {
696	push = { apply: arr.length ?
697
698		// Leverage slice if possible
699		function( target, els ) {
700			push_native.apply( target, slice.call(els) );
701		} :
702
703		// Support: IE<9
704		// Otherwise append directly
705		function( target, els ) {
706			var j = target.length,
707				i = 0;
708			// Can't trust NodeList.length
709			while ( (target[j++] = els[i++]) ) {}
710			target.length = j - 1;
711		}
712	};
713}
714
715function Sizzle( selector, context, results, seed ) {
716	var m, i, elem, nid, match, groups, newSelector,
717		newContext = context && context.ownerDocument,
718
719		// nodeType defaults to 9, since context defaults to document
720		nodeType = context ? context.nodeType : 9;
721
722	results = results || [];
723
724	// Return early from calls with invalid selector or context
725	if ( typeof selector !== "string" || !selector ||
726		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
727
728		return results;
729	}
730
731	// Try to shortcut find operations (as opposed to filters) in HTML documents
732	if ( !seed ) {
733
734		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
735			setDocument( context );
736		}
737		context = context || document;
738
739		if ( documentIsHTML ) {
740
741			// If the selector is sufficiently simple, try using a "get*By*" DOM method
742			// (excepting DocumentFragment context, where the methods don't exist)
743			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
744
745				// ID selector
746				if ( (m = match[1]) ) {
747
748					// Document context
749					if ( nodeType === 9 ) {
750						if ( (elem = context.getElementById( m )) ) {
751
752							// Support: IE, Opera, Webkit
753							// TODO: identify versions
754							// getElementById can match elements by name instead of ID
755							if ( elem.id === m ) {
756								results.push( elem );
757								return results;
758							}
759						} else {
760							return results;
761						}
762
763					// Element context
764					} else {
765
766						// Support: IE, Opera, Webkit
767						// TODO: identify versions
768						// getElementById can match elements by name instead of ID
769						if ( newContext && (elem = newContext.getElementById( m )) &&
770							contains( context, elem ) &&
771							elem.id === m ) {
772
773							results.push( elem );
774							return results;
775						}
776					}
777
778				// Type selector
779				} else if ( match[2] ) {
780					push.apply( results, context.getElementsByTagName( selector ) );
781					return results;
782
783				// Class selector
784				} else if ( (m = match[3]) && support.getElementsByClassName &&
785					context.getElementsByClassName ) {
786
787					push.apply( results, context.getElementsByClassName( m ) );
788					return results;
789				}
790			}
791
792			// Take advantage of querySelectorAll
793			if ( support.qsa &&
794				!compilerCache[ selector + " " ] &&
795				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
796
797				if ( nodeType !== 1 ) {
798					newContext = context;
799					newSelector = selector;
800
801				// qSA looks outside Element context, which is not what we want
802				// Thanks to Andrew Dupont for this workaround technique
803				// Support: IE <=8
804				// Exclude object elements
805				} else if ( context.nodeName.toLowerCase() !== "object" ) {
806
807					// Capture the context ID, setting it first if necessary
808					if ( (nid = context.getAttribute( "id" )) ) {
809						nid = nid.replace( rcssescape, fcssescape );
810					} else {
811						context.setAttribute( "id", (nid = expando) );
812					}
813
814					// Prefix every selector in the list
815					groups = tokenize( selector );
816					i = groups.length;
817					while ( i-- ) {
818						groups[i] = "#" + nid + " " + toSelector( groups[i] );
819					}
820					newSelector = groups.join( "," );
821
822					// Expand context for sibling selectors
823					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
824						context;
825				}
826
827				if ( newSelector ) {
828					try {
829						push.apply( results,
830							newContext.querySelectorAll( newSelector )
831						);
832						return results;
833					} catch ( qsaError ) {
834					} finally {
835						if ( nid === expando ) {
836							context.removeAttribute( "id" );
837						}
838					}
839				}
840			}
841		}
842	}
843
844	// All others
845	return select( selector.replace( rtrim, "$1" ), context, results, seed );
846}
847
848/**
849 * Create key-value caches of limited size
850 * @returns {function(string, object)} Returns the Object data after storing it on itself with
851 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
852 *	deleting the oldest entry
853 */
854function createCache() {
855	var keys = [];
856
857	function cache( key, value ) {
858		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
859		if ( keys.push( key + " " ) > Expr.cacheLength ) {
860			// Only keep the most recent entries
861			delete cache[ keys.shift() ];
862		}
863		return (cache[ key + " " ] = value);
864	}
865	return cache;
866}
867
868/**
869 * Mark a function for special use by Sizzle
870 * @param {Function} fn The function to mark
871 */
872function markFunction( fn ) {
873	fn[ expando ] = true;
874	return fn;
875}
876
877/**
878 * Support testing using an element
879 * @param {Function} fn Passed the created element and returns a boolean result
880 */
881function assert( fn ) {
882	var el = document.createElement("fieldset");
883
884	try {
885		return !!fn( el );
886	} catch (e) {
887		return false;
888	} finally {
889		// Remove from its parent by default
890		if ( el.parentNode ) {
891			el.parentNode.removeChild( el );
892		}
893		// release memory in IE
894		el = null;
895	}
896}
897
898/**
899 * Adds the same handler for all of the specified attrs
900 * @param {String} attrs Pipe-separated list of attributes
901 * @param {Function} handler The method that will be applied
902 */
903function addHandle( attrs, handler ) {
904	var arr = attrs.split("|"),
905		i = arr.length;
906
907	while ( i-- ) {
908		Expr.attrHandle[ arr[i] ] = handler;
909	}
910}
911
912/**
913 * Checks document order of two siblings
914 * @param {Element} a
915 * @param {Element} b
916 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
917 */
918function siblingCheck( a, b ) {
919	var cur = b && a,
920		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
921			a.sourceIndex - b.sourceIndex;
922
923	// Use IE sourceIndex if available on both nodes
924	if ( diff ) {
925		return diff;
926	}
927
928	// Check if b follows a
929	if ( cur ) {
930		while ( (cur = cur.nextSibling) ) {
931			if ( cur === b ) {
932				return -1;
933			}
934		}
935	}
936
937	return a ? 1 : -1;
938}
939
940/**
941 * Returns a function to use in pseudos for input types
942 * @param {String} type
943 */
944function createInputPseudo( type ) {
945	return function( elem ) {
946		var name = elem.nodeName.toLowerCase();
947		return name === "input" && elem.type === type;
948	};
949}
950
951/**
952 * Returns a function to use in pseudos for buttons
953 * @param {String} type
954 */
955function createButtonPseudo( type ) {
956	return function( elem ) {
957		var name = elem.nodeName.toLowerCase();
958		return (name === "input" || name === "button") && elem.type === type;
959	};
960}
961
962/**
963 * Returns a function to use in pseudos for :enabled/:disabled
964 * @param {Boolean} disabled true for :disabled; false for :enabled
965 */
966function createDisabledPseudo( disabled ) {
967
968	// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
969	return function( elem ) {
970
971		// Only certain elements can match :enabled or :disabled
972		// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
973		// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
974		if ( "form" in elem ) {
975
976			// Check for inherited disabledness on relevant non-disabled elements:
977			// * listed form-associated elements in a disabled fieldset
978			//   https://html.spec.whatwg.org/multipage/forms.html#category-listed
979			//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
980			// * option elements in a disabled optgroup
981			//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
982			// All such elements have a "form" property.
983			if ( elem.parentNode && elem.disabled === false ) {
984
985				// Option elements defer to a parent optgroup if present
986				if ( "label" in elem ) {
987					if ( "label" in elem.parentNode ) {
988						return elem.parentNode.disabled === disabled;
989					} else {
990						return elem.disabled === disabled;
991					}
992				}
993
994				// Support: IE 6 - 11
995				// Use the isDisabled shortcut property to check for disabled fieldset ancestors
996				return elem.isDisabled === disabled ||
997
998					// Where there is no isDisabled, check manually
999					/* jshint -W018 */
1000					elem.isDisabled !== !disabled &&
1001						disabledAncestor( elem ) === disabled;
1002			}
1003
1004			return elem.disabled === disabled;
1005
1006		// Try to winnow out elements that can't be disabled before trusting the disabled property.
1007		// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
1008		// even exist on them, let alone have a boolean value.
1009		} else if ( "label" in elem ) {
1010			return elem.disabled === disabled;
1011		}
1012
1013		// Remaining elements are neither :enabled nor :disabled
1014		return false;
1015	};
1016}
1017
1018/**
1019 * Returns a function to use in pseudos for positionals
1020 * @param {Function} fn
1021 */
1022function createPositionalPseudo( fn ) {
1023	return markFunction(function( argument ) {
1024		argument = +argument;
1025		return markFunction(function( seed, matches ) {
1026			var j,
1027				matchIndexes = fn( [], seed.length, argument ),
1028				i = matchIndexes.length;
1029
1030			// Match elements found at the specified indexes
1031			while ( i-- ) {
1032				if ( seed[ (j = matchIndexes[i]) ] ) {
1033					seed[j] = !(matches[j] = seed[j]);
1034				}
1035			}
1036		});
1037	});
1038}
1039
1040/**
1041 * Checks a node for validity as a Sizzle context
1042 * @param {Element|Object=} context
1043 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1044 */
1045function testContext( context ) {
1046	return context && typeof context.getElementsByTagName !== "undefined" && context;
1047}
1048
1049// Expose support vars for convenience
1050support = Sizzle.support = {};
1051
1052/**
1053 * Detects XML nodes
1054 * @param {Element|Object} elem An element or a document
1055 * @returns {Boolean} True iff elem is a non-HTML XML node
1056 */
1057isXML = Sizzle.isXML = function( elem ) {
1058	// documentElement is verified for cases where it doesn't yet exist
1059	// (such as loading iframes in IE - #4833)
1060	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1061	return documentElement ? documentElement.nodeName !== "HTML" : false;
1062};
1063
1064/**
1065 * Sets document-related variables once based on the current document
1066 * @param {Element|Object} [doc] An element or document object to use to set the document
1067 * @returns {Object} Returns the current document
1068 */
1069setDocument = Sizzle.setDocument = function( node ) {
1070	var hasCompare, subWindow,
1071		doc = node ? node.ownerDocument || node : preferredDoc;
1072
1073	// Return early if doc is invalid or already selected
1074	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1075		return document;
1076	}
1077
1078	// Update global variables
1079	document = doc;
1080	docElem = document.documentElement;
1081	documentIsHTML = !isXML( document );
1082
1083	// Support: IE 9-11, Edge
1084	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
1085	if ( preferredDoc !== document &&
1086		(subWindow = document.defaultView) && subWindow.top !== subWindow ) {
1087
1088		// Support: IE 11, Edge
1089		if ( subWindow.addEventListener ) {
1090			subWindow.addEventListener( "unload", unloadHandler, false );
1091
1092		// Support: IE 9 - 10 only
1093		} else if ( subWindow.attachEvent ) {
1094			subWindow.attachEvent( "onunload", unloadHandler );
1095		}
1096	}
1097
1098	/* Attributes
1099	---------------------------------------------------------------------- */
1100
1101	// Support: IE<8
1102	// Verify that getAttribute really returns attributes and not properties
1103	// (excepting IE8 booleans)
1104	support.attributes = assert(function( el ) {
1105		el.className = "i";
1106		return !el.getAttribute("className");
1107	});
1108
1109	/* getElement(s)By*
1110	---------------------------------------------------------------------- */
1111
1112	// Check if getElementsByTagName("*") returns only elements
1113	support.getElementsByTagName = assert(function( el ) {
1114		el.appendChild( document.createComment("") );
1115		return !el.getElementsByTagName("*").length;
1116	});
1117
1118	// Support: IE<9
1119	support.getElementsByClassName = rnative.test( document.getElementsByClassName );
1120
1121	// Support: IE<10
1122	// Check if getElementById returns elements by name
1123	// The broken getElementById methods don't pick up programmatically-set names,
1124	// so use a roundabout getElementsByName test
1125	support.getById = assert(function( el ) {
1126		docElem.appendChild( el ).id = expando;
1127		return !document.getElementsByName || !document.getElementsByName( expando ).length;
1128	});
1129
1130	// ID filter and find
1131	if ( support.getById ) {
1132		Expr.filter["ID"] = function( id ) {
1133			var attrId = id.replace( runescape, funescape );
1134			return function( elem ) {
1135				return elem.getAttribute("id") === attrId;
1136			};
1137		};
1138		Expr.find["ID"] = function( id, context ) {
1139			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1140				var elem = context.getElementById( id );
1141				return elem ? [ elem ] : [];
1142			}
1143		};
1144	} else {
1145		Expr.filter["ID"] =  function( id ) {
1146			var attrId = id.replace( runescape, funescape );
1147			return function( elem ) {
1148				var node = typeof elem.getAttributeNode !== "undefined" &&
1149					elem.getAttributeNode("id");
1150				return node && node.value === attrId;
1151			};
1152		};
1153
1154		// Support: IE 6 - 7 only
1155		// getElementById is not reliable as a find shortcut
1156		Expr.find["ID"] = function( id, context ) {
1157			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1158				var node, i, elems,
1159					elem = context.getElementById( id );
1160
1161				if ( elem ) {
1162
1163					// Verify the id attribute
1164					node = elem.getAttributeNode("id");
1165					if ( node && node.value === id ) {
1166						return [ elem ];
1167					}
1168
1169					// Fall back on getElementsByName
1170					elems = context.getElementsByName( id );
1171					i = 0;
1172					while ( (elem = elems[i++]) ) {
1173						node = elem.getAttributeNode("id");
1174						if ( node && node.value === id ) {
1175							return [ elem ];
1176						}
1177					}
1178				}
1179
1180				return [];
1181			}
1182		};
1183	}
1184
1185	// Tag
1186	Expr.find["TAG"] = support.getElementsByTagName ?
1187		function( tag, context ) {
1188			if ( typeof context.getElementsByTagName !== "undefined" ) {
1189				return context.getElementsByTagName( tag );
1190
1191			// DocumentFragment nodes don't have gEBTN
1192			} else if ( support.qsa ) {
1193				return context.querySelectorAll( tag );
1194			}
1195		} :
1196
1197		function( tag, context ) {
1198			var elem,
1199				tmp = [],
1200				i = 0,
1201				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1202				results = context.getElementsByTagName( tag );
1203
1204			// Filter out possible comments
1205			if ( tag === "*" ) {
1206				while ( (elem = results[i++]) ) {
1207					if ( elem.nodeType === 1 ) {
1208						tmp.push( elem );
1209					}
1210				}
1211
1212				return tmp;
1213			}
1214			return results;
1215		};
1216
1217	// Class
1218	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1219		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
1220			return context.getElementsByClassName( className );
1221		}
1222	};
1223
1224	/* QSA/matchesSelector
1225	---------------------------------------------------------------------- */
1226
1227	// QSA and matchesSelector support
1228
1229	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1230	rbuggyMatches = [];
1231
1232	// qSa(:focus) reports false when true (Chrome 21)
1233	// We allow this because of a bug in IE8/9 that throws an error
1234	// whenever `document.activeElement` is accessed on an iframe
1235	// So, we allow :focus to pass through QSA all the time to avoid the IE error
1236	// See https://bugs.jquery.com/ticket/13378
1237	rbuggyQSA = [];
1238
1239	if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
1240		// Build QSA regex
1241		// Regex strategy adopted from Diego Perini
1242		assert(function( el ) {
1243			// Select is set to empty string on purpose
1244			// This is to test IE's treatment of not explicitly
1245			// setting a boolean content attribute,
1246			// since its presence should be enough
1247			// https://bugs.jquery.com/ticket/12359
1248			docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
1249				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
1250				"<option selected=''></option></select>";
1251
1252			// Support: IE8, Opera 11-12.16
1253			// Nothing should be selected when empty strings follow ^= or $= or *=
1254			// The test attribute must be unknown in Opera but "safe" for WinRT
1255			// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1256			if ( el.querySelectorAll("[msallowcapture^='']").length ) {
1257				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1258			}
1259
1260			// Support: IE8
1261			// Boolean attributes and "value" are not treated correctly
1262			if ( !el.querySelectorAll("[selected]").length ) {
1263				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1264			}
1265
1266			// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
1267			if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1268				rbuggyQSA.push("~=");
1269			}
1270
1271			// Webkit/Opera - :checked should return selected option elements
1272			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1273			// IE8 throws error here and will not see later tests
1274			if ( !el.querySelectorAll(":checked").length ) {
1275				rbuggyQSA.push(":checked");
1276			}
1277
1278			// Support: Safari 8+, iOS 8+
1279			// https://bugs.webkit.org/show_bug.cgi?id=136851
1280			// In-page `selector#id sibling-combinator selector` fails
1281			if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
1282				rbuggyQSA.push(".#.+[+~]");
1283			}
1284		});
1285
1286		assert(function( el ) {
1287			el.innerHTML = "<a href='' disabled='disabled'></a>" +
1288				"<select disabled='disabled'><option/></select>";
1289
1290			// Support: Windows 8 Native Apps
1291			// The type and name attributes are restricted during .innerHTML assignment
1292			var input = document.createElement("input");
1293			input.setAttribute( "type", "hidden" );
1294			el.appendChild( input ).setAttribute( "name", "D" );
1295
1296			// Support: IE8
1297			// Enforce case-sensitivity of name attribute
1298			if ( el.querySelectorAll("[name=d]").length ) {
1299				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1300			}
1301
1302			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1303			// IE8 throws error here and will not see later tests
1304			if ( el.querySelectorAll(":enabled").length !== 2 ) {
1305				rbuggyQSA.push( ":enabled", ":disabled" );
1306			}
1307
1308			// Support: IE9-11+
1309			// IE's :disabled selector does not pick up the children of disabled fieldsets
1310			docElem.appendChild( el ).disabled = true;
1311			if ( el.querySelectorAll(":disabled").length !== 2 ) {
1312				rbuggyQSA.push( ":enabled", ":disabled" );
1313			}
1314
1315			// Opera 10-11 does not throw on post-comma invalid pseudos
1316			el.querySelectorAll("*,:x");
1317			rbuggyQSA.push(",.*:");
1318		});
1319	}
1320
1321	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1322		docElem.webkitMatchesSelector ||
1323		docElem.mozMatchesSelector ||
1324		docElem.oMatchesSelector ||
1325		docElem.msMatchesSelector) )) ) {
1326
1327		assert(function( el ) {
1328			// Check to see if it's possible to do matchesSelector
1329			// on a disconnected node (IE 9)
1330			support.disconnectedMatch = matches.call( el, "*" );
1331
1332			// This should fail with an exception
1333			// Gecko does not error, returns false instead
1334			matches.call( el, "[s!='']:x" );
1335			rbuggyMatches.push( "!=", pseudos );
1336		});
1337	}
1338
1339	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1340	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1341
1342	/* Contains
1343	---------------------------------------------------------------------- */
1344	hasCompare = rnative.test( docElem.compareDocumentPosition );
1345
1346	// Element contains another
1347	// Purposefully self-exclusive
1348	// As in, an element does not contain itself
1349	contains = hasCompare || rnative.test( docElem.contains ) ?
1350		function( a, b ) {
1351			var adown = a.nodeType === 9 ? a.documentElement : a,
1352				bup = b && b.parentNode;
1353			return a === bup || !!( bup && bup.nodeType === 1 && (
1354				adown.contains ?
1355					adown.contains( bup ) :
1356					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1357			));
1358		} :
1359		function( a, b ) {
1360			if ( b ) {
1361				while ( (b = b.parentNode) ) {
1362					if ( b === a ) {
1363						return true;
1364					}
1365				}
1366			}
1367			return false;
1368		};
1369
1370	/* Sorting
1371	---------------------------------------------------------------------- */
1372
1373	// Document order sorting
1374	sortOrder = hasCompare ?
1375	function( a, b ) {
1376
1377		// Flag for duplicate removal
1378		if ( a === b ) {
1379			hasDuplicate = true;
1380			return 0;
1381		}
1382
1383		// Sort on method existence if only one input has compareDocumentPosition
1384		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1385		if ( compare ) {
1386			return compare;
1387		}
1388
1389		// Calculate position if both inputs belong to the same document
1390		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1391			a.compareDocumentPosition( b ) :
1392
1393			// Otherwise we know they are disconnected
1394			1;
1395
1396		// Disconnected nodes
1397		if ( compare & 1 ||
1398			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1399
1400			// Choose the first element that is related to our preferred document
1401			if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1402				return -1;
1403			}
1404			if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1405				return 1;
1406			}
1407
1408			// Maintain original order
1409			return sortInput ?
1410				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1411				0;
1412		}
1413
1414		return compare & 4 ? -1 : 1;
1415	} :
1416	function( a, b ) {
1417		// Exit early if the nodes are identical
1418		if ( a === b ) {
1419			hasDuplicate = true;
1420			return 0;
1421		}
1422
1423		var cur,
1424			i = 0,
1425			aup = a.parentNode,
1426			bup = b.parentNode,
1427			ap = [ a ],
1428			bp = [ b ];
1429
1430		// Parentless nodes are either documents or disconnected
1431		if ( !aup || !bup ) {
1432			return a === document ? -1 :
1433				b === document ? 1 :
1434				aup ? -1 :
1435				bup ? 1 :
1436				sortInput ?
1437				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1438				0;
1439
1440		// If the nodes are siblings, we can do a quick check
1441		} else if ( aup === bup ) {
1442			return siblingCheck( a, b );
1443		}
1444
1445		// Otherwise we need full lists of their ancestors for comparison
1446		cur = a;
1447		while ( (cur = cur.parentNode) ) {
1448			ap.unshift( cur );
1449		}
1450		cur = b;
1451		while ( (cur = cur.parentNode) ) {
1452			bp.unshift( cur );
1453		}
1454
1455		// Walk down the tree looking for a discrepancy
1456		while ( ap[i] === bp[i] ) {
1457			i++;
1458		}
1459
1460		return i ?
1461			// Do a sibling check if the nodes have a common ancestor
1462			siblingCheck( ap[i], bp[i] ) :
1463
1464			// Otherwise nodes in our document sort first
1465			ap[i] === preferredDoc ? -1 :
1466			bp[i] === preferredDoc ? 1 :
1467			0;
1468	};
1469
1470	return document;
1471};
1472
1473Sizzle.matches = function( expr, elements ) {
1474	return Sizzle( expr, null, null, elements );
1475};
1476
1477Sizzle.matchesSelector = function( elem, expr ) {
1478	// Set document vars if needed
1479	if ( ( elem.ownerDocument || elem ) !== document ) {
1480		setDocument( elem );
1481	}
1482
1483	// Make sure that attribute selectors are quoted
1484	expr = expr.replace( rattributeQuotes, "='$1']" );
1485
1486	if ( support.matchesSelector && documentIsHTML &&
1487		!compilerCache[ expr + " " ] &&
1488		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1489		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
1490
1491		try {
1492			var ret = matches.call( elem, expr );
1493
1494			// IE 9's matchesSelector returns false on disconnected nodes
1495			if ( ret || support.disconnectedMatch ||
1496					// As well, disconnected nodes are said to be in a document
1497					// fragment in IE 9
1498					elem.document && elem.document.nodeType !== 11 ) {
1499				return ret;
1500			}
1501		} catch (e) {}
1502	}
1503
1504	return Sizzle( expr, document, null, [ elem ] ).length > 0;
1505};
1506
1507Sizzle.contains = function( context, elem ) {
1508	// Set document vars if needed
1509	if ( ( context.ownerDocument || context ) !== document ) {
1510		setDocument( context );
1511	}
1512	return contains( context, elem );
1513};
1514
1515Sizzle.attr = function( elem, name ) {
1516	// Set document vars if needed
1517	if ( ( elem.ownerDocument || elem ) !== document ) {
1518		setDocument( elem );
1519	}
1520
1521	var fn = Expr.attrHandle[ name.toLowerCase() ],
1522		// Don't get fooled by Object.prototype properties (jQuery #13807)
1523		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1524			fn( elem, name, !documentIsHTML ) :
1525			undefined;
1526
1527	return val !== undefined ?
1528		val :
1529		support.attributes || !documentIsHTML ?
1530			elem.getAttribute( name ) :
1531			(val = elem.getAttributeNode(name)) && val.specified ?
1532				val.value :
1533				null;
1534};
1535
1536Sizzle.escape = function( sel ) {
1537	return (sel + "").replace( rcssescape, fcssescape );
1538};
1539
1540Sizzle.error = function( msg ) {
1541	throw new Error( "Syntax error, unrecognized expression: " + msg );
1542};
1543
1544/**
1545 * Document sorting and removing duplicates
1546 * @param {ArrayLike} results
1547 */
1548Sizzle.uniqueSort = function( results ) {
1549	var elem,
1550		duplicates = [],
1551		j = 0,
1552		i = 0;
1553
1554	// Unless we *know* we can detect duplicates, assume their presence
1555	hasDuplicate = !support.detectDuplicates;
1556	sortInput = !support.sortStable && results.slice( 0 );
1557	results.sort( sortOrder );
1558
1559	if ( hasDuplicate ) {
1560		while ( (elem = results[i++]) ) {
1561			if ( elem === results[ i ] ) {
1562				j = duplicates.push( i );
1563			}
1564		}
1565		while ( j-- ) {
1566			results.splice( duplicates[ j ], 1 );
1567		}
1568	}
1569
1570	// Clear input after sorting to release objects
1571	// See https://github.com/jquery/sizzle/pull/225
1572	sortInput = null;
1573
1574	return results;
1575};
1576
1577/**
1578 * Utility function for retrieving the text value of an array of DOM nodes
1579 * @param {Array|Element} elem
1580 */
1581getText = Sizzle.getText = function( elem ) {
1582	var node,
1583		ret = "",
1584		i = 0,
1585		nodeType = elem.nodeType;
1586
1587	if ( !nodeType ) {
1588		// If no nodeType, this is expected to be an array
1589		while ( (node = elem[i++]) ) {
vendor: 11,976 bytes, lines 1590-1988
1590			// Do not traverse comment nodes
1591			ret += getText( node );
1592		}
1593	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1594		// Use textContent for elements
1595		// innerText usage removed for consistency of new lines (jQuery #11153)
1596		if ( typeof elem.textContent === "string" ) {
1597			return elem.textContent;
1598		} else {
1599			// Traverse its children
1600			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1601				ret += getText( elem );
1602			}
1603		}
1604	} else if ( nodeType === 3 || nodeType === 4 ) {
1605		return elem.nodeValue;
1606	}
1607	// Do not include comment or processing instruction nodes
1608
1609	return ret;
1610};
1611
1612Expr = Sizzle.selectors = {
1613
1614	// Can be adjusted by the user
1615	cacheLength: 50,
1616
1617	createPseudo: markFunction,
1618
1619	match: matchExpr,
1620
1621	attrHandle: {},
1622
1623	find: {},
1624
1625	relative: {
1626		">": { dir: "parentNode", first: true },
1627		" ": { dir: "parentNode" },
1628		"+": { dir: "previousSibling", first: true },
1629		"~": { dir: "previousSibling" }
1630	},
1631
1632	preFilter: {
1633		"ATTR": function( match ) {
1634			match[1] = match[1].replace( runescape, funescape );
1635
1636			// Move the given value to match[3] whether quoted or unquoted
1637			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1638
1639			if ( match[2] === "~=" ) {
1640				match[3] = " " + match[3] + " ";
1641			}
1642
1643			return match.slice( 0, 4 );
1644		},
1645
1646		"CHILD": function( match ) {
1647			/* matches from matchExpr["CHILD"]
1648				1 type (only|nth|...)
1649				2 what (child|of-type)
1650				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1651				4 xn-component of xn+y argument ([+-]?\d*n|)
1652				5 sign of xn-component
1653				6 x of xn-component
1654				7 sign of y-component
1655				8 y of y-component
1656			*/
1657			match[1] = match[1].toLowerCase();
1658
1659			if ( match[1].slice( 0, 3 ) === "nth" ) {
1660				// nth-* requires argument
1661				if ( !match[3] ) {
1662					Sizzle.error( match[0] );
1663				}
1664
1665				// numeric x and y parameters for Expr.filter.CHILD
1666				// remember that false/true cast respectively to 0/1
1667				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1668				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1669
1670			// other types prohibit arguments
1671			} else if ( match[3] ) {
1672				Sizzle.error( match[0] );
1673			}
1674
1675			return match;
1676		},
1677
1678		"PSEUDO": function( match ) {
1679			var excess,
1680				unquoted = !match[6] && match[2];
1681
1682			if ( matchExpr["CHILD"].test( match[0] ) ) {
1683				return null;
1684			}
1685
1686			// Accept quoted arguments as-is
1687			if ( match[3] ) {
1688				match[2] = match[4] || match[5] || "";
1689
1690			// Strip excess characters from unquoted arguments
1691			} else if ( unquoted && rpseudo.test( unquoted ) &&
1692				// Get excess from tokenize (recursively)
1693				(excess = tokenize( unquoted, true )) &&
1694				// advance to the next closing parenthesis
1695				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1696
1697				// excess is a negative index
1698				match[0] = match[0].slice( 0, excess );
1699				match[2] = unquoted.slice( 0, excess );
1700			}
1701
1702			// Return only captures needed by the pseudo filter method (type and argument)
1703			return match.slice( 0, 3 );
1704		}
1705	},
1706
1707	filter: {
1708
1709		"TAG": function( nodeNameSelector ) {
1710			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1711			return nodeNameSelector === "*" ?
1712				function() { return true; } :
1713				function( elem ) {
1714					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1715				};
1716		},
1717
1718		"CLASS": function( className ) {
1719			var pattern = classCache[ className + " " ];
1720
1721			return pattern ||
1722				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1723				classCache( className, function( elem ) {
1724					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1725				});
1726		},
1727
1728		"ATTR": function( name, operator, check ) {
1729			return function( elem ) {
1730				var result = Sizzle.attr( elem, name );
1731
1732				if ( result == null ) {
1733					return operator === "!=";
1734				}
1735				if ( !operator ) {
1736					return true;
1737				}
1738
1739				result += "";
1740
1741				return operator === "=" ? result === check :
1742					operator === "!=" ? result !== check :
1743					operator === "^=" ? check && result.indexOf( check ) === 0 :
1744					operator === "*=" ? check && result.indexOf( check ) > -1 :
1745					operator === "$=" ? check && result.slice( -check.length ) === check :
1746					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1747					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1748					false;
1749			};
1750		},
1751
1752		"CHILD": function( type, what, argument, first, last ) {
1753			var simple = type.slice( 0, 3 ) !== "nth",
1754				forward = type.slice( -4 ) !== "last",
1755				ofType = what === "of-type";
1756
1757			return first === 1 && last === 0 ?
1758
1759				// Shortcut for :nth-*(n)
1760				function( elem ) {
1761					return !!elem.parentNode;
1762				} :
1763
1764				function( elem, context, xml ) {
1765					var cache, uniqueCache, outerCache, node, nodeIndex, start,
1766						dir = simple !== forward ? "nextSibling" : "previousSibling",
1767						parent = elem.parentNode,
1768						name = ofType && elem.nodeName.toLowerCase(),
1769						useCache = !xml && !ofType,
1770						diff = false;
1771
1772					if ( parent ) {
1773
1774						// :(first|last|only)-(child|of-type)
1775						if ( simple ) {
1776							while ( dir ) {
1777								node = elem;
1778								while ( (node = node[ dir ]) ) {
1779									if ( ofType ?
1780										node.nodeName.toLowerCase() === name :
1781										node.nodeType === 1 ) {
1782
1783										return false;
1784									}
1785								}
1786								// Reverse direction for :only-* (if we haven't yet done so)
1787								start = dir = type === "only" && !start && "nextSibling";
1788							}
1789							return true;
1790						}
1791
1792						start = [ forward ? parent.firstChild : parent.lastChild ];
1793
1794						// non-xml :nth-child(...) stores cache data on `parent`
1795						if ( forward && useCache ) {
1796
1797							// Seek `elem` from a previously-cached index
1798
1799							// ...in a gzip-friendly way
1800							node = parent;
1801							outerCache = node[ expando ] || (node[ expando ] = {});
1802
1803							// Support: IE <9 only
1804							// Defend against cloned attroperties (jQuery gh-1709)
1805							uniqueCache = outerCache[ node.uniqueID ] ||
1806								(outerCache[ node.uniqueID ] = {});
1807
1808							cache = uniqueCache[ type ] || [];
1809							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1810							diff = nodeIndex && cache[ 2 ];
1811							node = nodeIndex && parent.childNodes[ nodeIndex ];
1812
1813							while ( (node = ++nodeIndex && node && node[ dir ] ||
1814
1815								// Fallback to seeking `elem` from the start
1816								(diff = nodeIndex = 0) || start.pop()) ) {
1817
1818								// When found, cache indexes on `parent` and break
1819								if ( node.nodeType === 1 && ++diff && node === elem ) {
1820									uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
1821									break;
1822								}
1823							}
1824
1825						} else {
1826							// Use previously-cached element index if available
1827							if ( useCache ) {
1828								// ...in a gzip-friendly way
1829								node = elem;
1830								outerCache = node[ expando ] || (node[ expando ] = {});
1831
1832								// Support: IE <9 only
1833								// Defend against cloned attroperties (jQuery gh-1709)
1834								uniqueCache = outerCache[ node.uniqueID ] ||
1835									(outerCache[ node.uniqueID ] = {});
1836
1837								cache = uniqueCache[ type ] || [];
1838								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
1839								diff = nodeIndex;
1840							}
1841
1842							// xml :nth-child(...)
1843							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
1844							if ( diff === false ) {
1845								// Use the same loop as above to seek `elem` from the start
1846								while ( (node = ++nodeIndex && node && node[ dir ] ||
1847									(diff = nodeIndex = 0) || start.pop()) ) {
1848
1849									if ( ( ofType ?
1850										node.nodeName.toLowerCase() === name :
1851										node.nodeType === 1 ) &&
1852										++diff ) {
1853
1854										// Cache the index of each encountered element
1855										if ( useCache ) {
1856											outerCache = node[ expando ] || (node[ expando ] = {});
1857
1858											// Support: IE <9 only
1859											// Defend against cloned attroperties (jQuery gh-1709)
1860											uniqueCache = outerCache[ node.uniqueID ] ||
1861												(outerCache[ node.uniqueID ] = {});
1862
1863											uniqueCache[ type ] = [ dirruns, diff ];
1864										}
1865
1866										if ( node === elem ) {
1867											break;
1868										}
1869									}
1870								}
1871							}
1872						}
1873
1874						// Incorporate the offset, then check against cycle size
1875						diff -= last;
1876						return diff === first || ( diff % first === 0 && diff / first >= 0 );
1877					}
1878				};
1879		},
1880
1881		"PSEUDO": function( pseudo, argument ) {
1882			// pseudo-class names are case-insensitive
1883			// http://www.w3.org/TR/selectors/#pseudo-classes
1884			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1885			// Remember that setFilters inherits from pseudos
1886			var args,
1887				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1888					Sizzle.error( "unsupported pseudo: " + pseudo );
1889
1890			// The user may use createPseudo to indicate that
1891			// arguments are needed to create the filter function
1892			// just as Sizzle does
1893			if ( fn[ expando ] ) {
1894				return fn( argument );
1895			}
1896
1897			// But maintain support for old signatures
1898			if ( fn.length > 1 ) {
1899				args = [ pseudo, pseudo, "", argument ];
1900				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1901					markFunction(function( seed, matches ) {
1902						var idx,
1903							matched = fn( seed, argument ),
1904							i = matched.length;
1905						while ( i-- ) {
1906							idx = indexOf( seed, matched[i] );
1907							seed[ idx ] = !( matches[ idx ] = matched[i] );
1908						}
1909					}) :
1910					function( elem ) {
1911						return fn( elem, 0, args );
1912					};
1913			}
1914
1915			return fn;
1916		}
1917	},
1918
1919	pseudos: {
1920		// Potentially complex pseudos
1921		"not": markFunction(function( selector ) {
1922			// Trim the selector passed to compile
1923			// to avoid treating leading and trailing
1924			// spaces as combinators
1925			var input = [],
1926				results = [],
1927				matcher = compile( selector.replace( rtrim, "$1" ) );
1928
1929			return matcher[ expando ] ?
1930				markFunction(function( seed, matches, context, xml ) {
1931					var elem,
1932						unmatched = matcher( seed, null, xml, [] ),
1933						i = seed.length;
1934
1935					// Match elements unmatched by `matcher`
1936					while ( i-- ) {
1937						if ( (elem = unmatched[i]) ) {
1938							seed[i] = !(matches[i] = elem);
1939						}
1940					}
1941				}) :
1942				function( elem, context, xml ) {
1943					input[0] = elem;
1944					matcher( input, null, xml, results );
1945					// Don't keep the element (issue #299)
1946					input[0] = null;
1947					return !results.pop();
1948				};
1949		}),
1950
1951		"has": markFunction(function( selector ) {
1952			return function( elem ) {
1953				return Sizzle( selector, elem ).length > 0;
1954			};
1955		}),
1956
1957		"contains": markFunction(function( text ) {
1958			text = text.replace( runescape, funescape );
1959			return function( elem ) {
1960				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
1961			};
1962		}),
1963
1964		// "Whether an element is represented by a :lang() selector
1965		// is based solely on the element's language value
1966		// being equal to the identifier C,
1967		// or beginning with the identifier C immediately followed by "-".
1968		// The matching of C against the element's language value is performed case-insensitively.
1969		// The identifier C does not have to be a valid language name."
1970		// http://www.w3.org/TR/selectors/#lang-pseudo
1971		"lang": markFunction( function( lang ) {
1972			// lang value must be a valid identifier
1973			if ( !ridentifier.test(lang || "") ) {
1974				Sizzle.error( "unsupported lang: " + lang );
1975			}
1976			lang = lang.replace( runescape, funescape ).toLowerCase();
1977			return function( elem ) {
1978				var elemLang;
1979				do {
1980					if ( (elemLang = documentIsHTML ?
1981						elem.lang :
1982						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
1983
1984						elemLang = elemLang.toLowerCase();
1985						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1986					}
1987				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
1988				return false;
vendor: 23,967 bytes, lines 1989-2860
1989			};
1990		}),
1991
1992		// Miscellaneous
1993		"target": function( elem ) {
1994			var hash = window.location && window.location.hash;
1995			return hash && hash.slice( 1 ) === elem.id;
1996		},
1997
1998		"root": function( elem ) {
1999			return elem === docElem;
2000		},
2001
2002		"focus": function( elem ) {
2003			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
2004		},
2005
2006		// Boolean properties
2007		"enabled": createDisabledPseudo( false ),
2008		"disabled": createDisabledPseudo( true ),
2009
2010		"checked": function( elem ) {
2011			// In CSS3, :checked should return both checked and selected elements
2012			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2013			var nodeName = elem.nodeName.toLowerCase();
2014			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
2015		},
2016
2017		"selected": function( elem ) {
2018			// Accessing this property makes selected-by-default
2019			// options in Safari work properly
2020			if ( elem.parentNode ) {
2021				elem.parentNode.selectedIndex;
2022			}
2023
2024			return elem.selected === true;
2025		},
2026
2027		// Contents
2028		"empty": function( elem ) {
2029			// http://www.w3.org/TR/selectors/#empty-pseudo
2030			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
2031			//   but not by others (comment: 8; processing instruction: 7; etc.)
2032			// nodeType < 6 works because attributes (2) do not appear as children
2033			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2034				if ( elem.nodeType < 6 ) {
2035					return false;
2036				}
2037			}
2038			return true;
2039		},
2040
2041		"parent": function( elem ) {
2042			return !Expr.pseudos["empty"]( elem );
2043		},
2044
2045		// Element/input types
2046		"header": function( elem ) {
2047			return rheader.test( elem.nodeName );
2048		},
2049
2050		"input": function( elem ) {
2051			return rinputs.test( elem.nodeName );
2052		},
2053
2054		"button": function( elem ) {
2055			var name = elem.nodeName.toLowerCase();
2056			return name === "input" && elem.type === "button" || name === "button";
2057		},
2058
2059		"text": function( elem ) {
2060			var attr;
2061			return elem.nodeName.toLowerCase() === "input" &&
2062				elem.type === "text" &&
2063
2064				// Support: IE<8
2065				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
2066				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
2067		},
2068
2069		// Position-in-collection
2070		"first": createPositionalPseudo(function() {
2071			return [ 0 ];
2072		}),
2073
2074		"last": createPositionalPseudo(function( matchIndexes, length ) {
2075			return [ length - 1 ];
2076		}),
2077
2078		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2079			return [ argument < 0 ? argument + length : argument ];
2080		}),
2081
2082		"even": createPositionalPseudo(function( matchIndexes, length ) {
2083			var i = 0;
2084			for ( ; i < length; i += 2 ) {
2085				matchIndexes.push( i );
2086			}
2087			return matchIndexes;
2088		}),
2089
2090		"odd": createPositionalPseudo(function( matchIndexes, length ) {
2091			var i = 1;
2092			for ( ; i < length; i += 2 ) {
2093				matchIndexes.push( i );
2094			}
2095			return matchIndexes;
2096		}),
2097
2098		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2099			var i = argument < 0 ? argument + length : argument;
2100			for ( ; --i >= 0; ) {
2101				matchIndexes.push( i );
2102			}
2103			return matchIndexes;
2104		}),
2105
2106		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2107			var i = argument < 0 ? argument + length : argument;
2108			for ( ; ++i < length; ) {
2109				matchIndexes.push( i );
2110			}
2111			return matchIndexes;
2112		})
2113	}
2114};
2115
2116Expr.pseudos["nth"] = Expr.pseudos["eq"];
2117
2118// Add button/input type pseudos
2119for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2120	Expr.pseudos[ i ] = createInputPseudo( i );
2121}
2122for ( i in { submit: true, reset: true } ) {
2123	Expr.pseudos[ i ] = createButtonPseudo( i );
2124}
2125
2126// Easy API for creating new setFilters
2127function setFilters() {}
2128setFilters.prototype = Expr.filters = Expr.pseudos;
2129Expr.setFilters = new setFilters();
2130
2131tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2132	var matched, match, tokens, type,
2133		soFar, groups, preFilters,
2134		cached = tokenCache[ selector + " " ];
2135
2136	if ( cached ) {
2137		return parseOnly ? 0 : cached.slice( 0 );
2138	}
2139
2140	soFar = selector;
2141	groups = [];
2142	preFilters = Expr.preFilter;
2143
2144	while ( soFar ) {
2145
2146		// Comma and first run
2147		if ( !matched || (match = rcomma.exec( soFar )) ) {
2148			if ( match ) {
2149				// Don't consume trailing commas as valid
2150				soFar = soFar.slice( match[0].length ) || soFar;
2151			}
2152			groups.push( (tokens = []) );
2153		}
2154
2155		matched = false;
2156
2157		// Combinators
2158		if ( (match = rcombinators.exec( soFar )) ) {
2159			matched = match.shift();
2160			tokens.push({
2161				value: matched,
2162				// Cast descendant combinators to space
2163				type: match[0].replace( rtrim, " " )
2164			});
2165			soFar = soFar.slice( matched.length );
2166		}
2167
2168		// Filters
2169		for ( type in Expr.filter ) {
2170			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2171				(match = preFilters[ type ]( match ))) ) {
2172				matched = match.shift();
2173				tokens.push({
2174					value: matched,
2175					type: type,
2176					matches: match
2177				});
2178				soFar = soFar.slice( matched.length );
2179			}
2180		}
2181
2182		if ( !matched ) {
2183			break;
2184		}
2185	}
2186
2187	// Return the length of the invalid excess
2188	// if we're just parsing
2189	// Otherwise, throw an error or return tokens
2190	return parseOnly ?
2191		soFar.length :
2192		soFar ?
2193			Sizzle.error( selector ) :
2194			// Cache the tokens
2195			tokenCache( selector, groups ).slice( 0 );
2196};
2197
2198function toSelector( tokens ) {
2199	var i = 0,
2200		len = tokens.length,
2201		selector = "";
2202	for ( ; i < len; i++ ) {
2203		selector += tokens[i].value;
2204	}
2205	return selector;
2206}
2207
2208function addCombinator( matcher, combinator, base ) {
2209	var dir = combinator.dir,
2210		skip = combinator.next,
2211		key = skip || dir,
2212		checkNonElements = base && key === "parentNode",
2213		doneName = done++;
2214
2215	return combinator.first ?
2216		// Check against closest ancestor/preceding element
2217		function( elem, context, xml ) {
2218			while ( (elem = elem[ dir ]) ) {
2219				if ( elem.nodeType === 1 || checkNonElements ) {
2220					return matcher( elem, context, xml );
2221				}
2222			}
2223			return false;
2224		} :
2225
2226		// Check against all ancestor/preceding elements
2227		function( elem, context, xml ) {
2228			var oldCache, uniqueCache, outerCache,
2229				newCache = [ dirruns, doneName ];
2230
2231			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
2232			if ( xml ) {
2233				while ( (elem = elem[ dir ]) ) {
2234					if ( elem.nodeType === 1 || checkNonElements ) {
2235						if ( matcher( elem, context, xml ) ) {
2236							return true;
2237						}
2238					}
2239				}
2240			} else {
2241				while ( (elem = elem[ dir ]) ) {
2242					if ( elem.nodeType === 1 || checkNonElements ) {
2243						outerCache = elem[ expando ] || (elem[ expando ] = {});
2244
2245						// Support: IE <9 only
2246						// Defend against cloned attroperties (jQuery gh-1709)
2247						uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
2248
2249						if ( skip && skip === elem.nodeName.toLowerCase() ) {
2250							elem = elem[ dir ] || elem;
2251						} else if ( (oldCache = uniqueCache[ key ]) &&
2252							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2253
2254							// Assign to newCache so results back-propagate to previous elements
2255							return (newCache[ 2 ] = oldCache[ 2 ]);
2256						} else {
2257							// Reuse newcache so results back-propagate to previous elements
2258							uniqueCache[ key ] = newCache;
2259
2260							// A match means we're done; a fail means we have to keep checking
2261							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2262								return true;
2263							}
2264						}
2265					}
2266				}
2267			}
2268			return false;
2269		};
2270}
2271
2272function elementMatcher( matchers ) {
2273	return matchers.length > 1 ?
2274		function( elem, context, xml ) {
2275			var i = matchers.length;
2276			while ( i-- ) {
2277				if ( !matchers[i]( elem, context, xml ) ) {
2278					return false;
2279				}
2280			}
2281			return true;
2282		} :
2283		matchers[0];
2284}
2285
2286function multipleContexts( selector, contexts, results ) {
2287	var i = 0,
2288		len = contexts.length;
2289	for ( ; i < len; i++ ) {
2290		Sizzle( selector, contexts[i], results );
2291	}
2292	return results;
2293}
2294
2295function condense( unmatched, map, filter, context, xml ) {
2296	var elem,
2297		newUnmatched = [],
2298		i = 0,
2299		len = unmatched.length,
2300		mapped = map != null;
2301
2302	for ( ; i < len; i++ ) {
2303		if ( (elem = unmatched[i]) ) {
2304			if ( !filter || filter( elem, context, xml ) ) {
2305				newUnmatched.push( elem );
2306				if ( mapped ) {
2307					map.push( i );
2308				}
2309			}
2310		}
2311	}
2312
2313	return newUnmatched;
2314}
2315
2316function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2317	if ( postFilter && !postFilter[ expando ] ) {
2318		postFilter = setMatcher( postFilter );
2319	}
2320	if ( postFinder && !postFinder[ expando ] ) {
2321		postFinder = setMatcher( postFinder, postSelector );
2322	}
2323	return markFunction(function( seed, results, context, xml ) {
2324		var temp, i, elem,
2325			preMap = [],
2326			postMap = [],
2327			preexisting = results.length,
2328
2329			// Get initial elements from seed or context
2330			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2331
2332			// Prefilter to get matcher input, preserving a map for seed-results synchronization
2333			matcherIn = preFilter && ( seed || !selector ) ?
2334				condense( elems, preMap, preFilter, context, xml ) :
2335				elems,
2336
2337			matcherOut = matcher ?
2338				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2339				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2340
2341					// ...intermediate processing is necessary
2342					[] :
2343
2344					// ...otherwise use results directly
2345					results :
2346				matcherIn;
2347
2348		// Find primary matches
2349		if ( matcher ) {
2350			matcher( matcherIn, matcherOut, context, xml );
2351		}
2352
2353		// Apply postFilter
2354		if ( postFilter ) {
2355			temp = condense( matcherOut, postMap );
2356			postFilter( temp, [], context, xml );
2357
2358			// Un-match failing elements by moving them back to matcherIn
2359			i = temp.length;
2360			while ( i-- ) {
2361				if ( (elem = temp[i]) ) {
2362					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2363				}
2364			}
2365		}
2366
2367		if ( seed ) {
2368			if ( postFinder || preFilter ) {
2369				if ( postFinder ) {
2370					// Get the final matcherOut by condensing this intermediate into postFinder contexts
2371					temp = [];
2372					i = matcherOut.length;
2373					while ( i-- ) {
2374						if ( (elem = matcherOut[i]) ) {
2375							// Restore matcherIn since elem is not yet a final match
2376							temp.push( (matcherIn[i] = elem) );
2377						}
2378					}
2379					postFinder( null, (matcherOut = []), temp, xml );
2380				}
2381
2382				// Move matched elements from seed to results to keep them synchronized
2383				i = matcherOut.length;
2384				while ( i-- ) {
2385					if ( (elem = matcherOut[i]) &&
2386						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
2387
2388						seed[temp] = !(results[temp] = elem);
2389					}
2390				}
2391			}
2392
2393		// Add elements to results, through postFinder if defined
2394		} else {
2395			matcherOut = condense(
2396				matcherOut === results ?
2397					matcherOut.splice( preexisting, matcherOut.length ) :
2398					matcherOut
2399			);
2400			if ( postFinder ) {
2401				postFinder( null, results, matcherOut, xml );
2402			} else {
2403				push.apply( results, matcherOut );
2404			}
2405		}
2406	});
2407}
2408
2409function matcherFromTokens( tokens ) {
2410	var checkContext, matcher, j,
2411		len = tokens.length,
2412		leadingRelative = Expr.relative[ tokens[0].type ],
2413		implicitRelative = leadingRelative || Expr.relative[" "],
2414		i = leadingRelative ? 1 : 0,
2415
2416		// The foundational matcher ensures that elements are reachable from top-level context(s)
2417		matchContext = addCombinator( function( elem ) {
2418			return elem === checkContext;
2419		}, implicitRelative, true ),
2420		matchAnyContext = addCombinator( function( elem ) {
2421			return indexOf( checkContext, elem ) > -1;
2422		}, implicitRelative, true ),
2423		matchers = [ function( elem, context, xml ) {
2424			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2425				(checkContext = context).nodeType ?
2426					matchContext( elem, context, xml ) :
2427					matchAnyContext( elem, context, xml ) );
2428			// Avoid hanging onto element (issue #299)
2429			checkContext = null;
2430			return ret;
2431		} ];
2432
2433	for ( ; i < len; i++ ) {
2434		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2435			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2436		} else {
2437			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2438
2439			// Return special upon seeing a positional matcher
2440			if ( matcher[ expando ] ) {
2441				// Find the next relative operator (if any) for proper handling
2442				j = ++i;
2443				for ( ; j < len; j++ ) {
2444					if ( Expr.relative[ tokens[j].type ] ) {
2445						break;
2446					}
2447				}
2448				return setMatcher(
2449					i > 1 && elementMatcher( matchers ),
2450					i > 1 && toSelector(
2451						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
2452						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2453					).replace( rtrim, "$1" ),
2454					matcher,
2455					i < j && matcherFromTokens( tokens.slice( i, j ) ),
2456					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2457					j < len && toSelector( tokens )
2458				);
2459			}
2460			matchers.push( matcher );
2461		}
2462	}
2463
2464	return elementMatcher( matchers );
2465}
2466
2467function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2468	var bySet = setMatchers.length > 0,
2469		byElement = elementMatchers.length > 0,
2470		superMatcher = function( seed, context, xml, results, outermost ) {
2471			var elem, j, matcher,
2472				matchedCount = 0,
2473				i = "0",
2474				unmatched = seed && [],
2475				setMatched = [],
2476				contextBackup = outermostContext,
2477				// We must always have either seed elements or outermost context
2478				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2479				// Use integer dirruns iff this is the outermost matcher
2480				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2481				len = elems.length;
2482
2483			if ( outermost ) {
2484				outermostContext = context === document || context || outermost;
2485			}
2486
2487			// Add elements passing elementMatchers directly to results
2488			// Support: IE<9, Safari
2489			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2490			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2491				if ( byElement && elem ) {
2492					j = 0;
2493					if ( !context && elem.ownerDocument !== document ) {
2494						setDocument( elem );
2495						xml = !documentIsHTML;
2496					}
2497					while ( (matcher = elementMatchers[j++]) ) {
2498						if ( matcher( elem, context || document, xml) ) {
2499							results.push( elem );
2500							break;
2501						}
2502					}
2503					if ( outermost ) {
2504						dirruns = dirrunsUnique;
2505					}
2506				}
2507
2508				// Track unmatched elements for set filters
2509				if ( bySet ) {
2510					// They will have gone through all possible matchers
2511					if ( (elem = !matcher && elem) ) {
2512						matchedCount--;
2513					}
2514
2515					// Lengthen the array for every element, matched or not
2516					if ( seed ) {
2517						unmatched.push( elem );
2518					}
2519				}
2520			}
2521
2522			// `i` is now the count of elements visited above, and adding it to `matchedCount`
2523			// makes the latter nonnegative.
2524			matchedCount += i;
2525
2526			// Apply set filters to unmatched elements
2527			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
2528			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
2529			// no element matchers and no seed.
2530			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
2531			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
2532			// numerically zero.
2533			if ( bySet && i !== matchedCount ) {
2534				j = 0;
2535				while ( (matcher = setMatchers[j++]) ) {
2536					matcher( unmatched, setMatched, context, xml );
2537				}
2538
2539				if ( seed ) {
2540					// Reintegrate element matches to eliminate the need for sorting
2541					if ( matchedCount > 0 ) {
2542						while ( i-- ) {
2543							if ( !(unmatched[i] || setMatched[i]) ) {
2544								setMatched[i] = pop.call( results );
2545							}
2546						}
2547					}
2548
2549					// Discard index placeholder values to get only actual matches
2550					setMatched = condense( setMatched );
2551				}
2552
2553				// Add matches to results
2554				push.apply( results, setMatched );
2555
2556				// Seedless set matches succeeding multiple successful matchers stipulate sorting
2557				if ( outermost && !seed && setMatched.length > 0 &&
2558					( matchedCount + setMatchers.length ) > 1 ) {
2559
2560					Sizzle.uniqueSort( results );
2561				}
2562			}
2563
2564			// Override manipulation of globals by nested matchers
2565			if ( outermost ) {
2566				dirruns = dirrunsUnique;
2567				outermostContext = contextBackup;
2568			}
2569
2570			return unmatched;
2571		};
2572
2573	return bySet ?
2574		markFunction( superMatcher ) :
2575		superMatcher;
2576}
2577
2578compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2579	var i,
2580		setMatchers = [],
2581		elementMatchers = [],
2582		cached = compilerCache[ selector + " " ];
2583
2584	if ( !cached ) {
2585		// Generate a function of recursive functions that can be used to check each element
2586		if ( !match ) {
2587			match = tokenize( selector );
2588		}
2589		i = match.length;
2590		while ( i-- ) {
2591			cached = matcherFromTokens( match[i] );
2592			if ( cached[ expando ] ) {
2593				setMatchers.push( cached );
2594			} else {
2595				elementMatchers.push( cached );
2596			}
2597		}
2598
2599		// Cache the compiled function
2600		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2601
2602		// Save selector and tokenization
2603		cached.selector = selector;
2604	}
2605	return cached;
2606};
2607
2608/**
2609 * A low-level selection function that works with Sizzle's compiled
2610 *  selector functions
2611 * @param {String|Function} selector A selector or a pre-compiled
2612 *  selector function built with Sizzle.compile
2613 * @param {Element} context
2614 * @param {Array} [results]
2615 * @param {Array} [seed] A set of elements to match against
2616 */
2617select = Sizzle.select = function( selector, context, results, seed ) {
2618	var i, tokens, token, type, find,
2619		compiled = typeof selector === "function" && selector,
2620		match = !seed && tokenize( (selector = compiled.selector || selector) );
2621
2622	results = results || [];
2623
2624	// Try to minimize operations if there is only one selector in the list and no seed
2625	// (the latter of which guarantees us context)
2626	if ( match.length === 1 ) {
2627
2628		// Reduce context if the leading compound selector is an ID
2629		tokens = match[0] = match[0].slice( 0 );
2630		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2631				context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
2632
2633			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2634			if ( !context ) {
2635				return results;
2636
2637			// Precompiled matchers will still verify ancestry, so step up a level
2638			} else if ( compiled ) {
2639				context = context.parentNode;
2640			}
2641
2642			selector = selector.slice( tokens.shift().value.length );
2643		}
2644
2645		// Fetch a seed set for right-to-left matching
2646		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2647		while ( i-- ) {
2648			token = tokens[i];
2649
2650			// Abort if we hit a combinator
2651			if ( Expr.relative[ (type = token.type) ] ) {
2652				break;
2653			}
2654			if ( (find = Expr.find[ type ]) ) {
2655				// Search, expanding context for leading sibling combinators
2656				if ( (seed = find(
2657					token.matches[0].replace( runescape, funescape ),
2658					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2659				)) ) {
2660
2661					// If seed is empty or no tokens remain, we can return early
2662					tokens.splice( i, 1 );
2663					selector = seed.length && toSelector( tokens );
2664					if ( !selector ) {
2665						push.apply( results, seed );
2666						return results;
2667					}
2668
2669					break;
2670				}
2671			}
2672		}
2673	}
2674
2675	// Compile and execute a filtering function if one is not provided
2676	// Provide `match` to avoid retokenization if we modified the selector above
2677	( compiled || compile( selector, match ) )(
2678		seed,
2679		context,
2680		!documentIsHTML,
2681		results,
2682		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
2683	);
2684	return results;
2685};
2686
2687// One-time assignments
2688
2689// Sort stability
2690support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2691
2692// Support: Chrome 14-35+
2693// Always assume duplicates if they aren't passed to the comparison function
2694support.detectDuplicates = !!hasDuplicate;
2695
2696// Initialize against the default document
2697setDocument();
2698
2699// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2700// Detached nodes confoundingly follow *each other*
2701support.sortDetached = assert(function( el ) {
2702	// Should return 1, but returns 4 (following)
2703	return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
2704});
2705
2706// Support: IE<8
2707// Prevent attribute/property "interpolation"
2708// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2709if ( !assert(function( el ) {
2710	el.innerHTML = "<a href='#'></a>";
2711	return el.firstChild.getAttribute("href") === "#" ;
2712}) ) {
2713	addHandle( "type|href|height|width", function( elem, name, isXML ) {
2714		if ( !isXML ) {
2715			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2716		}
2717	});
2718}
2719
2720// Support: IE<9
2721// Use defaultValue in place of getAttribute("value")
2722if ( !support.attributes || !assert(function( el ) {
2723	el.innerHTML = "<input/>";
2724	el.firstChild.setAttribute( "value", "" );
2725	return el.firstChild.getAttribute( "value" ) === "";
2726}) ) {
2727	addHandle( "value", function( elem, name, isXML ) {
2728		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2729			return elem.defaultValue;
2730		}
2731	});
2732}
2733
2734// Support: IE<9
2735// Use getAttributeNode to fetch booleans when getAttribute lies
2736if ( !assert(function( el ) {
2737	return el.getAttribute("disabled") == null;
2738}) ) {
2739	addHandle( booleans, function( elem, name, isXML ) {
2740		var val;
2741		if ( !isXML ) {
2742			return elem[ name ] === true ? name.toLowerCase() :
2743					(val = elem.getAttributeNode( name )) && val.specified ?
2744					val.value :
2745				null;
2746		}
2747	});
2748}
2749
2750return Sizzle;
2751
2752})( window );
2753
2754
2755
2756jQuery.find = Sizzle;
2757jQuery.expr = Sizzle.selectors;
2758
2759// Deprecated
2760jQuery.expr[ ":" ] = jQuery.expr.pseudos;
2761jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
2762jQuery.text = Sizzle.getText;
2763jQuery.isXMLDoc = Sizzle.isXML;
2764jQuery.contains = Sizzle.contains;
2765jQuery.escapeSelector = Sizzle.escape;
2766
2767
2768
2769
2770var dir = function( elem, dir, until ) {
2771	var matched = [],
2772		truncate = until !== undefined;
2773
2774	while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
2775		if ( elem.nodeType === 1 ) {
2776			if ( truncate && jQuery( elem ).is( until ) ) {
2777				break;
2778			}
2779			matched.push( elem );
2780		}
2781	}
2782	return matched;
2783};
2784
2785
2786var siblings = function( n, elem ) {
2787	var matched = [];
2788
2789	for ( ; n; n = n.nextSibling ) {
2790		if ( n.nodeType === 1 && n !== elem ) {
2791			matched.push( n );
2792		}
2793	}
2794
2795	return matched;
2796};
2797
2798
2799var rneedsContext = jQuery.expr.match.needsContext;
2800
2801
2802
2803function nodeName( elem, name ) {
2804
2805  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
2806
2807};
2808var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
2809
2810
2811
2812// Implement the identical functionality for filter and not
2813function winnow( elements, qualifier, not ) {
2814	if ( isFunction( qualifier ) ) {
2815		return jQuery.grep( elements, function( elem, i ) {
2816			return !!qualifier.call( elem, i, elem ) !== not;
2817		} );
2818	}
2819
2820	// Single element
2821	if ( qualifier.nodeType ) {
2822		return jQuery.grep( elements, function( elem ) {
2823			return ( elem === qualifier ) !== not;
2824		} );
2825	}
2826
2827	// Arraylike of elements (jQuery, arguments, Array)
2828	if ( typeof qualifier !== "string" ) {
2829		return jQuery.grep( elements, function( elem ) {
2830			return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
2831		} );
2832	}
2833
2834	// Filtered directly for both simple and complex selectors
2835	return jQuery.filter( qualifier, elements, not );
2836}
2837
2838jQuery.filter = function( expr, elems, not ) {
2839	var elem = elems[ 0 ];
2840
2841	if ( not ) {
2842		expr = ":not(" + expr + ")";
2843	}
2844
2845	if ( elems.length === 1 && elem.nodeType === 1 ) {
2846		return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
2847	}
2848
2849	return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2850		return elem.nodeType === 1;
2851	} ) );
2852};
2853
2854jQuery.fn.extend( {
2855	find: function( selector ) {
2856		var i, ret,
2857			len = this.length,
2858			self = this;
2859
2860		if ( typeof selector !== "string" ) {
vendor: 4,662 bytes, lines 2861-3046
2861			return this.pushStack( jQuery( selector ).filter( function() {
2862				for ( i = 0; i < len; i++ ) {
2863					if ( jQuery.contains( self[ i ], this ) ) {
2864						return true;
2865					}
2866				}
2867			} ) );
2868		}
2869
2870		ret = this.pushStack( [] );
2871
2872		for ( i = 0; i < len; i++ ) {
2873			jQuery.find( selector, self[ i ], ret );
2874		}
2875
2876		return len > 1 ? jQuery.uniqueSort( ret ) : ret;
2877	},
2878	filter: function( selector ) {
2879		return this.pushStack( winnow( this, selector || [], false ) );
2880	},
2881	not: function( selector ) {
2882		return this.pushStack( winnow( this, selector || [], true ) );
2883	},
2884	is: function( selector ) {
2885		return !!winnow(
2886			this,
2887
2888			// If this is a positional/relative selector, check membership in the returned set
2889			// so $("p:first").is("p:last") won't return true for a doc with two "p".
2890			typeof selector === "string" && rneedsContext.test( selector ) ?
2891				jQuery( selector ) :
2892				selector || [],
2893			false
2894		).length;
2895	}
2896} );
2897
2898
2899// Initialize a jQuery object
2900
2901
2902// A central reference to the root jQuery(document)
2903var rootjQuery,
2904
2905	// A simple way to check for HTML strings
2906	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2907	// Strict HTML recognition (#11290: must start with <)
2908	// Shortcut simple #id case for speed
2909	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
2910
2911	init = jQuery.fn.init = function( selector, context, root ) {
2912		var match, elem;
2913
2914		// HANDLE: $(""), $(null), $(undefined), $(false)
2915		if ( !selector ) {
2916			return this;
2917		}
2918
2919		// Method init() accepts an alternate rootjQuery
2920		// so migrate can support jQuery.sub (gh-2101)
2921		root = root || rootjQuery;
2922
2923		// Handle HTML strings
2924		if ( typeof selector === "string" ) {
2925			if ( selector[ 0 ] === "<" &&
2926				selector[ selector.length - 1 ] === ">" &&
2927				selector.length >= 3 ) {
2928
2929				// Assume that strings that start and end with <> are HTML and skip the regex check
2930				match = [ null, selector, null ];
2931
2932			} else {
2933				match = rquickExpr.exec( selector );
2934			}
2935
2936			// Match html or make sure no context is specified for #id
2937			if ( match && ( match[ 1 ] || !context ) ) {
2938
2939				// HANDLE: $(html) -> $(array)
2940				if ( match[ 1 ] ) {
2941					context = context instanceof jQuery ? context[ 0 ] : context;
2942
2943					// Option to run scripts is true for back-compat
2944					// Intentionally let the error be thrown if parseHTML is not present
2945					jQuery.merge( this, jQuery.parseHTML(
2946						match[ 1 ],
2947						context && context.nodeType ? context.ownerDocument || context : document,
2948						true
2949					) );
2950
2951					// HANDLE: $(html, props)
2952					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
2953						for ( match in context ) {
2954
2955							// Properties of context are called as methods if possible
2956							if ( isFunction( this[ match ] ) ) {
2957								this[ match ]( context[ match ] );
2958
2959							// ...and otherwise set as attributes
2960							} else {
2961								this.attr( match, context[ match ] );
2962							}
2963						}
2964					}
2965
2966					return this;
2967
2968				// HANDLE: $(#id)
2969				} else {
2970					elem = document.getElementById( match[ 2 ] );
2971
2972					if ( elem ) {
2973
2974						// Inject the element directly into the jQuery object
2975						this[ 0 ] = elem;
2976						this.length = 1;
2977					}
2978					return this;
2979				}
2980
2981			// HANDLE: $(expr, $(...))
2982			} else if ( !context || context.jquery ) {
2983				return ( context || root ).find( selector );
2984
2985			// HANDLE: $(expr, context)
2986			// (which is just equivalent to: $(context).find(expr)
2987			} else {
2988				return this.constructor( context ).find( selector );
2989			}
2990
2991		// HANDLE: $(DOMElement)
2992		} else if ( selector.nodeType ) {
2993			this[ 0 ] = selector;
2994			this.length = 1;
2995			return this;
2996
2997		// HANDLE: $(function)
2998		// Shortcut for document ready
2999		} else if ( isFunction( selector ) ) {
3000			return root.ready !== undefined ?
3001				root.ready( selector ) :
3002
3003				// Execute immediately if ready is not present
3004				selector( jQuery );
3005		}
3006
3007		return jQuery.makeArray( selector, this );
3008	};
3009
3010// Give the init function the jQuery prototype for later instantiation
3011init.prototype = jQuery.fn;
3012
3013// Initialize central reference
3014rootjQuery = jQuery( document );
3015
3016
3017var rparentsprev = /^(?:parents|prev(?:Until|All))/,
3018
3019	// Methods guaranteed to produce a unique set when starting from a unique set
3020	guaranteedUnique = {
3021		children: true,
3022		contents: true,
3023		next: true,
3024		prev: true
3025	};
3026
3027jQuery.fn.extend( {
3028	has: function( target ) {
3029		var targets = jQuery( target, this ),
3030			l = targets.length;
3031
3032		return this.filter( function() {
3033			var i = 0;
3034			for ( ; i < l; i++ ) {
3035				if ( jQuery.contains( this, targets[ i ] ) ) {
3036					return true;
3037				}
3038			}
3039		} );
3040	},
3041
3042	closest: function( selectors, context ) {
3043		var cur,
3044			i = 0,
3045			l = this.length,
3046			matched = [],
vendor: 6,003 bytes, lines 3047-3273
3047			targets = typeof selectors !== "string" && jQuery( selectors );
3048
3049		// Positional selectors never match, since there's no _selection_ context
3050		if ( !rneedsContext.test( selectors ) ) {
3051			for ( ; i < l; i++ ) {
3052				for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
3053
3054					// Always skip document fragments
3055					if ( cur.nodeType < 11 && ( targets ?
3056						targets.index( cur ) > -1 :
3057
3058						// Don't pass non-elements to Sizzle
3059						cur.nodeType === 1 &&
3060							jQuery.find.matchesSelector( cur, selectors ) ) ) {
3061
3062						matched.push( cur );
3063						break;
3064					}
3065				}
3066			}
3067		}
3068
3069		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
3070	},
3071
3072	// Determine the position of an element within the set
3073	index: function( elem ) {
3074
3075		// No argument, return index in parent
3076		if ( !elem ) {
3077			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
3078		}
3079
3080		// Index in selector
3081		if ( typeof elem === "string" ) {
3082			return indexOf.call( jQuery( elem ), this[ 0 ] );
3083		}
3084
3085		// Locate the position of the desired element
3086		return indexOf.call( this,
3087
3088			// If it receives a jQuery object, the first element is used
3089			elem.jquery ? elem[ 0 ] : elem
3090		);
3091	},
3092
3093	add: function( selector, context ) {
3094		return this.pushStack(
3095			jQuery.uniqueSort(
3096				jQuery.merge( this.get(), jQuery( selector, context ) )
3097			)
3098		);
3099	},
3100
3101	addBack: function( selector ) {
3102		return this.add( selector == null ?
3103			this.prevObject : this.prevObject.filter( selector )
3104		);
3105	}
3106} );
3107
3108function sibling( cur, dir ) {
3109	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
3110	return cur;
3111}
3112
3113jQuery.each( {
3114	parent: function( elem ) {
3115		var parent = elem.parentNode;
3116		return parent && parent.nodeType !== 11 ? parent : null;
3117	},
3118	parents: function( elem ) {
3119		return dir( elem, "parentNode" );
3120	},
3121	parentsUntil: function( elem, i, until ) {
3122		return dir( elem, "parentNode", until );
3123	},
3124	next: function( elem ) {
3125		return sibling( elem, "nextSibling" );
3126	},
3127	prev: function( elem ) {
3128		return sibling( elem, "previousSibling" );
3129	},
3130	nextAll: function( elem ) {
3131		return dir( elem, "nextSibling" );
3132	},
3133	prevAll: function( elem ) {
3134		return dir( elem, "previousSibling" );
3135	},
3136	nextUntil: function( elem, i, until ) {
3137		return dir( elem, "nextSibling", until );
3138	},
3139	prevUntil: function( elem, i, until ) {
3140		return dir( elem, "previousSibling", until );
3141	},
3142	siblings: function( elem ) {
3143		return siblings( ( elem.parentNode || {} ).firstChild, elem );
3144	},
3145	children: function( elem ) {
3146		return siblings( elem.firstChild );
3147	},
3148	contents: function( elem ) {
3149        if ( nodeName( elem, "iframe" ) ) {
3150            return elem.contentDocument;
3151        }
3152
3153        // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
3154        // Treat the template element as a regular one in browsers that
3155        // don't support it.
3156        if ( nodeName( elem, "template" ) ) {
3157            elem = elem.content || elem;
3158        }
3159
3160        return jQuery.merge( [], elem.childNodes );
3161	}
3162}, function( name, fn ) {
3163	jQuery.fn[ name ] = function( until, selector ) {
3164		var matched = jQuery.map( this, fn, until );
3165
3166		if ( name.slice( -5 ) !== "Until" ) {
3167			selector = until;
3168		}
3169
3170		if ( selector && typeof selector === "string" ) {
3171			matched = jQuery.filter( selector, matched );
3172		}
3173
3174		if ( this.length > 1 ) {
3175
3176			// Remove duplicates
3177			if ( !guaranteedUnique[ name ] ) {
3178				jQuery.uniqueSort( matched );
3179			}
3180
3181			// Reverse order for parents* and prev-derivatives
3182			if ( rparentsprev.test( name ) ) {
3183				matched.reverse();
3184			}
3185		}
3186
3187		return this.pushStack( matched );
3188	};
3189} );
3190var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
3191
3192
3193
3194// Convert String-formatted options into Object-formatted ones
3195function createOptions( options ) {
3196	var object = {};
3197	jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
3198		object[ flag ] = true;
3199	} );
3200	return object;
3201}
3202
3203/*
3204 * Create a callback list using the following parameters:
3205 *
3206 *	options: an optional list of space-separated options that will change how
3207 *			the callback list behaves or a more traditional option object
3208 *
3209 * By default a callback list will act like an event callback list and can be
3210 * "fired" multiple times.
3211 *
3212 * Possible options:
3213 *
3214 *	once:			will ensure the callback list can only be fired once (like a Deferred)
3215 *
3216 *	memory:			will keep track of previous values and will call any callback added
3217 *					after the list has been fired right away with the latest "memorized"
3218 *					values (like a Deferred)
3219 *
3220 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
3221 *
3222 *	stopOnFalse:	interrupt callings when a callback returns false
3223 *
3224 */
3225jQuery.Callbacks = function( options ) {
3226
3227	// Convert options from String-formatted to Object-formatted if needed
3228	// (we check in cache first)
3229	options = typeof options === "string" ?
3230		createOptions( options ) :
3231		jQuery.extend( {}, options );
3232
3233	var // Flag to know if list is currently firing
3234		firing,
3235
3236		// Last fire value for non-forgettable lists
3237		memory,
3238
3239		// Flag to know if list was already fired
3240		fired,
3241
3242		// Flag to prevent firing
3243		locked,
3244
3245		// Actual callback list
3246		list = [],
3247
3248		// Queue of execution data for repeatable lists
3249		queue = [],
3250
3251		// Index of currently firing callback (modified by add/remove as needed)
3252		firingIndex = -1,
3253
3254		// Fire callbacks
3255		fire = function() {
3256
3257			// Enforce single-firing
3258			locked = locked || options.once;
3259
3260			// Execute callbacks for all pending executions,
3261			// respecting firingIndex overrides and runtime changes
3262			fired = firing = true;
3263			for ( ; queue.length; firingIndex = -1 ) {
3264				memory = queue.shift();
3265				while ( ++firingIndex < list.length ) {
3266
3267					// Run callback and check for early termination
3268					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
3269						options.stopOnFalse ) {
3270
3271						// Jump to end and forget the data so .add doesn't re-fire
3272						firingIndex = list.length;
3273						memory = false;
vendor: 4,918 bytes, lines 3274-3483
3274					}
3275				}
3276			}
3277
3278			// Forget the data if we're done with it
3279			if ( !options.memory ) {
3280				memory = false;
3281			}
3282
3283			firing = false;
3284
3285			// Clean up if we're done firing for good
3286			if ( locked ) {
3287
3288				// Keep an empty list if we have data for future add calls
3289				if ( memory ) {
3290					list = [];
3291
3292				// Otherwise, this object is spent
3293				} else {
3294					list = "";
3295				}
3296			}
3297		},
3298
3299		// Actual Callbacks object
3300		self = {
3301
3302			// Add a callback or a collection of callbacks to the list
3303			add: function() {
3304				if ( list ) {
3305
3306					// If we have memory from a past run, we should fire after adding
3307					if ( memory && !firing ) {
3308						firingIndex = list.length - 1;
3309						queue.push( memory );
3310					}
3311
3312					( function add( args ) {
3313						jQuery.each( args, function( _, arg ) {
3314							if ( isFunction( arg ) ) {
3315								if ( !options.unique || !self.has( arg ) ) {
3316									list.push( arg );
3317								}
3318							} else if ( arg && arg.length && toType( arg ) !== "string" ) {
3319
3320								// Inspect recursively
3321								add( arg );
3322							}
3323						} );
3324					} )( arguments );
3325
3326					if ( memory && !firing ) {
3327						fire();
3328					}
3329				}
3330				return this;
3331			},
3332
3333			// Remove a callback from the list
3334			remove: function() {
3335				jQuery.each( arguments, function( _, arg ) {
3336					var index;
3337					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3338						list.splice( index, 1 );
3339
3340						// Handle firing indexes
3341						if ( index <= firingIndex ) {
3342							firingIndex--;
3343						}
3344					}
3345				} );
3346				return this;
3347			},
3348
3349			// Check if a given callback is in the list.
3350			// If no argument is given, return whether or not list has callbacks attached.
3351			has: function( fn ) {
3352				return fn ?
3353					jQuery.inArray( fn, list ) > -1 :
3354					list.length > 0;
3355			},
3356
3357			// Remove all callbacks from the list
3358			empty: function() {
3359				if ( list ) {
3360					list = [];
3361				}
3362				return this;
3363			},
3364
3365			// Disable .fire and .add
3366			// Abort any current/pending executions
3367			// Clear all callbacks and values
3368			disable: function() {
3369				locked = queue = [];
3370				list = memory = "";
3371				return this;
3372			},
3373			disabled: function() {
3374				return !list;
3375			},
3376
3377			// Disable .fire
3378			// Also disable .add unless we have memory (since it would have no effect)
3379			// Abort any pending executions
3380			lock: function() {
3381				locked = queue = [];
3382				if ( !memory && !firing ) {
3383					list = memory = "";
3384				}
3385				return this;
3386			},
3387			locked: function() {
3388				return !!locked;
3389			},
3390
3391			// Call all callbacks with the given context and arguments
3392			fireWith: function( context, args ) {
3393				if ( !locked ) {
3394					args = args || [];
3395					args = [ context, args.slice ? args.slice() : args ];
3396					queue.push( args );
3397					if ( !firing ) {
3398						fire();
3399					}
3400				}
3401				return this;
3402			},
3403
3404			// Call all the callbacks with the given arguments
3405			fire: function() {
3406				self.fireWith( this, arguments );
3407				return this;
3408			},
3409
3410			// To know if the callbacks have already been called at least once
3411			fired: function() {
3412				return !!fired;
3413			}
3414		};
3415
3416	return self;
3417};
3418
3419
3420function Identity( v ) {
3421	return v;
3422}
3423function Thrower( ex ) {
3424	throw ex;
3425}
3426
3427function adoptValue( value, resolve, reject, noValue ) {
3428	var method;
3429
3430	try {
3431
3432		// Check for promise aspect first to privilege synchronous behavior
3433		if ( value && isFunction( ( method = value.promise ) ) ) {
3434			method.call( value ).done( resolve ).fail( reject );
3435
3436		// Other thenables
3437		} else if ( value && isFunction( ( method = value.then ) ) ) {
3438			method.call( value, resolve, reject );
3439
3440		// Other non-thenables
3441		} else {
3442
3443			// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
3444			// * false: [ value ].slice( 0 ) => resolve( value )
3445			// * true: [ value ].slice( 1 ) => resolve()
3446			resolve.apply( undefined, [ value ].slice( noValue ) );
3447		}
3448
3449	// For Promises/A+, convert exceptions into rejections
3450	// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
3451	// Deferred#then to conditionally suppress rejection.
3452	} catch ( value ) {
3453
3454		// Support: Android 4.0 only
3455		// Strict mode functions invoked without .call/.apply get global-object context
3456		reject.apply( undefined, [ value ] );
3457	}
3458}
3459
3460jQuery.extend( {
3461
3462	Deferred: function( func ) {
3463		var tuples = [
3464
3465				// action, add listener, callbacks,
3466				// ... .then handlers, argument index, [final state]
3467				[ "notify", "progress", jQuery.Callbacks( "memory" ),
3468					jQuery.Callbacks( "memory" ), 2 ],
3469				[ "resolve", "done", jQuery.Callbacks( "once memory" ),
3470					jQuery.Callbacks( "once memory" ), 0, "resolved" ],
3471				[ "reject", "fail", jQuery.Callbacks( "once memory" ),
3472					jQuery.Callbacks( "once memory" ), 1, "rejected" ]
3473			],
3474			state = "pending",
3475			promise = {
3476				state: function() {
3477					return state;
3478				},
3479				always: function() {
3480					deferred.done( arguments ).fail( arguments );
3481					return this;
3482				},
3483				"catch": function( fn ) {
vendor: 15,167 bytes, lines 3484-4075
3484					return promise.then( null, fn );
3485				},
3486
3487				// Keep pipe for back-compat
3488				pipe: function( /* fnDone, fnFail, fnProgress */ ) {
3489					var fns = arguments;
3490
3491					return jQuery.Deferred( function( newDefer ) {
3492						jQuery.each( tuples, function( i, tuple ) {
3493
3494							// Map tuples (progress, done, fail) to arguments (done, fail, progress)
3495							var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
3496
3497							// deferred.progress(function() { bind to newDefer or newDefer.notify })
3498							// deferred.done(function() { bind to newDefer or newDefer.resolve })
3499							// deferred.fail(function() { bind to newDefer or newDefer.reject })
3500							deferred[ tuple[ 1 ] ]( function() {
3501								var returned = fn && fn.apply( this, arguments );
3502								if ( returned && isFunction( returned.promise ) ) {
3503									returned.promise()
3504										.progress( newDefer.notify )
3505										.done( newDefer.resolve )
3506										.fail( newDefer.reject );
3507								} else {
3508									newDefer[ tuple[ 0 ] + "With" ](
3509										this,
3510										fn ? [ returned ] : arguments
3511									);
3512								}
3513							} );
3514						} );
3515						fns = null;
3516					} ).promise();
3517				},
3518				then: function( onFulfilled, onRejected, onProgress ) {
3519					var maxDepth = 0;
3520					function resolve( depth, deferred, handler, special ) {
3521						return function() {
3522							var that = this,
3523								args = arguments,
3524								mightThrow = function() {
3525									var returned, then;
3526
3527									// Support: Promises/A+ section 2.3.3.3.3
3528									// https://promisesaplus.com/#point-59
3529									// Ignore double-resolution attempts
3530									if ( depth < maxDepth ) {
3531										return;
3532									}
3533
3534									returned = handler.apply( that, args );
3535
3536									// Support: Promises/A+ section 2.3.1
3537									// https://promisesaplus.com/#point-48
3538									if ( returned === deferred.promise() ) {
3539										throw new TypeError( "Thenable self-resolution" );
3540									}
3541
3542									// Support: Promises/A+ sections 2.3.3.1, 3.5
3543									// https://promisesaplus.com/#point-54
3544									// https://promisesaplus.com/#point-75
3545									// Retrieve `then` only once
3546									then = returned &&
3547
3548										// Support: Promises/A+ section 2.3.4
3549										// https://promisesaplus.com/#point-64
3550										// Only check objects and functions for thenability
3551										( typeof returned === "object" ||
3552											typeof returned === "function" ) &&
3553										returned.then;
3554
3555									// Handle a returned thenable
3556									if ( isFunction( then ) ) {
3557
3558										// Special processors (notify) just wait for resolution
3559										if ( special ) {
3560											then.call(
3561												returned,
3562												resolve( maxDepth, deferred, Identity, special ),
3563												resolve( maxDepth, deferred, Thrower, special )
3564											);
3565
3566										// Normal processors (resolve) also hook into progress
3567										} else {
3568
3569											// ...and disregard older resolution values
3570											maxDepth++;
3571
3572											then.call(
3573												returned,
3574												resolve( maxDepth, deferred, Identity, special ),
3575												resolve( maxDepth, deferred, Thrower, special ),
3576												resolve( maxDepth, deferred, Identity,
3577													deferred.notifyWith )
3578											);
3579										}
3580
3581									// Handle all other returned values
3582									} else {
3583
3584										// Only substitute handlers pass on context
3585										// and multiple values (non-spec behavior)
3586										if ( handler !== Identity ) {
3587											that = undefined;
3588											args = [ returned ];
3589										}
3590
3591										// Process the value(s)
3592										// Default process is resolve
3593										( special || deferred.resolveWith )( that, args );
3594									}
3595								},
3596
3597								// Only normal processors (resolve) catch and reject exceptions
3598								process = special ?
3599									mightThrow :
3600									function() {
3601										try {
3602											mightThrow();
3603										} catch ( e ) {
3604
3605											if ( jQuery.Deferred.exceptionHook ) {
3606												jQuery.Deferred.exceptionHook( e,
3607													process.stackTrace );
3608											}
3609
3610											// Support: Promises/A+ section 2.3.3.3.4.1
3611											// https://promisesaplus.com/#point-61
3612											// Ignore post-resolution exceptions
3613											if ( depth + 1 >= maxDepth ) {
3614
3615												// Only substitute handlers pass on context
3616												// and multiple values (non-spec behavior)
3617												if ( handler !== Thrower ) {
3618													that = undefined;
3619													args = [ e ];
3620												}
3621
3622												deferred.rejectWith( that, args );
3623											}
3624										}
3625									};
3626
3627							// Support: Promises/A+ section 2.3.3.3.1
3628							// https://promisesaplus.com/#point-57
3629							// Re-resolve promises immediately to dodge false rejection from
3630							// subsequent errors
3631							if ( depth ) {
3632								process();
3633							} else {
3634
3635								// Call an optional hook to record the stack, in case of exception
3636								// since it's otherwise lost when execution goes async
3637								if ( jQuery.Deferred.getStackHook ) {
3638									process.stackTrace = jQuery.Deferred.getStackHook();
3639								}
3640								window.setTimeout( process );
3641							}
3642						};
3643					}
3644
3645					return jQuery.Deferred( function( newDefer ) {
3646
3647						// progress_handlers.add( ... )
3648						tuples[ 0 ][ 3 ].add(
3649							resolve(
3650								0,
3651								newDefer,
3652								isFunction( onProgress ) ?
3653									onProgress :
3654									Identity,
3655								newDefer.notifyWith
3656							)
3657						);
3658
3659						// fulfilled_handlers.add( ... )
3660						tuples[ 1 ][ 3 ].add(
3661							resolve(
3662								0,
3663								newDefer,
3664								isFunction( onFulfilled ) ?
3665									onFulfilled :
3666									Identity
3667							)
3668						);
3669
3670						// rejected_handlers.add( ... )
3671						tuples[ 2 ][ 3 ].add(
3672							resolve(
3673								0,
3674								newDefer,
3675								isFunction( onRejected ) ?
3676									onRejected :
3677									Thrower
3678							)
3679						);
3680					} ).promise();
3681				},
3682
3683				// Get a promise for this deferred
3684				// If obj is provided, the promise aspect is added to the object
3685				promise: function( obj ) {
3686					return obj != null ? jQuery.extend( obj, promise ) : promise;
3687				}
3688			},
3689			deferred = {};
3690
3691		// Add list-specific methods
3692		jQuery.each( tuples, function( i, tuple ) {
3693			var list = tuple[ 2 ],
3694				stateString = tuple[ 5 ];
3695
3696			// promise.progress = list.add
3697			// promise.done = list.add
3698			// promise.fail = list.add
3699			promise[ tuple[ 1 ] ] = list.add;
3700
3701			// Handle state
3702			if ( stateString ) {
3703				list.add(
3704					function() {
3705
3706						// state = "resolved" (i.e., fulfilled)
3707						// state = "rejected"
3708						state = stateString;
3709					},
3710
3711					// rejected_callbacks.disable
3712					// fulfilled_callbacks.disable
3713					tuples[ 3 - i ][ 2 ].disable,
3714
3715					// rejected_handlers.disable
3716					// fulfilled_handlers.disable
3717					tuples[ 3 - i ][ 3 ].disable,
3718
3719					// progress_callbacks.lock
3720					tuples[ 0 ][ 2 ].lock,
3721
3722					// progress_handlers.lock
3723					tuples[ 0 ][ 3 ].lock
3724				);
3725			}
3726
3727			// progress_handlers.fire
3728			// fulfilled_handlers.fire
3729			// rejected_handlers.fire
3730			list.add( tuple[ 3 ].fire );
3731
3732			// deferred.notify = function() { deferred.notifyWith(...) }
3733			// deferred.resolve = function() { deferred.resolveWith(...) }
3734			// deferred.reject = function() { deferred.rejectWith(...) }
3735			deferred[ tuple[ 0 ] ] = function() {
3736				deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
3737				return this;
3738			};
3739
3740			// deferred.notifyWith = list.fireWith
3741			// deferred.resolveWith = list.fireWith
3742			// deferred.rejectWith = list.fireWith
3743			deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
3744		} );
3745
3746		// Make the deferred a promise
3747		promise.promise( deferred );
3748
3749		// Call given func if any
3750		if ( func ) {
3751			func.call( deferred, deferred );
3752		}
3753
3754		// All done!
3755		return deferred;
3756	},
3757
3758	// Deferred helper
3759	when: function( singleValue ) {
3760		var
3761
3762			// count of uncompleted subordinates
3763			remaining = arguments.length,
3764
3765			// count of unprocessed arguments
3766			i = remaining,
3767
3768			// subordinate fulfillment data
3769			resolveContexts = Array( i ),
3770			resolveValues = slice.call( arguments ),
3771
3772			// the master Deferred
3773			master = jQuery.Deferred(),
3774
3775			// subordinate callback factory
3776			updateFunc = function( i ) {
3777				return function( value ) {
3778					resolveContexts[ i ] = this;
3779					resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3780					if ( !( --remaining ) ) {
3781						master.resolveWith( resolveContexts, resolveValues );
3782					}
3783				};
3784			};
3785
3786		// Single- and empty arguments are adopted like Promise.resolve
3787		if ( remaining <= 1 ) {
3788			adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
3789				!remaining );
3790
3791			// Use .then() to unwrap secondary thenables (cf. gh-3000)
3792			if ( master.state() === "pending" ||
3793				isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
3794
3795				return master.then();
3796			}
3797		}
3798
3799		// Multiple arguments are aggregated like Promise.all array elements
3800		while ( i-- ) {
3801			adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
3802		}
3803
3804		return master.promise();
3805	}
3806} );
3807
3808
3809// These usually indicate a programmer mistake during development,
3810// warn about them ASAP rather than swallowing them by default.
3811var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
3812
3813jQuery.Deferred.exceptionHook = function( error, stack ) {
3814
3815	// Support: IE 8 - 9 only
3816	// Console exists when dev tools are open, which can happen at any time
3817	if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
3818		window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
3819	}
3820};
3821
3822
3823
3824
3825jQuery.readyException = function( error ) {
3826	window.setTimeout( function() {
3827		throw error;
3828	} );
3829};
3830
3831
3832
3833
3834// The deferred used on DOM ready
3835var readyList = jQuery.Deferred();
3836
3837jQuery.fn.ready = function( fn ) {
3838
3839	readyList
3840		.then( fn )
3841
3842		// Wrap jQuery.readyException in a function so that the lookup
3843		// happens at the time of error handling instead of callback
3844		// registration.
3845		.catch( function( error ) {
3846			jQuery.readyException( error );
3847		} );
3848
3849	return this;
3850};
3851
3852jQuery.extend( {
3853
3854	// Is the DOM ready to be used? Set to true once it occurs.
3855	isReady: false,
3856
3857	// A counter to track how many items to wait for before
3858	// the ready event fires. See #6781
3859	readyWait: 1,
3860
3861	// Handle when the DOM is ready
3862	ready: function( wait ) {
3863
3864		// Abort if there are pending holds or we're already ready
3865		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3866			return;
3867		}
3868
3869		// Remember that the DOM is ready
3870		jQuery.isReady = true;
3871
3872		// If a normal DOM Ready event fired, decrement, and wait if need be
3873		if ( wait !== true && --jQuery.readyWait > 0 ) {
3874			return;
3875		}
3876
3877		// If there are functions bound, to execute
3878		readyList.resolveWith( document, [ jQuery ] );
3879	}
3880} );
3881
3882jQuery.ready.then = readyList.then;
3883
3884// The ready event handler and self cleanup method
3885function completed() {
3886	document.removeEventListener( "DOMContentLoaded", completed );
3887	window.removeEventListener( "load", completed );
3888	jQuery.ready();
3889}
3890
3891// Catch cases where $(document).ready() is called
3892// after the browser event has already occurred.
3893// Support: IE <=9 - 10 only
3894// Older IE sometimes signals "interactive" too soon
3895if ( document.readyState === "complete" ||
3896	( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
3897
3898	// Handle it asynchronously to allow scripts the opportunity to delay ready
3899	window.setTimeout( jQuery.ready );
3900
3901} else {
3902
3903	// Use the handy event callback
3904	document.addEventListener( "DOMContentLoaded", completed );
3905
3906	// A fallback to window.onload, that will always work
3907	window.addEventListener( "load", completed );
3908}
3909
3910
3911
3912
3913// Multifunctional method to get and set values of a collection
3914// The value/s can optionally be executed if it's a function
3915var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
3916	var i = 0,
3917		len = elems.length,
3918		bulk = key == null;
3919
3920	// Sets many values
3921	if ( toType( key ) === "object" ) {
3922		chainable = true;
3923		for ( i in key ) {
3924			access( elems, fn, i, key[ i ], true, emptyGet, raw );
3925		}
3926
3927	// Sets one value
3928	} else if ( value !== undefined ) {
3929		chainable = true;
3930
3931		if ( !isFunction( value ) ) {
3932			raw = true;
3933		}
3934
3935		if ( bulk ) {
3936
3937			// Bulk operations run against the entire set
3938			if ( raw ) {
3939				fn.call( elems, value );
3940				fn = null;
3941
3942			// ...except when executing function values
3943			} else {
3944				bulk = fn;
3945				fn = function( elem, key, value ) {
3946					return bulk.call( jQuery( elem ), value );
3947				};
3948			}
3949		}
3950
3951		if ( fn ) {
3952			for ( ; i < len; i++ ) {
3953				fn(
3954					elems[ i ], key, raw ?
3955					value :
3956					value.call( elems[ i ], i, fn( elems[ i ], key ) )
3957				);
3958			}
3959		}
3960	}
3961
3962	if ( chainable ) {
3963		return elems;
3964	}
3965
3966	// Gets
3967	if ( bulk ) {
3968		return fn.call( elems );
3969	}
3970
3971	return len ? fn( elems[ 0 ], key ) : emptyGet;
3972};
3973
3974
3975// Matches dashed string for camelizing
3976var rmsPrefix = /^-ms-/,
3977	rdashAlpha = /-([a-z])/g;
3978
3979// Used by camelCase as callback to replace()
3980function fcamelCase( all, letter ) {
3981	return letter.toUpperCase();
3982}
3983
3984// Convert dashed to camelCase; used by the css and data modules
3985// Support: IE <=9 - 11, Edge 12 - 15
3986// Microsoft forgot to hump their vendor prefix (#9572)
3987function camelCase( string ) {
3988	return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
3989}
3990var acceptData = function( owner ) {
3991
3992	// Accepts only:
3993	//  - Node
3994	//    - Node.ELEMENT_NODE
3995	//    - Node.DOCUMENT_NODE
3996	//  - Object
3997	//    - Any
3998	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
3999};
4000
4001
4002
4003
4004function Data() {
4005	this.expando = jQuery.expando + Data.uid++;
4006}
4007
4008Data.uid = 1;
4009
4010Data.prototype = {
4011
4012	cache: function( owner ) {
4013
4014		// Check if the owner object already has a cache
4015		var value = owner[ this.expando ];
4016
4017		// If not, create one
4018		if ( !value ) {
4019			value = {};
4020
4021			// We can accept data for non-element nodes in modern browsers,
4022			// but we should not, see #8335.
4023			// Always return an empty object.
4024			if ( acceptData( owner ) ) {
4025
4026				// If it is a node unlikely to be stringify-ed or looped over
4027				// use plain assignment
4028				if ( owner.nodeType ) {
4029					owner[ this.expando ] = value;
4030
4031				// Otherwise secure it in a non-enumerable property
4032				// configurable must be true to allow the property to be
4033				// deleted when data is removed
4034				} else {
4035					Object.defineProperty( owner, this.expando, {
4036						value: value,
4037						configurable: true
4038					} );
4039				}
4040			}
4041		}
4042
4043		return value;
4044	},
4045	set: function( owner, data, value ) {
4046		var prop,
4047			cache = this.cache( owner );
4048
4049		// Handle: [ owner, key, value ] args
4050		// Always use camelCase key (gh-2257)
4051		if ( typeof data === "string" ) {
4052			cache[ camelCase( data ) ] = value;
4053
4054		// Handle: [ owner, { properties } ] args
4055		} else {
4056
4057			// Copy the properties one-by-one to the cache object
4058			for ( prop in data ) {
4059				cache[ camelCase( prop ) ] = data[ prop ];
4060			}
4061		}
4062		return cache;
4063	},
4064	get: function( owner, key ) {
4065		return key === undefined ?
4066			this.cache( owner ) :
4067
4068			// Always use camelCase key (gh-2257)
4069			owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
4070	},
4071	access: function( owner, key, value ) {
4072
4073		// In cases where either:
4074		//
4075		//   1. No key was specified
vendor: 8,694 bytes, lines 4076-4434
4076		//   2. A string key was specified, but no value provided
4077		//
4078		// Take the "read" path and allow the get method to determine
4079		// which value to return, respectively either:
4080		//
4081		//   1. The entire cache object
4082		//   2. The data stored at the key
4083		//
4084		if ( key === undefined ||
4085				( ( key && typeof key === "string" ) && value === undefined ) ) {
4086
4087			return this.get( owner, key );
4088		}
4089
4090		// When the key is not a string, or both a key and value
4091		// are specified, set or extend (existing objects) with either:
4092		//
4093		//   1. An object of properties
4094		//   2. A key and value
4095		//
4096		this.set( owner, key, value );
4097
4098		// Since the "set" path can have two possible entry points
4099		// return the expected data based on which path was taken[*]
4100		return value !== undefined ? value : key;
4101	},
4102	remove: function( owner, key ) {
4103		var i,
4104			cache = owner[ this.expando ];
4105
4106		if ( cache === undefined ) {
4107			return;
4108		}
4109
4110		if ( key !== undefined ) {
4111
4112			// Support array or space separated string of keys
4113			if ( Array.isArray( key ) ) {
4114
4115				// If key is an array of keys...
4116				// We always set camelCase keys, so remove that.
4117				key = key.map( camelCase );
4118			} else {
4119				key = camelCase( key );
4120
4121				// If a key with the spaces exists, use it.
4122				// Otherwise, create an array by matching non-whitespace
4123				key = key in cache ?
4124					[ key ] :
4125					( key.match( rnothtmlwhite ) || [] );
4126			}
4127
4128			i = key.length;
4129
4130			while ( i-- ) {
4131				delete cache[ key[ i ] ];
4132			}
4133		}
4134
4135		// Remove the expando if there's no more data
4136		if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
4137
4138			// Support: Chrome <=35 - 45
4139			// Webkit & Blink performance suffers when deleting properties
4140			// from DOM nodes, so set to undefined instead
4141			// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
4142			if ( owner.nodeType ) {
4143				owner[ this.expando ] = undefined;
4144			} else {
4145				delete owner[ this.expando ];
4146			}
4147		}
4148	},
4149	hasData: function( owner ) {
4150		var cache = owner[ this.expando ];
4151		return cache !== undefined && !jQuery.isEmptyObject( cache );
4152	}
4153};
4154var dataPriv = new Data();
4155
4156var dataUser = new Data();
4157
4158
4159
4160//	Implementation Summary
4161//
4162//	1. Enforce API surface and semantic compatibility with 1.9.x branch
4163//	2. Improve the module's maintainability by reducing the storage
4164//		paths to a single mechanism.
4165//	3. Use the same single mechanism to support "private" and "user" data.
4166//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
4167//	5. Avoid exposing implementation details on user objects (eg. expando properties)
4168//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
4169
4170var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
4171	rmultiDash = /[A-Z]/g;
4172
4173function getData( data ) {
4174	if ( data === "true" ) {
4175		return true;
4176	}
4177
4178	if ( data === "false" ) {
4179		return false;
4180	}
4181
4182	if ( data === "null" ) {
4183		return null;
4184	}
4185
4186	// Only convert to a number if it doesn't change the string
4187	if ( data === +data + "" ) {
4188		return +data;
4189	}
4190
4191	if ( rbrace.test( data ) ) {
4192		return JSON.parse( data );
4193	}
4194
4195	return data;
4196}
4197
4198function dataAttr( elem, key, data ) {
4199	var name;
4200
4201	// If nothing was found internally, try to fetch any
4202	// data from the HTML5 data-* attribute
4203	if ( data === undefined && elem.nodeType === 1 ) {
4204		name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
4205		data = elem.getAttribute( name );
4206
4207		if ( typeof data === "string" ) {
4208			try {
4209				data = getData( data );
4210			} catch ( e ) {}
4211
4212			// Make sure we set the data so it isn't changed later
4213			dataUser.set( elem, key, data );
4214		} else {
4215			data = undefined;
4216		}
4217	}
4218	return data;
4219}
4220
4221jQuery.extend( {
4222	hasData: function( elem ) {
4223		return dataUser.hasData( elem ) || dataPriv.hasData( elem );
4224	},
4225
4226	data: function( elem, name, data ) {
4227		return dataUser.access( elem, name, data );
4228	},
4229
4230	removeData: function( elem, name ) {
4231		dataUser.remove( elem, name );
4232	},
4233
4234	// TODO: Now that all calls to _data and _removeData have been replaced
4235	// with direct calls to dataPriv methods, these can be deprecated.
4236	_data: function( elem, name, data ) {
4237		return dataPriv.access( elem, name, data );
4238	},
4239
4240	_removeData: function( elem, name ) {
4241		dataPriv.remove( elem, name );
4242	}
4243} );
4244
4245jQuery.fn.extend( {
4246	data: function( key, value ) {
4247		var i, name, data,
4248			elem = this[ 0 ],
4249			attrs = elem && elem.attributes;
4250
4251		// Gets all values
4252		if ( key === undefined ) {
4253			if ( this.length ) {
4254				data = dataUser.get( elem );
4255
4256				if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
4257					i = attrs.length;
4258					while ( i-- ) {
4259
4260						// Support: IE 11 only
4261						// The attrs elements can be null (#14894)
4262						if ( attrs[ i ] ) {
4263							name = attrs[ i ].name;
4264							if ( name.indexOf( "data-" ) === 0 ) {
4265								name = camelCase( name.slice( 5 ) );
4266								dataAttr( elem, name, data[ name ] );
4267							}
4268						}
4269					}
4270					dataPriv.set( elem, "hasDataAttrs", true );
4271				}
4272			}
4273
4274			return data;
4275		}
4276
4277		// Sets multiple values
4278		if ( typeof key === "object" ) {
4279			return this.each( function() {
4280				dataUser.set( this, key );
4281			} );
4282		}
4283
4284		return access( this, function( value ) {
4285			var data;
4286
4287			// The calling jQuery object (element matches) is not empty
4288			// (and therefore has an element appears at this[ 0 ]) and the
4289			// `value` parameter was not undefined. An empty jQuery object
4290			// will result in `undefined` for elem = this[ 0 ] which will
4291			// throw an exception if an attempt to read a data cache is made.
4292			if ( elem && value === undefined ) {
4293
4294				// Attempt to get data from the cache
4295				// The key will always be camelCased in Data
4296				data = dataUser.get( elem, key );
4297				if ( data !== undefined ) {
4298					return data;
4299				}
4300
4301				// Attempt to "discover" the data in
4302				// HTML5 custom data-* attrs
4303				data = dataAttr( elem, key );
4304				if ( data !== undefined ) {
4305					return data;
4306				}
4307
4308				// We tried really hard, but the data doesn't exist.
4309				return;
4310			}
4311
4312			// Set the data...
4313			this.each( function() {
4314
4315				// We always store the camelCased key
4316				dataUser.set( this, key, value );
4317			} );
4318		}, null, value, arguments.length > 1, null, true );
4319	},
4320
4321	removeData: function( key ) {
4322		return this.each( function() {
4323			dataUser.remove( this, key );
4324		} );
4325	}
4326} );
4327
4328
4329jQuery.extend( {
4330	queue: function( elem, type, data ) {
4331		var queue;
4332
4333		if ( elem ) {
4334			type = ( type || "fx" ) + "queue";
4335			queue = dataPriv.get( elem, type );
4336
4337			// Speed up dequeue by getting out quickly if this is just a lookup
4338			if ( data ) {
4339				if ( !queue || Array.isArray( data ) ) {
4340					queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
4341				} else {
4342					queue.push( data );
4343				}
4344			}
4345			return queue || [];
4346		}
4347	},
4348
4349	dequeue: function( elem, type ) {
4350		type = type || "fx";
4351
4352		var queue = jQuery.queue( elem, type ),
4353			startLength = queue.length,
4354			fn = queue.shift(),
4355			hooks = jQuery._queueHooks( elem, type ),
4356			next = function() {
4357				jQuery.dequeue( elem, type );
4358			};
4359
4360		// If the fx queue is dequeued, always remove the progress sentinel
4361		if ( fn === "inprogress" ) {
4362			fn = queue.shift();
4363			startLength--;
4364		}
4365
4366		if ( fn ) {
4367
4368			// Add a progress sentinel to prevent the fx queue from being
4369			// automatically dequeued
4370			if ( type === "fx" ) {
4371				queue.unshift( "inprogress" );
4372			}
4373
4374			// Clear up the last queue stop function
4375			delete hooks.stop;
4376			fn.call( elem, next, hooks );
4377		}
4378
4379		if ( !startLength && hooks ) {
4380			hooks.empty.fire();
4381		}
4382	},
4383
4384	// Not public - generate a queueHooks object, or return the current one
4385	_queueHooks: function( elem, type ) {
4386		var key = type + "queueHooks";
4387		return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
4388			empty: jQuery.Callbacks( "once memory" ).add( function() {
4389				dataPriv.remove( elem, [ type + "queue", key ] );
4390			} )
4391		} );
4392	}
4393} );
4394
4395jQuery.fn.extend( {
4396	queue: function( type, data ) {
4397		var setter = 2;
4398
4399		if ( typeof type !== "string" ) {
4400			data = type;
4401			type = "fx";
4402			setter--;
4403		}
4404
4405		if ( arguments.length < setter ) {
4406			return jQuery.queue( this[ 0 ], type );
4407		}
4408
4409		return data === undefined ?
4410			this :
4411			this.each( function() {
4412				var queue = jQuery.queue( this, type, data );
4413
4414				// Ensure a hooks for this queue
4415				jQuery._queueHooks( this, type );
4416
4417				if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
4418					jQuery.dequeue( this, type );
4419				}
4420			} );
4421	},
4422	dequeue: function( type ) {
4423		return this.each( function() {
4424			jQuery.dequeue( this, type );
4425		} );
4426	},
4427	clearQueue: function( type ) {
4428		return this.queue( type || "fx", [] );
4429	},
4430
4431	// Get a promise resolved when queues of a certain type
4432	// are emptied (fx is the type by default)
4433	promise: function( type, obj ) {
4434		var tmp,
vendor: 37,137 bytes, lines 4435-5860
4435			count = 1,
4436			defer = jQuery.Deferred(),
4437			elements = this,
4438			i = this.length,
4439			resolve = function() {
4440				if ( !( --count ) ) {
4441					defer.resolveWith( elements, [ elements ] );
4442				}
4443			};
4444
4445		if ( typeof type !== "string" ) {
4446			obj = type;
4447			type = undefined;
4448		}
4449		type = type || "fx";
4450
4451		while ( i-- ) {
4452			tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
4453			if ( tmp && tmp.empty ) {
4454				count++;
4455				tmp.empty.add( resolve );
4456			}
4457		}
4458		resolve();
4459		return defer.promise( obj );
4460	}
4461} );
4462var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
4463
4464var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
4465
4466
4467var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4468
4469var isHiddenWithinTree = function( elem, el ) {
4470
4471		// isHiddenWithinTree might be called from jQuery#filter function;
4472		// in that case, element will be second argument
4473		elem = el || elem;
4474
4475		// Inline style trumps all
4476		return elem.style.display === "none" ||
4477			elem.style.display === "" &&
4478
4479			// Otherwise, check computed style
4480			// Support: Firefox <=43 - 45
4481			// Disconnected elements can have computed display: none, so first confirm that elem is
4482			// in the document.
4483			jQuery.contains( elem.ownerDocument, elem ) &&
4484
4485			jQuery.css( elem, "display" ) === "none";
4486	};
4487
4488var swap = function( elem, options, callback, args ) {
4489	var ret, name,
4490		old = {};
4491
4492	// Remember the old values, and insert the new ones
4493	for ( name in options ) {
4494		old[ name ] = elem.style[ name ];
4495		elem.style[ name ] = options[ name ];
4496	}
4497
4498	ret = callback.apply( elem, args || [] );
4499
4500	// Revert the old values
4501	for ( name in options ) {
4502		elem.style[ name ] = old[ name ];
4503	}
4504
4505	return ret;
4506};
4507
4508
4509
4510
4511function adjustCSS( elem, prop, valueParts, tween ) {
4512	var adjusted, scale,
4513		maxIterations = 20,
4514		currentValue = tween ?
4515			function() {
4516				return tween.cur();
4517			} :
4518			function() {
4519				return jQuery.css( elem, prop, "" );
4520			},
4521		initial = currentValue(),
4522		unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
4523
4524		// Starting value computation is required for potential unit mismatches
4525		initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
4526			rcssNum.exec( jQuery.css( elem, prop ) );
4527
4528	if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
4529
4530		// Support: Firefox <=54
4531		// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
4532		initial = initial / 2;
4533
4534		// Trust units reported by jQuery.css
4535		unit = unit || initialInUnit[ 3 ];
4536
4537		// Iteratively approximate from a nonzero starting point
4538		initialInUnit = +initial || 1;
4539
4540		while ( maxIterations-- ) {
4541
4542			// Evaluate and update our best guess (doubling guesses that zero out).
4543			// Finish if the scale equals or crosses 1 (making the old*new product non-positive).
4544			jQuery.style( elem, prop, initialInUnit + unit );
4545			if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
4546				maxIterations = 0;
4547			}
4548			initialInUnit = initialInUnit / scale;
4549
4550		}
4551
4552		initialInUnit = initialInUnit * 2;
4553		jQuery.style( elem, prop, initialInUnit + unit );
4554
4555		// Make sure we update the tween properties later on
4556		valueParts = valueParts || [];
4557	}
4558
4559	if ( valueParts ) {
4560		initialInUnit = +initialInUnit || +initial || 0;
4561
4562		// Apply relative offset (+=/-=) if specified
4563		adjusted = valueParts[ 1 ] ?
4564			initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
4565			+valueParts[ 2 ];
4566		if ( tween ) {
4567			tween.unit = unit;
4568			tween.start = initialInUnit;
4569			tween.end = adjusted;
4570		}
4571	}
4572	return adjusted;
4573}
4574
4575
4576var defaultDisplayMap = {};
4577
4578function getDefaultDisplay( elem ) {
4579	var temp,
4580		doc = elem.ownerDocument,
4581		nodeName = elem.nodeName,
4582		display = defaultDisplayMap[ nodeName ];
4583
4584	if ( display ) {
4585		return display;
4586	}
4587
4588	temp = doc.body.appendChild( doc.createElement( nodeName ) );
4589	display = jQuery.css( temp, "display" );
4590
4591	temp.parentNode.removeChild( temp );
4592
4593	if ( display === "none" ) {
4594		display = "block";
4595	}
4596	defaultDisplayMap[ nodeName ] = display;
4597
4598	return display;
4599}
4600
4601function showHide( elements, show ) {
4602	var display, elem,
4603		values = [],
4604		index = 0,
4605		length = elements.length;
4606
4607	// Determine new display value for elements that need to change
4608	for ( ; index < length; index++ ) {
4609		elem = elements[ index ];
4610		if ( !elem.style ) {
4611			continue;
4612		}
4613
4614		display = elem.style.display;
4615		if ( show ) {
4616
4617			// Since we force visibility upon cascade-hidden elements, an immediate (and slow)
4618			// check is required in this first loop unless we have a nonempty display value (either
4619			// inline or about-to-be-restored)
4620			if ( display === "none" ) {
4621				values[ index ] = dataPriv.get( elem, "display" ) || null;
4622				if ( !values[ index ] ) {
4623					elem.style.display = "";
4624				}
4625			}
4626			if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
4627				values[ index ] = getDefaultDisplay( elem );
4628			}
4629		} else {
4630			if ( display !== "none" ) {
4631				values[ index ] = "none";
4632
4633				// Remember what we're overwriting
4634				dataPriv.set( elem, "display", display );
4635			}
4636		}
4637	}
4638
4639	// Set the display of the elements in a second loop to avoid constant reflow
4640	for ( index = 0; index < length; index++ ) {
4641		if ( values[ index ] != null ) {
4642			elements[ index ].style.display = values[ index ];
4643		}
4644	}
4645
4646	return elements;
4647}
4648
4649jQuery.fn.extend( {
4650	show: function() {
4651		return showHide( this, true );
4652	},
4653	hide: function() {
4654		return showHide( this );
4655	},
4656	toggle: function( state ) {
4657		if ( typeof state === "boolean" ) {
4658			return state ? this.show() : this.hide();
4659		}
4660
4661		return this.each( function() {
4662			if ( isHiddenWithinTree( this ) ) {
4663				jQuery( this ).show();
4664			} else {
4665				jQuery( this ).hide();
4666			}
4667		} );
4668	}
4669} );
4670var rcheckableType = ( /^(?:checkbox|radio)$/i );
4671
4672var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
4673
4674var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
4675
4676
4677
4678// We have to close these tags to support XHTML (#13200)
4679var wrapMap = {
4680
4681	// Support: IE <=9 only
4682	option: [ 1, "<select multiple='multiple'>", "</select>" ],
4683
4684	// XHTML parsers do not magically insert elements in the
4685	// same way that tag soup parsers do. So we cannot shorten
4686	// this by omitting <tbody> or other required elements.
4687	thead: [ 1, "<table>", "</table>" ],
4688	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
4689	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
4690	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
4691
4692	_default: [ 0, "", "" ]
4693};
4694
4695// Support: IE <=9 only
4696wrapMap.optgroup = wrapMap.option;
4697
4698wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
4699wrapMap.th = wrapMap.td;
4700
4701
4702function getAll( context, tag ) {
4703
4704	// Support: IE <=9 - 11 only
4705	// Use typeof to avoid zero-argument method invocation on host objects (#15151)
4706	var ret;
4707
4708	if ( typeof context.getElementsByTagName !== "undefined" ) {
4709		ret = context.getElementsByTagName( tag || "*" );
4710
4711	} else if ( typeof context.querySelectorAll !== "undefined" ) {
4712		ret = context.querySelectorAll( tag || "*" );
4713
4714	} else {
4715		ret = [];
4716	}
4717
4718	if ( tag === undefined || tag && nodeName( context, tag ) ) {
4719		return jQuery.merge( [ context ], ret );
4720	}
4721
4722	return ret;
4723}
4724
4725
4726// Mark scripts as having already been evaluated
4727function setGlobalEval( elems, refElements ) {
4728	var i = 0,
4729		l = elems.length;
4730
4731	for ( ; i < l; i++ ) {
4732		dataPriv.set(
4733			elems[ i ],
4734			"globalEval",
4735			!refElements || dataPriv.get( refElements[ i ], "globalEval" )
4736		);
4737	}
4738}
4739
4740
4741var rhtml = /<|&#?\w+;/;
4742
4743function buildFragment( elems, context, scripts, selection, ignored ) {
4744	var elem, tmp, tag, wrap, contains, j,
4745		fragment = context.createDocumentFragment(),
4746		nodes = [],
4747		i = 0,
4748		l = elems.length;
4749
4750	for ( ; i < l; i++ ) {
4751		elem = elems[ i ];
4752
4753		if ( elem || elem === 0 ) {
4754
4755			// Add nodes directly
4756			if ( toType( elem ) === "object" ) {
4757
4758				// Support: Android <=4.0 only, PhantomJS 1 only
4759				// push.apply(_, arraylike) throws on ancient WebKit
4760				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
4761
4762			// Convert non-html into a text node
4763			} else if ( !rhtml.test( elem ) ) {
4764				nodes.push( context.createTextNode( elem ) );
4765
4766			// Convert html into DOM nodes
4767			} else {
4768				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
4769
4770				// Deserialize a standard representation
4771				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
4772				wrap = wrapMap[ tag ] || wrapMap._default;
4773				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
4774
4775				// Descend through wrappers to the right content
4776				j = wrap[ 0 ];
4777				while ( j-- ) {
4778					tmp = tmp.lastChild;
4779				}
4780
4781				// Support: Android <=4.0 only, PhantomJS 1 only
4782				// push.apply(_, arraylike) throws on ancient WebKit
4783				jQuery.merge( nodes, tmp.childNodes );
4784
4785				// Remember the top-level container
4786				tmp = fragment.firstChild;
4787
4788				// Ensure the created nodes are orphaned (#12392)
4789				tmp.textContent = "";
4790			}
4791		}
4792	}
4793
4794	// Remove wrapper from fragment
4795	fragment.textContent = "";
4796
4797	i = 0;
4798	while ( ( elem = nodes[ i++ ] ) ) {
4799
4800		// Skip elements already in the context collection (trac-4087)
4801		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
4802			if ( ignored ) {
4803				ignored.push( elem );
4804			}
4805			continue;
4806		}
4807
4808		contains = jQuery.contains( elem.ownerDocument, elem );
4809
4810		// Append to fragment
4811		tmp = getAll( fragment.appendChild( elem ), "script" );
4812
4813		// Preserve script evaluation history
4814		if ( contains ) {
4815			setGlobalEval( tmp );
4816		}
4817
4818		// Capture executables
4819		if ( scripts ) {
4820			j = 0;
4821			while ( ( elem = tmp[ j++ ] ) ) {
4822				if ( rscriptType.test( elem.type || "" ) ) {
4823					scripts.push( elem );
4824				}
4825			}
4826		}
4827	}
4828
4829	return fragment;
4830}
4831
4832
4833( function() {
4834	var fragment = document.createDocumentFragment(),
4835		div = fragment.appendChild( document.createElement( "div" ) ),
4836		input = document.createElement( "input" );
4837
4838	// Support: Android 4.0 - 4.3 only
4839	// Check state lost if the name is set (#11217)
4840	// Support: Windows Web Apps (WWA)
4841	// `name` and `type` must use .setAttribute for WWA (#14901)
4842	input.setAttribute( "type", "radio" );
4843	input.setAttribute( "checked", "checked" );
4844	input.setAttribute( "name", "t" );
4845
4846	div.appendChild( input );
4847
4848	// Support: Android <=4.1 only
4849	// Older WebKit doesn't clone checked state correctly in fragments
4850	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4851
4852	// Support: IE <=11 only
4853	// Make sure textarea (and checkbox) defaultValue is properly cloned
4854	div.innerHTML = "<textarea>x</textarea>";
4855	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4856} )();
4857var documentElement = document.documentElement;
4858
4859
4860
4861var
4862	rkeyEvent = /^key/,
4863	rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
4864	rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
4865
4866function returnTrue() {
4867	return true;
4868}
4869
4870function returnFalse() {
4871	return false;
4872}
4873
4874// Support: IE <=9 only
4875// See #13393 for more info
4876function safeActiveElement() {
4877	try {
4878		return document.activeElement;
4879	} catch ( err ) { }
4880}
4881
4882function on( elem, types, selector, data, fn, one ) {
4883	var origFn, type;
4884
4885	// Types can be a map of types/handlers
4886	if ( typeof types === "object" ) {
4887
4888		// ( types-Object, selector, data )
4889		if ( typeof selector !== "string" ) {
4890
4891			// ( types-Object, data )
4892			data = data || selector;
4893			selector = undefined;
4894		}
4895		for ( type in types ) {
4896			on( elem, type, selector, data, types[ type ], one );
4897		}
4898		return elem;
4899	}
4900
4901	if ( data == null && fn == null ) {
4902
4903		// ( types, fn )
4904		fn = selector;
4905		data = selector = undefined;
4906	} else if ( fn == null ) {
4907		if ( typeof selector === "string" ) {
4908
4909			// ( types, selector, fn )
4910			fn = data;
4911			data = undefined;
4912		} else {
4913
4914			// ( types, data, fn )
4915			fn = data;
4916			data = selector;
4917			selector = undefined;
4918		}
4919	}
4920	if ( fn === false ) {
4921		fn = returnFalse;
4922	} else if ( !fn ) {
4923		return elem;
4924	}
4925
4926	if ( one === 1 ) {
4927		origFn = fn;
4928		fn = function( event ) {
4929
4930			// Can use an empty set, since event contains the info
4931			jQuery().off( event );
4932			return origFn.apply( this, arguments );
4933		};
4934
4935		// Use same guid so caller can remove using origFn
4936		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4937	}
4938	return elem.each( function() {
4939		jQuery.event.add( this, types, fn, data, selector );
4940	} );
4941}
4942
4943/*
4944 * Helper functions for managing events -- not part of the public interface.
4945 * Props to Dean Edwards' addEvent library for many of the ideas.
4946 */
4947jQuery.event = {
4948
4949	global: {},
4950
4951	add: function( elem, types, handler, data, selector ) {
4952
4953		var handleObjIn, eventHandle, tmp,
4954			events, t, handleObj,
4955			special, handlers, type, namespaces, origType,
4956			elemData = dataPriv.get( elem );
4957
4958		// Don't attach events to noData or text/comment nodes (but allow plain objects)
4959		if ( !elemData ) {
4960			return;
4961		}
4962
4963		// Caller can pass in an object of custom data in lieu of the handler
4964		if ( handler.handler ) {
4965			handleObjIn = handler;
4966			handler = handleObjIn.handler;
4967			selector = handleObjIn.selector;
4968		}
4969
4970		// Ensure that invalid selectors throw exceptions at attach time
4971		// Evaluate against documentElement in case elem is a non-element node (e.g., document)
4972		if ( selector ) {
4973			jQuery.find.matchesSelector( documentElement, selector );
4974		}
4975
4976		// Make sure that the handler has a unique ID, used to find/remove it later
4977		if ( !handler.guid ) {
4978			handler.guid = jQuery.guid++;
4979		}
4980
4981		// Init the element's event structure and main handler, if this is the first
4982		if ( !( events = elemData.events ) ) {
4983			events = elemData.events = {};
4984		}
4985		if ( !( eventHandle = elemData.handle ) ) {
4986			eventHandle = elemData.handle = function( e ) {
4987
4988				// Discard the second event of a jQuery.event.trigger() and
4989				// when an event is called after a page has unloaded
4990				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
4991					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
4992			};
4993		}
4994
4995		// Handle multiple events separated by a space
4996		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
4997		t = types.length;
4998		while ( t-- ) {
4999			tmp = rtypenamespace.exec( types[ t ] ) || [];
5000			type = origType = tmp[ 1 ];
5001			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5002
5003			// There *must* be a type, no attaching namespace-only handlers
5004			if ( !type ) {
5005				continue;
5006			}
5007
5008			// If event changes its type, use the special event handlers for the changed type
5009			special = jQuery.event.special[ type ] || {};
5010
5011			// If selector defined, determine special event api type, otherwise given type
5012			type = ( selector ? special.delegateType : special.bindType ) || type;
5013
5014			// Update special based on newly reset type
5015			special = jQuery.event.special[ type ] || {};
5016
5017			// handleObj is passed to all event handlers
5018			handleObj = jQuery.extend( {
5019				type: type,
5020				origType: origType,
5021				data: data,
5022				handler: handler,
5023				guid: handler.guid,
5024				selector: selector,
5025				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
5026				namespace: namespaces.join( "." )
5027			}, handleObjIn );
5028
5029			// Init the event handler queue if we're the first
5030			if ( !( handlers = events[ type ] ) ) {
5031				handlers = events[ type ] = [];
5032				handlers.delegateCount = 0;
5033
5034				// Only use addEventListener if the special events handler returns false
5035				if ( !special.setup ||
5036					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
5037
5038					if ( elem.addEventListener ) {
5039						elem.addEventListener( type, eventHandle );
5040					}
5041				}
5042			}
5043
5044			if ( special.add ) {
5045				special.add.call( elem, handleObj );
5046
5047				if ( !handleObj.handler.guid ) {
5048					handleObj.handler.guid = handler.guid;
5049				}
5050			}
5051
5052			// Add to the element's handler list, delegates in front
5053			if ( selector ) {
5054				handlers.splice( handlers.delegateCount++, 0, handleObj );
5055			} else {
5056				handlers.push( handleObj );
5057			}
5058
5059			// Keep track of which events have ever been used, for event optimization
5060			jQuery.event.global[ type ] = true;
5061		}
5062
5063	},
5064
5065	// Detach an event or set of events from an element
5066	remove: function( elem, types, handler, selector, mappedTypes ) {
5067
5068		var j, origCount, tmp,
5069			events, t, handleObj,
5070			special, handlers, type, namespaces, origType,
5071			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
5072
5073		if ( !elemData || !( events = elemData.events ) ) {
5074			return;
5075		}
5076
5077		// Once for each type.namespace in types; type may be omitted
5078		types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
5079		t = types.length;
5080		while ( t-- ) {
5081			tmp = rtypenamespace.exec( types[ t ] ) || [];
5082			type = origType = tmp[ 1 ];
5083			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
5084
5085			// Unbind all events (on this namespace, if provided) for the element
5086			if ( !type ) {
5087				for ( type in events ) {
5088					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
5089				}
5090				continue;
5091			}
5092
5093			special = jQuery.event.special[ type ] || {};
5094			type = ( selector ? special.delegateType : special.bindType ) || type;
5095			handlers = events[ type ] || [];
5096			tmp = tmp[ 2 ] &&
5097				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
5098
5099			// Remove matching events
5100			origCount = j = handlers.length;
5101			while ( j-- ) {
5102				handleObj = handlers[ j ];
5103
5104				if ( ( mappedTypes || origType === handleObj.origType ) &&
5105					( !handler || handler.guid === handleObj.guid ) &&
5106					( !tmp || tmp.test( handleObj.namespace ) ) &&
5107					( !selector || selector === handleObj.selector ||
5108						selector === "**" && handleObj.selector ) ) {
5109					handlers.splice( j, 1 );
5110
5111					if ( handleObj.selector ) {
5112						handlers.delegateCount--;
5113					}
5114					if ( special.remove ) {
5115						special.remove.call( elem, handleObj );
5116					}
5117				}
5118			}
5119
5120			// Remove generic event handler if we removed something and no more handlers exist
5121			// (avoids potential for endless recursion during removal of special event handlers)
5122			if ( origCount && !handlers.length ) {
5123				if ( !special.teardown ||
5124					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
5125
5126					jQuery.removeEvent( elem, type, elemData.handle );
5127				}
5128
5129				delete events[ type ];
5130			}
5131		}
5132
5133		// Remove data and the expando if it's no longer used
5134		if ( jQuery.isEmptyObject( events ) ) {
5135			dataPriv.remove( elem, "handle events" );
5136		}
5137	},
5138
5139	dispatch: function( nativeEvent ) {
5140
5141		// Make a writable jQuery.Event from the native event object
5142		var event = jQuery.event.fix( nativeEvent );
5143
5144		var i, j, ret, matched, handleObj, handlerQueue,
5145			args = new Array( arguments.length ),
5146			handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
5147			special = jQuery.event.special[ event.type ] || {};
5148
5149		// Use the fix-ed jQuery.Event rather than the (read-only) native event
5150		args[ 0 ] = event;
5151
5152		for ( i = 1; i < arguments.length; i++ ) {
5153			args[ i ] = arguments[ i ];
5154		}
5155
5156		event.delegateTarget = this;
5157
5158		// Call the preDispatch hook for the mapped type, and let it bail if desired
5159		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5160			return;
5161		}
5162
5163		// Determine handlers
5164		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5165
5166		// Run delegates first; they may want to stop propagation beneath us
5167		i = 0;
5168		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
5169			event.currentTarget = matched.elem;
5170
5171			j = 0;
5172			while ( ( handleObj = matched.handlers[ j++ ] ) &&
5173				!event.isImmediatePropagationStopped() ) {
5174
5175				// Triggered event must either 1) have no namespace, or 2) have namespace(s)
5176				// a subset or equal to those in the bound event (both can have no namespace).
5177				if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
5178
5179					event.handleObj = handleObj;
5180					event.data = handleObj.data;
5181
5182					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
5183						handleObj.handler ).apply( matched.elem, args );
5184
5185					if ( ret !== undefined ) {
5186						if ( ( event.result = ret ) === false ) {
5187							event.preventDefault();
5188							event.stopPropagation();
5189						}
5190					}
5191				}
5192			}
5193		}
5194
5195		// Call the postDispatch hook for the mapped type
5196		if ( special.postDispatch ) {
5197			special.postDispatch.call( this, event );
5198		}
5199
5200		return event.result;
5201	},
5202
5203	handlers: function( event, handlers ) {
5204		var i, handleObj, sel, matchedHandlers, matchedSelectors,
5205			handlerQueue = [],
5206			delegateCount = handlers.delegateCount,
5207			cur = event.target;
5208
5209		// Find delegate handlers
5210		if ( delegateCount &&
5211
5212			// Support: IE <=9
5213			// Black-hole SVG <use> instance trees (trac-13180)
5214			cur.nodeType &&
5215
5216			// Support: Firefox <=42
5217			// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
5218			// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
5219			// Support: IE 11 only
5220			// ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
5221			!( event.type === "click" && event.button >= 1 ) ) {
5222
5223			for ( ; cur !== this; cur = cur.parentNode || this ) {
5224
5225				// Don't check non-elements (#13208)
5226				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
5227				if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
5228					matchedHandlers = [];
5229					matchedSelectors = {};
5230					for ( i = 0; i < delegateCount; i++ ) {
5231						handleObj = handlers[ i ];
5232
5233						// Don't conflict with Object.prototype properties (#13203)
5234						sel = handleObj.selector + " ";
5235
5236						if ( matchedSelectors[ sel ] === undefined ) {
5237							matchedSelectors[ sel ] = handleObj.needsContext ?
5238								jQuery( sel, this ).index( cur ) > -1 :
5239								jQuery.find( sel, this, null, [ cur ] ).length;
5240						}
5241						if ( matchedSelectors[ sel ] ) {
5242							matchedHandlers.push( handleObj );
5243						}
5244					}
5245					if ( matchedHandlers.length ) {
5246						handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
5247					}
5248				}
5249			}
5250		}
5251
5252		// Add the remaining (directly-bound) handlers
5253		cur = this;
5254		if ( delegateCount < handlers.length ) {
5255			handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
5256		}
5257
5258		return handlerQueue;
5259	},
5260
5261	addProp: function( name, hook ) {
5262		Object.defineProperty( jQuery.Event.prototype, name, {
5263			enumerable: true,
5264			configurable: true,
5265
5266			get: isFunction( hook ) ?
5267				function() {
5268					if ( this.originalEvent ) {
5269							return hook( this.originalEvent );
5270					}
5271				} :
5272				function() {
5273					if ( this.originalEvent ) {
5274							return this.originalEvent[ name ];
5275					}
5276				},
5277
5278			set: function( value ) {
5279				Object.defineProperty( this, name, {
5280					enumerable: true,
5281					configurable: true,
5282					writable: true,
5283					value: value
5284				} );
5285			}
5286		} );
5287	},
5288
5289	fix: function( originalEvent ) {
5290		return originalEvent[ jQuery.expando ] ?
5291			originalEvent :
5292			new jQuery.Event( originalEvent );
5293	},
5294
5295	special: {
5296		load: {
5297
5298			// Prevent triggered image.load events from bubbling to window.load
5299			noBubble: true
5300		},
5301		focus: {
5302
5303			// Fire native event if possible so blur/focus sequence is correct
5304			trigger: function() {
5305				if ( this !== safeActiveElement() && this.focus ) {
5306					this.focus();
5307					return false;
5308				}
5309			},
5310			delegateType: "focusin"
5311		},
5312		blur: {
5313			trigger: function() {
5314				if ( this === safeActiveElement() && this.blur ) {
5315					this.blur();
5316					return false;
5317				}
5318			},
5319			delegateType: "focusout"
5320		},
5321		click: {
5322
5323			// For checkbox, fire native event so checked state will be right
5324			trigger: function() {
5325				if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
5326					this.click();
5327					return false;
5328				}
5329			},
5330
5331			// For cross-browser consistency, don't fire native .click() on links
5332			_default: function( event ) {
5333				return nodeName( event.target, "a" );
5334			}
5335		},
5336
5337		beforeunload: {
5338			postDispatch: function( event ) {
5339
5340				// Support: Firefox 20+
5341				// Firefox doesn't alert if the returnValue field is not set.
5342				if ( event.result !== undefined && event.originalEvent ) {
5343					event.originalEvent.returnValue = event.result;
5344				}
5345			}
5346		}
5347	}
5348};
5349
5350jQuery.removeEvent = function( elem, type, handle ) {
5351
5352	// This "if" is needed for plain objects
5353	if ( elem.removeEventListener ) {
5354		elem.removeEventListener( type, handle );
5355	}
5356};
5357
5358jQuery.Event = function( src, props ) {
5359
5360	// Allow instantiation without the 'new' keyword
5361	if ( !( this instanceof jQuery.Event ) ) {
5362		return new jQuery.Event( src, props );
5363	}
5364
5365	// Event object
5366	if ( src && src.type ) {
5367		this.originalEvent = src;
5368		this.type = src.type;
5369
5370		// Events bubbling up the document may have been marked as prevented
5371		// by a handler lower down the tree; reflect the correct value.
5372		this.isDefaultPrevented = src.defaultPrevented ||
5373				src.defaultPrevented === undefined &&
5374
5375				// Support: Android <=2.3 only
5376				src.returnValue === false ?
5377			returnTrue :
5378			returnFalse;
5379
5380		// Create target properties
5381		// Support: Safari <=6 - 7 only
5382		// Target should not be a text node (#504, #13143)
5383		this.target = ( src.target && src.target.nodeType === 3 ) ?
5384			src.target.parentNode :
5385			src.target;
5386
5387		this.currentTarget = src.currentTarget;
5388		this.relatedTarget = src.relatedTarget;
5389
5390	// Event type
5391	} else {
5392		this.type = src;
5393	}
5394
5395	// Put explicitly provided properties onto the event object
5396	if ( props ) {
5397		jQuery.extend( this, props );
5398	}
5399
5400	// Create a timestamp if incoming event doesn't have one
5401	this.timeStamp = src && src.timeStamp || Date.now();
5402
5403	// Mark it as fixed
5404	this[ jQuery.expando ] = true;
5405};
5406
5407// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5408// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5409jQuery.Event.prototype = {
5410	constructor: jQuery.Event,
5411	isDefaultPrevented: returnFalse,
5412	isPropagationStopped: returnFalse,
5413	isImmediatePropagationStopped: returnFalse,
5414	isSimulated: false,
5415
5416	preventDefault: function() {
5417		var e = this.originalEvent;
5418
5419		this.isDefaultPrevented = returnTrue;
5420
5421		if ( e && !this.isSimulated ) {
5422			e.preventDefault();
5423		}
5424	},
5425	stopPropagation: function() {
5426		var e = this.originalEvent;
5427
5428		this.isPropagationStopped = returnTrue;
5429
5430		if ( e && !this.isSimulated ) {
5431			e.stopPropagation();
5432		}
5433	},
5434	stopImmediatePropagation: function() {
5435		var e = this.originalEvent;
5436
5437		this.isImmediatePropagationStopped = returnTrue;
5438
5439		if ( e && !this.isSimulated ) {
5440			e.stopImmediatePropagation();
5441		}
5442
5443		this.stopPropagation();
5444	}
5445};
5446
5447// Includes all common event props including KeyEvent and MouseEvent specific props
5448jQuery.each( {
5449	altKey: true,
5450	bubbles: true,
5451	cancelable: true,
5452	changedTouches: true,
5453	ctrlKey: true,
5454	detail: true,
5455	eventPhase: true,
5456	metaKey: true,
5457	pageX: true,
5458	pageY: true,
5459	shiftKey: true,
5460	view: true,
5461	"char": true,
5462	charCode: true,
5463	key: true,
5464	keyCode: true,
5465	button: true,
5466	buttons: true,
5467	clientX: true,
5468	clientY: true,
5469	offsetX: true,
5470	offsetY: true,
5471	pointerId: true,
5472	pointerType: true,
5473	screenX: true,
5474	screenY: true,
5475	targetTouches: true,
5476	toElement: true,
5477	touches: true,
5478
5479	which: function( event ) {
5480		var button = event.button;
5481
5482		// Add which for key events
5483		if ( event.which == null && rkeyEvent.test( event.type ) ) {
5484			return event.charCode != null ? event.charCode : event.keyCode;
5485		}
5486
5487		// Add which for click: 1 === left; 2 === middle; 3 === right
5488		if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
5489			if ( button & 1 ) {
5490				return 1;
5491			}
5492
5493			if ( button & 2 ) {
5494				return 3;
5495			}
5496
5497			if ( button & 4 ) {
5498				return 2;
5499			}
5500
5501			return 0;
5502		}
5503
5504		return event.which;
5505	}
5506}, jQuery.event.addProp );
5507
5508// Create mouseenter/leave events using mouseover/out and event-time checks
5509// so that event delegation works in jQuery.
5510// Do the same for pointerenter/pointerleave and pointerover/pointerout
5511//
5512// Support: Safari 7 only
5513// Safari sends mouseenter too often; see:
5514// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
5515// for the description of the bug (it existed in older Chrome versions as well).
5516jQuery.each( {
5517	mouseenter: "mouseover",
5518	mouseleave: "mouseout",
5519	pointerenter: "pointerover",
5520	pointerleave: "pointerout"
5521}, function( orig, fix ) {
5522	jQuery.event.special[ orig ] = {
5523		delegateType: fix,
5524		bindType: fix,
5525
5526		handle: function( event ) {
5527			var ret,
5528				target = this,
5529				related = event.relatedTarget,
5530				handleObj = event.handleObj;
5531
5532			// For mouseenter/leave call the handler if related is outside the target.
5533			// NB: No relatedTarget if the mouse left/entered the browser window
5534			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
5535				event.type = handleObj.origType;
5536				ret = handleObj.handler.apply( this, arguments );
5537				event.type = fix;
5538			}
5539			return ret;
5540		}
5541	};
5542} );
5543
5544jQuery.fn.extend( {
5545
5546	on: function( types, selector, data, fn ) {
5547		return on( this, types, selector, data, fn );
5548	},
5549	one: function( types, selector, data, fn ) {
5550		return on( this, types, selector, data, fn, 1 );
5551	},
5552	off: function( types, selector, fn ) {
5553		var handleObj, type;
5554		if ( types && types.preventDefault && types.handleObj ) {
5555
5556			// ( event )  dispatched jQuery.Event
5557			handleObj = types.handleObj;
5558			jQuery( types.delegateTarget ).off(
5559				handleObj.namespace ?
5560					handleObj.origType + "." + handleObj.namespace :
5561					handleObj.origType,
5562				handleObj.selector,
5563				handleObj.handler
5564			);
5565			return this;
5566		}
5567		if ( typeof types === "object" ) {
5568
5569			// ( types-object [, selector] )
5570			for ( type in types ) {
5571				this.off( type, selector, types[ type ] );
5572			}
5573			return this;
5574		}
5575		if ( selector === false || typeof selector === "function" ) {
5576
5577			// ( types [, fn] )
5578			fn = selector;
5579			selector = undefined;
5580		}
5581		if ( fn === false ) {
5582			fn = returnFalse;
5583		}
5584		return this.each( function() {
5585			jQuery.event.remove( this, types, fn, selector );
5586		} );
5587	}
5588} );
5589
5590
5591var
5592
5593	/* eslint-disable max-len */
5594
5595	// See https://github.com/eslint/eslint/issues/3229
5596	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
5597
5598	/* eslint-enable */
5599
5600	// Support: IE <=10 - 11, Edge 12 - 13 only
5601	// In IE/Edge using regex groups here causes severe slowdowns.
5602	// See https://connect.microsoft.com/IE/feedback/details/1736512/
5603	rnoInnerhtml = /<script|<style|<link/i,
5604
5605	// checked="checked" or checked
5606	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5607	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
5608
5609// Prefer a tbody over its parent table for containing new rows
5610function manipulationTarget( elem, content ) {
5611	if ( nodeName( elem, "table" ) &&
5612		nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
5613
5614		return jQuery( elem ).children( "tbody" )[ 0 ] || elem;
5615	}
5616
5617	return elem;
5618}
5619
5620// Replace/restore the type attribute of script elements for safe DOM manipulation
5621function disableScript( elem ) {
5622	elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
5623	return elem;
5624}
5625function restoreScript( elem ) {
5626	if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
5627		elem.type = elem.type.slice( 5 );
5628	} else {
5629		elem.removeAttribute( "type" );
5630	}
5631
5632	return elem;
5633}
5634
5635function cloneCopyEvent( src, dest ) {
5636	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
5637
5638	if ( dest.nodeType !== 1 ) {
5639		return;
5640	}
5641
5642	// 1. Copy private data: events, handlers, etc.
5643	if ( dataPriv.hasData( src ) ) {
5644		pdataOld = dataPriv.access( src );
5645		pdataCur = dataPriv.set( dest, pdataOld );
5646		events = pdataOld.events;
5647
5648		if ( events ) {
5649			delete pdataCur.handle;
5650			pdataCur.events = {};
5651
5652			for ( type in events ) {
5653				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5654					jQuery.event.add( dest, type, events[ type ][ i ] );
5655				}
5656			}
5657		}
5658	}
5659
5660	// 2. Copy user data
5661	if ( dataUser.hasData( src ) ) {
5662		udataOld = dataUser.access( src );
5663		udataCur = jQuery.extend( {}, udataOld );
5664
5665		dataUser.set( dest, udataCur );
5666	}
5667}
5668
5669// Fix IE bugs, see support tests
5670function fixInput( src, dest ) {
5671	var nodeName = dest.nodeName.toLowerCase();
5672
5673	// Fails to persist the checked state of a cloned checkbox or radio button.
5674	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5675		dest.checked = src.checked;
5676
5677	// Fails to return the selected option to the default selected state when cloning options
5678	} else if ( nodeName === "input" || nodeName === "textarea" ) {
5679		dest.defaultValue = src.defaultValue;
5680	}
5681}
5682
5683function domManip( collection, args, callback, ignored ) {
5684
5685	// Flatten any nested arrays
5686	args = concat.apply( [], args );
5687
5688	var fragment, first, scripts, hasScripts, node, doc,
5689		i = 0,
5690		l = collection.length,
5691		iNoClone = l - 1,
5692		value = args[ 0 ],
5693		valueIsFunction = isFunction( value );
5694
5695	// We can't cloneNode fragments that contain checked, in WebKit
5696	if ( valueIsFunction ||
5697			( l > 1 && typeof value === "string" &&
5698				!support.checkClone && rchecked.test( value ) ) ) {
5699		return collection.each( function( index ) {
5700			var self = collection.eq( index );
5701			if ( valueIsFunction ) {
5702				args[ 0 ] = value.call( this, index, self.html() );
5703			}
5704			domManip( self, args, callback, ignored );
5705		} );
5706	}
5707
5708	if ( l ) {
5709		fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
5710		first = fragment.firstChild;
5711
5712		if ( fragment.childNodes.length === 1 ) {
5713			fragment = first;
5714		}
5715
5716		// Require either new content or an interest in ignored elements to invoke the callback
5717		if ( first || ignored ) {
5718			scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5719			hasScripts = scripts.length;
5720
5721			// Use the original fragment for the last item
5722			// instead of the first because it can end up
5723			// being emptied incorrectly in certain situations (#8070).
5724			for ( ; i < l; i++ ) {
5725				node = fragment;
5726
5727				if ( i !== iNoClone ) {
5728					node = jQuery.clone( node, true, true );
5729
5730					// Keep references to cloned scripts for later restoration
5731					if ( hasScripts ) {
5732
5733						// Support: Android <=4.0 only, PhantomJS 1 only
5734						// push.apply(_, arraylike) throws on ancient WebKit
5735						jQuery.merge( scripts, getAll( node, "script" ) );
5736					}
5737				}
5738
5739				callback.call( collection[ i ], node, i );
5740			}
5741
5742			if ( hasScripts ) {
5743				doc = scripts[ scripts.length - 1 ].ownerDocument;
5744
5745				// Reenable scripts
5746				jQuery.map( scripts, restoreScript );
5747
5748				// Evaluate executable scripts on first document insertion
5749				for ( i = 0; i < hasScripts; i++ ) {
5750					node = scripts[ i ];
5751					if ( rscriptType.test( node.type || "" ) &&
5752						!dataPriv.access( node, "globalEval" ) &&
5753						jQuery.contains( doc, node ) ) {
5754
5755						if ( node.src && ( node.type || "" ).toLowerCase()  !== "module" ) {
5756
5757							// Optional AJAX dependency, but won't run scripts if not present
5758							if ( jQuery._evalUrl ) {
5759								jQuery._evalUrl( node.src );
5760							}
5761						} else {
5762							DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node );
5763						}
5764					}
5765				}
5766			}
5767		}
5768	}
5769
5770	return collection;
5771}
5772
5773function remove( elem, selector, keepData ) {
5774	var node,
5775		nodes = selector ? jQuery.filter( selector, elem ) : elem,
5776		i = 0;
5777
5778	for ( ; ( node = nodes[ i ] ) != null; i++ ) {
5779		if ( !keepData && node.nodeType === 1 ) {
5780			jQuery.cleanData( getAll( node ) );
5781		}
5782
5783		if ( node.parentNode ) {
5784			if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
5785				setGlobalEval( getAll( node, "script" ) );
5786			}
5787			node.parentNode.removeChild( node );
5788		}
5789	}
5790
5791	return elem;
5792}
5793
5794jQuery.extend( {
5795	htmlPrefilter: function( html ) {
5796		return html.replace( rxhtmlTag, "<$1></$2>" );
5797	},
5798
5799	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5800		var i, l, srcElements, destElements,
5801			clone = elem.cloneNode( true ),
5802			inPage = jQuery.contains( elem.ownerDocument, elem );
5803
5804		// Fix IE cloning issues
5805		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
5806				!jQuery.isXMLDoc( elem ) ) {
5807
5808			// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
5809			destElements = getAll( clone );
5810			srcElements = getAll( elem );
5811
5812			for ( i = 0, l = srcElements.length; i < l; i++ ) {
5813				fixInput( srcElements[ i ], destElements[ i ] );
5814			}
5815		}
5816
5817		// Copy the events from the original to the clone
5818		if ( dataAndEvents ) {
5819			if ( deepDataAndEvents ) {
5820				srcElements = srcElements || getAll( elem );
5821				destElements = destElements || getAll( clone );
5822
5823				for ( i = 0, l = srcElements.length; i < l; i++ ) {
5824					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
5825				}
5826			} else {
5827				cloneCopyEvent( elem, clone );
5828			}
5829		}
5830
5831		// Preserve script evaluation history
5832		destElements = getAll( clone, "script" );
5833		if ( destElements.length > 0 ) {
5834			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
5835		}
5836
5837		// Return the cloned set
5838		return clone;
5839	},
5840
5841	cleanData: function( elems ) {
5842		var data, elem, type,
5843			special = jQuery.event.special,
5844			i = 0;
5845
5846		for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
5847			if ( acceptData( elem ) ) {
5848				if ( ( data = elem[ dataPriv.expando ] ) ) {
5849					if ( data.events ) {
5850						for ( type in data.events ) {
5851							if ( special[ type ] ) {
5852								jQuery.event.remove( elem, type );
5853
5854							// This is a shortcut to avoid jQuery.event.remove's overhead
5855							} else {
5856								jQuery.removeEvent( elem, type, data.handle );
5857							}
5858						}
5859					}
5860
vendor: 1,119 bytes, lines 5861-5905
5861					// Support: Chrome <=35 - 45+
5862					// Assign undefined instead of using delete, see Data#remove
5863					elem[ dataPriv.expando ] = undefined;
5864				}
5865				if ( elem[ dataUser.expando ] ) {
5866
5867					// Support: Chrome <=35 - 45+
5868					// Assign undefined instead of using delete, see Data#remove
5869					elem[ dataUser.expando ] = undefined;
5870				}
5871			}
5872		}
5873	}
5874} );
5875
5876jQuery.fn.extend( {
5877	detach: function( selector ) {
5878		return remove( this, selector, true );
5879	},
5880
5881	remove: function( selector ) {
5882		return remove( this, selector );
5883	},
5884
5885	text: function( value ) {
5886		return access( this, function( value ) {
5887			return value === undefined ?
5888				jQuery.text( this ) :
5889				this.empty().each( function() {
5890					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5891						this.textContent = value;
5892					}
5893				} );
5894		}, null, value, arguments.length );
5895	},
5896
5897	append: function() {
5898		return domManip( this, arguments, function( elem ) {
5899			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5900				var target = manipulationTarget( this, elem );
5901				target.appendChild( elem );
5902			}
5903		} );
5904	},
5905
vendor: 52,786 bytes, lines 5906-7960
5906	prepend: function() {
5907		return domManip( this, arguments, function( elem ) {
5908			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5909				var target = manipulationTarget( this, elem );
5910				target.insertBefore( elem, target.firstChild );
5911			}
5912		} );
5913	},
5914
5915	before: function() {
5916		return domManip( this, arguments, function( elem ) {
5917			if ( this.parentNode ) {
5918				this.parentNode.insertBefore( elem, this );
5919			}
5920		} );
5921	},
5922
5923	after: function() {
5924		return domManip( this, arguments, function( elem ) {
5925			if ( this.parentNode ) {
5926				this.parentNode.insertBefore( elem, this.nextSibling );
5927			}
5928		} );
5929	},
5930
5931	empty: function() {
5932		var elem,
5933			i = 0;
5934
5935		for ( ; ( elem = this[ i ] ) != null; i++ ) {
5936			if ( elem.nodeType === 1 ) {
5937
5938				// Prevent memory leaks
5939				jQuery.cleanData( getAll( elem, false ) );
5940
5941				// Remove any remaining nodes
5942				elem.textContent = "";
5943			}
5944		}
5945
5946		return this;
5947	},
5948
5949	clone: function( dataAndEvents, deepDataAndEvents ) {
5950		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5951		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5952
5953		return this.map( function() {
5954			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5955		} );
5956	},
5957
5958	html: function( value ) {
5959		return access( this, function( value ) {
5960			var elem = this[ 0 ] || {},
5961				i = 0,
5962				l = this.length;
5963
5964			if ( value === undefined && elem.nodeType === 1 ) {
5965				return elem.innerHTML;
5966			}
5967
5968			// See if we can take a shortcut and just use innerHTML
5969			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5970				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
5971
5972				value = jQuery.htmlPrefilter( value );
5973
5974				try {
5975					for ( ; i < l; i++ ) {
5976						elem = this[ i ] || {};
5977
5978						// Remove element nodes and prevent memory leaks
5979						if ( elem.nodeType === 1 ) {
5980							jQuery.cleanData( getAll( elem, false ) );
5981							elem.innerHTML = value;
5982						}
5983					}
5984
5985					elem = 0;
5986
5987				// If using innerHTML throws an exception, use the fallback method
5988				} catch ( e ) {}
5989			}
5990
5991			if ( elem ) {
5992				this.empty().append( value );
5993			}
5994		}, null, value, arguments.length );
5995	},
5996
5997	replaceWith: function() {
5998		var ignored = [];
5999
6000		// Make the changes, replacing each non-ignored context element with the new content
6001		return domManip( this, arguments, function( elem ) {
6002			var parent = this.parentNode;
6003
6004			if ( jQuery.inArray( this, ignored ) < 0 ) {
6005				jQuery.cleanData( getAll( this ) );
6006				if ( parent ) {
6007					parent.replaceChild( elem, this );
6008				}
6009			}
6010
6011		// Force callback invocation
6012		}, ignored );
6013	}
6014} );
6015
6016jQuery.each( {
6017	appendTo: "append",
6018	prependTo: "prepend",
6019	insertBefore: "before",
6020	insertAfter: "after",
6021	replaceAll: "replaceWith"
6022}, function( name, original ) {
6023	jQuery.fn[ name ] = function( selector ) {
6024		var elems,
6025			ret = [],
6026			insert = jQuery( selector ),
6027			last = insert.length - 1,
6028			i = 0;
6029
6030		for ( ; i <= last; i++ ) {
6031			elems = i === last ? this : this.clone( true );
6032			jQuery( insert[ i ] )[ original ]( elems );
6033
6034			// Support: Android <=4.0 only, PhantomJS 1 only
6035			// .get() because push.apply(_, arraylike) throws on ancient WebKit
6036			push.apply( ret, elems.get() );
6037		}
6038
6039		return this.pushStack( ret );
6040	};
6041} );
6042var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6043
6044var getStyles = function( elem ) {
6045
6046		// Support: IE <=11 only, Firefox <=30 (#15098, #14150)
6047		// IE throws on elements created in popups
6048		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6049		var view = elem.ownerDocument.defaultView;
6050
6051		if ( !view || !view.opener ) {
6052			view = window;
6053		}
6054
6055		return view.getComputedStyle( elem );
6056	};
6057
6058var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
6059
6060
6061
6062( function() {
6063
6064	// Executing both pixelPosition & boxSizingReliable tests require only one layout
6065	// so they're executed at the same time to save the second computation.
6066	function computeStyleTests() {
6067
6068		// This is a singleton, we need to execute it only once
6069		if ( !div ) {
6070			return;
6071		}
6072
6073		container.style.cssText = "position:absolute;left:-11111px;width:60px;" +
6074			"margin-top:1px;padding:0;border:0";
6075		div.style.cssText =
6076			"position:relative;display:block;box-sizing:border-box;overflow:scroll;" +
6077			"margin:auto;border:1px;padding:1px;" +
6078			"width:60%;top:1%";
6079		documentElement.appendChild( container ).appendChild( div );
6080
6081		var divStyle = window.getComputedStyle( div );
6082		pixelPositionVal = divStyle.top !== "1%";
6083
6084		// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
6085		reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;
6086
6087		// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3
6088		// Some styles come back with percentage values, even though they shouldn't
6089		div.style.right = "60%";
6090		pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;
6091
6092		// Support: IE 9 - 11 only
6093		// Detect misreporting of content dimensions for box-sizing:border-box elements
6094		boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;
6095
6096		// Support: IE 9 only
6097		// Detect overflow:scroll screwiness (gh-3699)
6098		div.style.position = "absolute";
6099		scrollboxSizeVal = div.offsetWidth === 36 || "absolute";
6100
6101		documentElement.removeChild( container );
6102
6103		// Nullify the div so it wouldn't be stored in the memory and
6104		// it will also be a sign that checks already performed
6105		div = null;
6106	}
6107
6108	function roundPixelMeasures( measure ) {
6109		return Math.round( parseFloat( measure ) );
6110	}
6111
6112	var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
6113		reliableMarginLeftVal,
6114		container = document.createElement( "div" ),
6115		div = document.createElement( "div" );
6116
6117	// Finish early in limited (non-browser) environments
6118	if ( !div.style ) {
6119		return;
6120	}
6121
6122	// Support: IE <=9 - 11 only
6123	// Style of cloned element affects source element cloned (#8908)
6124	div.style.backgroundClip = "content-box";
6125	div.cloneNode( true ).style.backgroundClip = "";
6126	support.clearCloneStyle = div.style.backgroundClip === "content-box";
6127
6128	jQuery.extend( support, {
6129		boxSizingReliable: function() {
6130			computeStyleTests();
6131			return boxSizingReliableVal;
6132		},
6133		pixelBoxStyles: function() {
6134			computeStyleTests();
6135			return pixelBoxStylesVal;
6136		},
6137		pixelPosition: function() {
6138			computeStyleTests();
6139			return pixelPositionVal;
6140		},
6141		reliableMarginLeft: function() {
6142			computeStyleTests();
6143			return reliableMarginLeftVal;
6144		},
6145		scrollboxSize: function() {
6146			computeStyleTests();
6147			return scrollboxSizeVal;
6148		}
6149	} );
6150} )();
6151
6152
6153function curCSS( elem, name, computed ) {
6154	var width, minWidth, maxWidth, ret,
6155
6156		// Support: Firefox 51+
6157		// Retrieving style before computed somehow
6158		// fixes an issue with getting wrong values
6159		// on detached elements
6160		style = elem.style;
6161
6162	computed = computed || getStyles( elem );
6163
6164	// getPropertyValue is needed for:
6165	//   .css('filter') (IE 9 only, #12537)
6166	//   .css('--customProperty) (#3144)
6167	if ( computed ) {
6168		ret = computed.getPropertyValue( name ) || computed[ name ];
6169
6170		if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6171			ret = jQuery.style( elem, name );
6172		}
6173
6174		// A tribute to the "awesome hack by Dean Edwards"
6175		// Android Browser returns percentage for some values,
6176		// but width seems to be reliably pixels.
6177		// This is against the CSSOM draft spec:
6178		// https://drafts.csswg.org/cssom/#resolved-values
6179		if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {
6180
6181			// Remember the original values
6182			width = style.width;
6183			minWidth = style.minWidth;
6184			maxWidth = style.maxWidth;
6185
6186			// Put in the new values to get a computed value out
6187			style.minWidth = style.maxWidth = style.width = ret;
6188			ret = computed.width;
6189
6190			// Revert the changed values
6191			style.width = width;
6192			style.minWidth = minWidth;
6193			style.maxWidth = maxWidth;
6194		}
6195	}
6196
6197	return ret !== undefined ?
6198
6199		// Support: IE <=9 - 11 only
6200		// IE returns zIndex value as an integer.
6201		ret + "" :
6202		ret;
6203}
6204
6205
6206function addGetHookIf( conditionFn, hookFn ) {
6207
6208	// Define the hook, we'll check on the first run if it's really needed.
6209	return {
6210		get: function() {
6211			if ( conditionFn() ) {
6212
6213				// Hook not needed (or it's not possible to use it due
6214				// to missing dependency), remove it.
6215				delete this.get;
6216				return;
6217			}
6218
6219			// Hook needed; redefine it so that the support test is not executed again.
6220			return ( this.get = hookFn ).apply( this, arguments );
6221		}
6222	};
6223}
6224
6225
6226var
6227
6228	// Swappable if display is none or starts with table
6229	// except "table", "table-cell", or "table-caption"
6230	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6231	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6232	rcustomProp = /^--/,
6233	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6234	cssNormalTransform = {
6235		letterSpacing: "0",
6236		fontWeight: "400"
6237	},
6238
6239	cssPrefixes = [ "Webkit", "Moz", "ms" ],
6240	emptyStyle = document.createElement( "div" ).style;
6241
6242// Return a css property mapped to a potentially vendor prefixed property
6243function vendorPropName( name ) {
6244
6245	// Shortcut for names that are not vendor prefixed
6246	if ( name in emptyStyle ) {
6247		return name;
6248	}
6249
6250	// Check for vendor prefixed names
6251	var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
6252		i = cssPrefixes.length;
6253
6254	while ( i-- ) {
6255		name = cssPrefixes[ i ] + capName;
6256		if ( name in emptyStyle ) {
6257			return name;
6258		}
6259	}
6260}
6261
6262// Return a property mapped along what jQuery.cssProps suggests or to
6263// a vendor prefixed property.
6264function finalPropName( name ) {
6265	var ret = jQuery.cssProps[ name ];
6266	if ( !ret ) {
6267		ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;
6268	}
6269	return ret;
6270}
6271
6272function setPositiveNumber( elem, value, subtract ) {
6273
6274	// Any relative (+/-) values have already been
6275	// normalized at this point
6276	var matches = rcssNum.exec( value );
6277	return matches ?
6278
6279		// Guard against undefined "subtract", e.g., when used as in cssHooks
6280		Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
6281		value;
6282}
6283
6284function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
6285	var i = dimension === "width" ? 1 : 0,
6286		extra = 0,
6287		delta = 0;
6288
6289	// Adjustment may not be necessary
6290	if ( box === ( isBorderBox ? "border" : "content" ) ) {
6291		return 0;
6292	}
6293
6294	for ( ; i < 4; i += 2 ) {
6295
6296		// Both box models exclude margin
6297		if ( box === "margin" ) {
6298			delta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
6299		}
6300
6301		// If we get here with a content-box, we're seeking "padding" or "border" or "margin"
6302		if ( !isBorderBox ) {
6303
6304			// Add padding
6305			delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6306
6307			// For "border" or "margin", add border
6308			if ( box !== "padding" ) {
6309				delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6310
6311			// But still keep track of it otherwise
6312			} else {
6313				extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6314			}
6315
6316		// If we get here with a border-box (content + padding + border), we're seeking "content" or
6317		// "padding" or "margin"
6318		} else {
6319
6320			// For "content", subtract padding
6321			if ( box === "content" ) {
6322				delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6323			}
6324
6325			// For "content" or "padding", subtract border
6326			if ( box !== "margin" ) {
6327				delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6328			}
6329		}
6330	}
6331
6332	// Account for positive content-box scroll gutter when requested by providing computedVal
6333	if ( !isBorderBox && computedVal >= 0 ) {
6334
6335		// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
6336		// Assuming integer scroll gutter, subtract the rest and round down
6337		delta += Math.max( 0, Math.ceil(
6338			elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6339			computedVal -
6340			delta -
6341			extra -
6342			0.5
6343		) );
6344	}
6345
6346	return delta;
6347}
6348
6349function getWidthOrHeight( elem, dimension, extra ) {
6350
6351	// Start with computed style
6352	var styles = getStyles( elem ),
6353		val = curCSS( elem, dimension, styles ),
6354		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6355		valueIsBorderBox = isBorderBox;
6356
6357	// Support: Firefox <=54
6358	// Return a confounding non-pixel value or feign ignorance, as appropriate.
6359	if ( rnumnonpx.test( val ) ) {
6360		if ( !extra ) {
6361			return val;
6362		}
6363		val = "auto";
6364	}
6365
6366	// Check for style in case a browser which returns unreliable values
6367	// for getComputedStyle silently falls back to the reliable elem.style
6368	valueIsBorderBox = valueIsBorderBox &&
6369		( support.boxSizingReliable() || val === elem.style[ dimension ] );
6370
6371	// Fall back to offsetWidth/offsetHeight when value is "auto"
6372	// This happens for inline elements with no explicit setting (gh-3571)
6373	// Support: Android <=4.1 - 4.3 only
6374	// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
6375	if ( val === "auto" ||
6376		!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) {
6377
6378		val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ];
6379
6380		// offsetWidth/offsetHeight provide border-box values
6381		valueIsBorderBox = true;
6382	}
6383
6384	// Normalize "" and auto
6385	val = parseFloat( val ) || 0;
6386
6387	// Adjust for the element's box model
6388	return ( val +
6389		boxModelAdjustment(
6390			elem,
6391			dimension,
6392			extra || ( isBorderBox ? "border" : "content" ),
6393			valueIsBorderBox,
6394			styles,
6395
6396			// Provide the current computed size to request scroll gutter calculation (gh-3589)
6397			val
6398		)
6399	) + "px";
6400}
6401
6402jQuery.extend( {
6403
6404	// Add in style property hooks for overriding the default
6405	// behavior of getting and setting a style property
6406	cssHooks: {
6407		opacity: {
6408			get: function( elem, computed ) {
6409				if ( computed ) {
6410
6411					// We should always get a number back from opacity
6412					var ret = curCSS( elem, "opacity" );
6413					return ret === "" ? "1" : ret;
6414				}
6415			}
6416		}
6417	},
6418
6419	// Don't automatically add "px" to these possibly-unitless properties
6420	cssNumber: {
6421		"animationIterationCount": true,
6422		"columnCount": true,
6423		"fillOpacity": true,
6424		"flexGrow": true,
6425		"flexShrink": true,
6426		"fontWeight": true,
6427		"lineHeight": true,
6428		"opacity": true,
6429		"order": true,
6430		"orphans": true,
6431		"widows": true,
6432		"zIndex": true,
6433		"zoom": true
6434	},
6435
6436	// Add in properties whose names you wish to fix before
6437	// setting or getting the value
6438	cssProps: {},
6439
6440	// Get and set the style property on a DOM Node
6441	style: function( elem, name, value, extra ) {
6442
6443		// Don't set styles on text and comment nodes
6444		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6445			return;
6446		}
6447
6448		// Make sure that we're working with the right name
6449		var ret, type, hooks,
6450			origName = camelCase( name ),
6451			isCustomProp = rcustomProp.test( name ),
6452			style = elem.style;
6453
6454		// Make sure that we're working with the right name. We don't
6455		// want to query the value if it is a CSS custom property
6456		// since they are user-defined.
6457		if ( !isCustomProp ) {
6458			name = finalPropName( origName );
6459		}
6460
6461		// Gets hook for the prefixed version, then unprefixed version
6462		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6463
6464		// Check if we're setting a value
6465		if ( value !== undefined ) {
6466			type = typeof value;
6467
6468			// Convert "+=" or "-=" to relative numbers (#7345)
6469			if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
6470				value = adjustCSS( elem, name, ret );
6471
6472				// Fixes bug #9237
6473				type = "number";
6474			}
6475
6476			// Make sure that null and NaN values aren't set (#7116)
6477			if ( value == null || value !== value ) {
6478				return;
6479			}
6480
6481			// If a number was passed in, add the unit (except for certain CSS properties)
6482			if ( type === "number" ) {
6483				value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
6484			}
6485
6486			// background-* props affect original clone's values
6487			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
6488				style[ name ] = "inherit";
6489			}
6490
6491			// If a hook was provided, use that value, otherwise just set the specified value
6492			if ( !hooks || !( "set" in hooks ) ||
6493				( value = hooks.set( elem, value, extra ) ) !== undefined ) {
6494
6495				if ( isCustomProp ) {
6496					style.setProperty( name, value );
6497				} else {
6498					style[ name ] = value;
6499				}
6500			}
6501
6502		} else {
6503
6504			// If a hook was provided get the non-computed value from there
6505			if ( hooks && "get" in hooks &&
6506				( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
6507
6508				return ret;
6509			}
6510
6511			// Otherwise just get the value from the style object
6512			return style[ name ];
6513		}
6514	},
6515
6516	css: function( elem, name, extra, styles ) {
6517		var val, num, hooks,
6518			origName = camelCase( name ),
6519			isCustomProp = rcustomProp.test( name );
6520
6521		// Make sure that we're working with the right name. We don't
6522		// want to modify the value if it is a CSS custom property
6523		// since they are user-defined.
6524		if ( !isCustomProp ) {
6525			name = finalPropName( origName );
6526		}
6527
6528		// Try prefixed name followed by the unprefixed name
6529		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6530
6531		// If a hook was provided get the computed value from there
6532		if ( hooks && "get" in hooks ) {
6533			val = hooks.get( elem, true, extra );
6534		}
6535
6536		// Otherwise, if a way to get the computed value exists, use that
6537		if ( val === undefined ) {
6538			val = curCSS( elem, name, styles );
6539		}
6540
6541		// Convert "normal" to computed value
6542		if ( val === "normal" && name in cssNormalTransform ) {
6543			val = cssNormalTransform[ name ];
6544		}
6545
6546		// Make numeric if forced or a qualifier was provided and val looks numeric
6547		if ( extra === "" || extra ) {
6548			num = parseFloat( val );
6549			return extra === true || isFinite( num ) ? num || 0 : val;
6550		}
6551
6552		return val;
6553	}
6554} );
6555
6556jQuery.each( [ "height", "width" ], function( i, dimension ) {
6557	jQuery.cssHooks[ dimension ] = {
6558		get: function( elem, computed, extra ) {
6559			if ( computed ) {
6560
6561				// Certain elements can have dimension info if we invisibly show them
6562				// but it must have a current display style that would benefit
6563				return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
6564
6565					// Support: Safari 8+
6566					// Table columns in Safari have non-zero offsetWidth & zero
6567					// getBoundingClientRect().width unless display is changed.
6568					// Support: IE <=11 only
6569					// Running getBoundingClientRect on a disconnected node
6570					// in IE throws an error.
6571					( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
6572						swap( elem, cssShow, function() {
6573							return getWidthOrHeight( elem, dimension, extra );
6574						} ) :
6575						getWidthOrHeight( elem, dimension, extra );
6576			}
6577		},
6578
6579		set: function( elem, value, extra ) {
6580			var matches,
6581				styles = getStyles( elem ),
6582				isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6583				subtract = extra && boxModelAdjustment(
6584					elem,
6585					dimension,
6586					extra,
6587					isBorderBox,
6588					styles
6589				);
6590
6591			// Account for unreliable border-box dimensions by comparing offset* to computed and
6592			// faking a content-box to get border and padding (gh-3699)
6593			if ( isBorderBox && support.scrollboxSize() === styles.position ) {
6594				subtract -= Math.ceil(
6595					elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
6596					parseFloat( styles[ dimension ] ) -
6597					boxModelAdjustment( elem, dimension, "border", false, styles ) -
6598					0.5
6599				);
6600			}
6601
6602			// Convert to pixels if value adjustment is needed
6603			if ( subtract && ( matches = rcssNum.exec( value ) ) &&
6604				( matches[ 3 ] || "px" ) !== "px" ) {
6605
6606				elem.style[ dimension ] = value;
6607				value = jQuery.css( elem, dimension );
6608			}
6609
6610			return setPositiveNumber( elem, value, subtract );
6611		}
6612	};
6613} );
6614
6615jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
6616	function( elem, computed ) {
6617		if ( computed ) {
6618			return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
6619				elem.getBoundingClientRect().left -
6620					swap( elem, { marginLeft: 0 }, function() {
6621						return elem.getBoundingClientRect().left;
6622					} )
6623				) + "px";
6624		}
6625	}
6626);
6627
6628// These hooks are used by animate to expand properties
6629jQuery.each( {
6630	margin: "",
6631	padding: "",
6632	border: "Width"
6633}, function( prefix, suffix ) {
6634	jQuery.cssHooks[ prefix + suffix ] = {
6635		expand: function( value ) {
6636			var i = 0,
6637				expanded = {},
6638
6639				// Assumes a single number if not a string
6640				parts = typeof value === "string" ? value.split( " " ) : [ value ];
6641
6642			for ( ; i < 4; i++ ) {
6643				expanded[ prefix + cssExpand[ i ] + suffix ] =
6644					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6645			}
6646
6647			return expanded;
6648		}
6649	};
6650
6651	if ( prefix !== "margin" ) {
6652		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6653	}
6654} );
6655
6656jQuery.fn.extend( {
6657	css: function( name, value ) {
6658		return access( this, function( elem, name, value ) {
6659			var styles, len,
6660				map = {},
6661				i = 0;
6662
6663			if ( Array.isArray( name ) ) {
6664				styles = getStyles( elem );
6665				len = name.length;
6666
6667				for ( ; i < len; i++ ) {
6668					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6669				}
6670
6671				return map;
6672			}
6673
6674			return value !== undefined ?
6675				jQuery.style( elem, name, value ) :
6676				jQuery.css( elem, name );
6677		}, name, value, arguments.length > 1 );
6678	}
6679} );
6680
6681
6682function Tween( elem, options, prop, end, easing ) {
6683	return new Tween.prototype.init( elem, options, prop, end, easing );
6684}
6685jQuery.Tween = Tween;
6686
6687Tween.prototype = {
6688	constructor: Tween,
6689	init: function( elem, options, prop, end, easing, unit ) {
6690		this.elem = elem;
6691		this.prop = prop;
6692		this.easing = easing || jQuery.easing._default;
6693		this.options = options;
6694		this.start = this.now = this.cur();
6695		this.end = end;
6696		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
6697	},
6698	cur: function() {
6699		var hooks = Tween.propHooks[ this.prop ];
6700
6701		return hooks && hooks.get ?
6702			hooks.get( this ) :
6703			Tween.propHooks._default.get( this );
6704	},
6705	run: function( percent ) {
6706		var eased,
6707			hooks = Tween.propHooks[ this.prop ];
6708
6709		if ( this.options.duration ) {
6710			this.pos = eased = jQuery.easing[ this.easing ](
6711				percent, this.options.duration * percent, 0, 1, this.options.duration
6712			);
6713		} else {
6714			this.pos = eased = percent;
6715		}
6716		this.now = ( this.end - this.start ) * eased + this.start;
6717
6718		if ( this.options.step ) {
6719			this.options.step.call( this.elem, this.now, this );
6720		}
6721
6722		if ( hooks && hooks.set ) {
6723			hooks.set( this );
6724		} else {
6725			Tween.propHooks._default.set( this );
6726		}
6727		return this;
6728	}
6729};
6730
6731Tween.prototype.init.prototype = Tween.prototype;
6732
6733Tween.propHooks = {
6734	_default: {
6735		get: function( tween ) {
6736			var result;
6737
6738			// Use a property on the element directly when it is not a DOM element,
6739			// or when there is no matching style property that exists.
6740			if ( tween.elem.nodeType !== 1 ||
6741				tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
6742				return tween.elem[ tween.prop ];
6743			}
6744
6745			// Passing an empty string as a 3rd parameter to .css will automatically
6746			// attempt a parseFloat and fallback to a string if the parse fails.
6747			// Simple values such as "10px" are parsed to Float;
6748			// complex values such as "rotate(1rad)" are returned as-is.
6749			result = jQuery.css( tween.elem, tween.prop, "" );
6750
6751			// Empty strings, null, undefined and "auto" are converted to 0.
6752			return !result || result === "auto" ? 0 : result;
6753		},
6754		set: function( tween ) {
6755
6756			// Use step hook for back compat.
6757			// Use cssHook if its there.
6758			// Use .style if available and use plain properties where available.
6759			if ( jQuery.fx.step[ tween.prop ] ) {
6760				jQuery.fx.step[ tween.prop ]( tween );
6761			} else if ( tween.elem.nodeType === 1 &&
6762				( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
6763					jQuery.cssHooks[ tween.prop ] ) ) {
6764				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
6765			} else {
6766				tween.elem[ tween.prop ] = tween.now;
6767			}
6768		}
6769	}
6770};
6771
6772// Support: IE <=9 only
6773// Panic based approach to setting things on disconnected nodes
6774Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
6775	set: function( tween ) {
6776		if ( tween.elem.nodeType && tween.elem.parentNode ) {
6777			tween.elem[ tween.prop ] = tween.now;
6778		}
6779	}
6780};
6781
6782jQuery.easing = {
6783	linear: function( p ) {
6784		return p;
6785	},
6786	swing: function( p ) {
6787		return 0.5 - Math.cos( p * Math.PI ) / 2;
6788	},
6789	_default: "swing"
6790};
6791
6792jQuery.fx = Tween.prototype.init;
6793
6794// Back compat <1.8 extension point
6795jQuery.fx.step = {};
6796
6797
6798
6799
6800var
6801	fxNow, inProgress,
6802	rfxtypes = /^(?:toggle|show|hide)$/,
6803	rrun = /queueHooks$/;
6804
6805function schedule() {
6806	if ( inProgress ) {
6807		if ( document.hidden === false && window.requestAnimationFrame ) {
6808			window.requestAnimationFrame( schedule );
6809		} else {
6810			window.setTimeout( schedule, jQuery.fx.interval );
6811		}
6812
6813		jQuery.fx.tick();
6814	}
6815}
6816
6817// Animations created synchronously will run synchronously
6818function createFxNow() {
6819	window.setTimeout( function() {
6820		fxNow = undefined;
6821	} );
6822	return ( fxNow = Date.now() );
6823}
6824
6825// Generate parameters to create a standard animation
6826function genFx( type, includeWidth ) {
6827	var which,
6828		i = 0,
6829		attrs = { height: type };
6830
6831	// If we include width, step value is 1 to do all cssExpand values,
6832	// otherwise step value is 2 to skip over Left and Right
6833	includeWidth = includeWidth ? 1 : 0;
6834	for ( ; i < 4; i += 2 - includeWidth ) {
6835		which = cssExpand[ i ];
6836		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
6837	}
6838
6839	if ( includeWidth ) {
6840		attrs.opacity = attrs.width = type;
6841	}
6842
6843	return attrs;
6844}
6845
6846function createTween( value, prop, animation ) {
6847	var tween,
6848		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
6849		index = 0,
6850		length = collection.length;
6851	for ( ; index < length; index++ ) {
6852		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
6853
6854			// We're done with this property
6855			return tween;
6856		}
6857	}
6858}
6859
6860function defaultPrefilter( elem, props, opts ) {
6861	var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
6862		isBox = "width" in props || "height" in props,
6863		anim = this,
6864		orig = {},
6865		style = elem.style,
6866		hidden = elem.nodeType && isHiddenWithinTree( elem ),
6867		dataShow = dataPriv.get( elem, "fxshow" );
6868
6869	// Queue-skipping animations hijack the fx hooks
6870	if ( !opts.queue ) {
6871		hooks = jQuery._queueHooks( elem, "fx" );
6872		if ( hooks.unqueued == null ) {
6873			hooks.unqueued = 0;
6874			oldfire = hooks.empty.fire;
6875			hooks.empty.fire = function() {
6876				if ( !hooks.unqueued ) {
6877					oldfire();
6878				}
6879			};
6880		}
6881		hooks.unqueued++;
6882
6883		anim.always( function() {
6884
6885			// Ensure the complete handler is called before this completes
6886			anim.always( function() {
6887				hooks.unqueued--;
6888				if ( !jQuery.queue( elem, "fx" ).length ) {
6889					hooks.empty.fire();
6890				}
6891			} );
6892		} );
6893	}
6894
6895	// Detect show/hide animations
6896	for ( prop in props ) {
6897		value = props[ prop ];
6898		if ( rfxtypes.test( value ) ) {
6899			delete props[ prop ];
6900			toggle = toggle || value === "toggle";
6901			if ( value === ( hidden ? "hide" : "show" ) ) {
6902
6903				// Pretend to be hidden if this is a "show" and
6904				// there is still data from a stopped show/hide
6905				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
6906					hidden = true;
6907
6908				// Ignore all other no-op show/hide data
6909				} else {
6910					continue;
6911				}
6912			}
6913			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
6914		}
6915	}
6916
6917	// Bail out if this is a no-op like .hide().hide()
6918	propTween = !jQuery.isEmptyObject( props );
6919	if ( !propTween && jQuery.isEmptyObject( orig ) ) {
6920		return;
6921	}
6922
6923	// Restrict "overflow" and "display" styles during box animations
6924	if ( isBox && elem.nodeType === 1 ) {
6925
6926		// Support: IE <=9 - 11, Edge 12 - 15
6927		// Record all 3 overflow attributes because IE does not infer the shorthand
6928		// from identically-valued overflowX and overflowY and Edge just mirrors
6929		// the overflowX value there.
6930		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
6931
6932		// Identify a display type, preferring old show/hide data over the CSS cascade
6933		restoreDisplay = dataShow && dataShow.display;
6934		if ( restoreDisplay == null ) {
6935			restoreDisplay = dataPriv.get( elem, "display" );
6936		}
6937		display = jQuery.css( elem, "display" );
6938		if ( display === "none" ) {
6939			if ( restoreDisplay ) {
6940				display = restoreDisplay;
6941			} else {
6942
6943				// Get nonempty value(s) by temporarily forcing visibility
6944				showHide( [ elem ], true );
6945				restoreDisplay = elem.style.display || restoreDisplay;
6946				display = jQuery.css( elem, "display" );
6947				showHide( [ elem ] );
6948			}
6949		}
6950
6951		// Animate inline elements as inline-block
6952		if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
6953			if ( jQuery.css( elem, "float" ) === "none" ) {
6954
6955				// Restore the original display value at the end of pure show/hide animations
6956				if ( !propTween ) {
6957					anim.done( function() {
6958						style.display = restoreDisplay;
6959					} );
6960					if ( restoreDisplay == null ) {
6961						display = style.display;
6962						restoreDisplay = display === "none" ? "" : display;
6963					}
6964				}
6965				style.display = "inline-block";
6966			}
6967		}
6968	}
6969
6970	if ( opts.overflow ) {
6971		style.overflow = "hidden";
6972		anim.always( function() {
6973			style.overflow = opts.overflow[ 0 ];
6974			style.overflowX = opts.overflow[ 1 ];
6975			style.overflowY = opts.overflow[ 2 ];
6976		} );
6977	}
6978
6979	// Implement show/hide animations
6980	propTween = false;
6981	for ( prop in orig ) {
6982
6983		// General show/hide setup for this element animation
6984		if ( !propTween ) {
6985			if ( dataShow ) {
6986				if ( "hidden" in dataShow ) {
6987					hidden = dataShow.hidden;
6988				}
6989			} else {
6990				dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
6991			}
6992
6993			// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
6994			if ( toggle ) {
6995				dataShow.hidden = !hidden;
6996			}
6997
6998			// Show elements before animating them
6999			if ( hidden ) {
7000				showHide( [ elem ], true );
7001			}
7002
7003			/* eslint-disable no-loop-func */
7004
7005			anim.done( function() {
7006
7007			/* eslint-enable no-loop-func */
7008
7009				// The final step of a "hide" animation is actually hiding the element
7010				if ( !hidden ) {
7011					showHide( [ elem ] );
7012				}
7013				dataPriv.remove( elem, "fxshow" );
7014				for ( prop in orig ) {
7015					jQuery.style( elem, prop, orig[ prop ] );
7016				}
7017			} );
7018		}
7019
7020		// Per-property setup
7021		propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7022		if ( !( prop in dataShow ) ) {
7023			dataShow[ prop ] = propTween.start;
7024			if ( hidden ) {
7025				propTween.end = propTween.start;
7026				propTween.start = 0;
7027			}
7028		}
7029	}
7030}
7031
7032function propFilter( props, specialEasing ) {
7033	var index, name, easing, value, hooks;
7034
7035	// camelCase, specialEasing and expand cssHook pass
7036	for ( index in props ) {
7037		name = camelCase( index );
7038		easing = specialEasing[ name ];
7039		value = props[ index ];
7040		if ( Array.isArray( value ) ) {
7041			easing = value[ 1 ];
7042			value = props[ index ] = value[ 0 ];
7043		}
7044
7045		if ( index !== name ) {
7046			props[ name ] = value;
7047			delete props[ index ];
7048		}
7049
7050		hooks = jQuery.cssHooks[ name ];
7051		if ( hooks && "expand" in hooks ) {
7052			value = hooks.expand( value );
7053			delete props[ name ];
7054
7055			// Not quite $.extend, this won't overwrite existing keys.
7056			// Reusing 'index' because we have the correct "name"
7057			for ( index in value ) {
7058				if ( !( index in props ) ) {
7059					props[ index ] = value[ index ];
7060					specialEasing[ index ] = easing;
7061				}
7062			}
7063		} else {
7064			specialEasing[ name ] = easing;
7065		}
7066	}
7067}
7068
7069function Animation( elem, properties, options ) {
7070	var result,
7071		stopped,
7072		index = 0,
7073		length = Animation.prefilters.length,
7074		deferred = jQuery.Deferred().always( function() {
7075
7076			// Don't match elem in the :animated selector
7077			delete tick.elem;
7078		} ),
7079		tick = function() {
7080			if ( stopped ) {
7081				return false;
7082			}
7083			var currentTime = fxNow || createFxNow(),
7084				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7085
7086				// Support: Android 2.3 only
7087				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
7088				temp = remaining / animation.duration || 0,
7089				percent = 1 - temp,
7090				index = 0,
7091				length = animation.tweens.length;
7092
7093			for ( ; index < length; index++ ) {
7094				animation.tweens[ index ].run( percent );
7095			}
7096
7097			deferred.notifyWith( elem, [ animation, percent, remaining ] );
7098
7099			// If there's more to do, yield
7100			if ( percent < 1 && length ) {
7101				return remaining;
7102			}
7103
7104			// If this was an empty animation, synthesize a final progress notification
7105			if ( !length ) {
7106				deferred.notifyWith( elem, [ animation, 1, 0 ] );
7107			}
7108
7109			// Resolve the animation and report its conclusion
7110			deferred.resolveWith( elem, [ animation ] );
7111			return false;
7112		},
7113		animation = deferred.promise( {
7114			elem: elem,
7115			props: jQuery.extend( {}, properties ),
7116			opts: jQuery.extend( true, {
7117				specialEasing: {},
7118				easing: jQuery.easing._default
7119			}, options ),
7120			originalProperties: properties,
7121			originalOptions: options,
7122			startTime: fxNow || createFxNow(),
7123			duration: options.duration,
7124			tweens: [],
7125			createTween: function( prop, end ) {
7126				var tween = jQuery.Tween( elem, animation.opts, prop, end,
7127						animation.opts.specialEasing[ prop ] || animation.opts.easing );
7128				animation.tweens.push( tween );
7129				return tween;
7130			},
7131			stop: function( gotoEnd ) {
7132				var index = 0,
7133
7134					// If we are going to the end, we want to run all the tweens
7135					// otherwise we skip this part
7136					length = gotoEnd ? animation.tweens.length : 0;
7137				if ( stopped ) {
7138					return this;
7139				}
7140				stopped = true;
7141				for ( ; index < length; index++ ) {
7142					animation.tweens[ index ].run( 1 );
7143				}
7144
7145				// Resolve when we played the last frame; otherwise, reject
7146				if ( gotoEnd ) {
7147					deferred.notifyWith( elem, [ animation, 1, 0 ] );
7148					deferred.resolveWith( elem, [ animation, gotoEnd ] );
7149				} else {
7150					deferred.rejectWith( elem, [ animation, gotoEnd ] );
7151				}
7152				return this;
7153			}
7154		} ),
7155		props = animation.props;
7156
7157	propFilter( props, animation.opts.specialEasing );
7158
7159	for ( ; index < length; index++ ) {
7160		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
7161		if ( result ) {
7162			if ( isFunction( result.stop ) ) {
7163				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
7164					result.stop.bind( result );
7165			}
7166			return result;
7167		}
7168	}
7169
7170	jQuery.map( props, createTween, animation );
7171
7172	if ( isFunction( animation.opts.start ) ) {
7173		animation.opts.start.call( elem, animation );
7174	}
7175
7176	// Attach callbacks from options
7177	animation
7178		.progress( animation.opts.progress )
7179		.done( animation.opts.done, animation.opts.complete )
7180		.fail( animation.opts.fail )
7181		.always( animation.opts.always );
7182
7183	jQuery.fx.timer(
7184		jQuery.extend( tick, {
7185			elem: elem,
7186			anim: animation,
7187			queue: animation.opts.queue
7188		} )
7189	);
7190
7191	return animation;
7192}
7193
7194jQuery.Animation = jQuery.extend( Animation, {
7195
7196	tweeners: {
7197		"*": [ function( prop, value ) {
7198			var tween = this.createTween( prop, value );
7199			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
7200			return tween;
7201		} ]
7202	},
7203
7204	tweener: function( props, callback ) {
7205		if ( isFunction( props ) ) {
7206			callback = props;
7207			props = [ "*" ];
7208		} else {
7209			props = props.match( rnothtmlwhite );
7210		}
7211
7212		var prop,
7213			index = 0,
7214			length = props.length;
7215
7216		for ( ; index < length; index++ ) {
7217			prop = props[ index ];
7218			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
7219			Animation.tweeners[ prop ].unshift( callback );
7220		}
7221	},
7222
7223	prefilters: [ defaultPrefilter ],
7224
7225	prefilter: function( callback, prepend ) {
7226		if ( prepend ) {
7227			Animation.prefilters.unshift( callback );
7228		} else {
7229			Animation.prefilters.push( callback );
7230		}
7231	}
7232} );
7233
7234jQuery.speed = function( speed, easing, fn ) {
7235	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7236		complete: fn || !fn && easing ||
7237			isFunction( speed ) && speed,
7238		duration: speed,
7239		easing: fn && easing || easing && !isFunction( easing ) && easing
7240	};
7241
7242	// Go to the end state if fx are off
7243	if ( jQuery.fx.off ) {
7244		opt.duration = 0;
7245
7246	} else {
7247		if ( typeof opt.duration !== "number" ) {
7248			if ( opt.duration in jQuery.fx.speeds ) {
7249				opt.duration = jQuery.fx.speeds[ opt.duration ];
7250
7251			} else {
7252				opt.duration = jQuery.fx.speeds._default;
7253			}
7254		}
7255	}
7256
7257	// Normalize opt.queue - true/undefined/null -> "fx"
7258	if ( opt.queue == null || opt.queue === true ) {
7259		opt.queue = "fx";
7260	}
7261
7262	// Queueing
7263	opt.old = opt.complete;
7264
7265	opt.complete = function() {
7266		if ( isFunction( opt.old ) ) {
7267			opt.old.call( this );
7268		}
7269
7270		if ( opt.queue ) {
7271			jQuery.dequeue( this, opt.queue );
7272		}
7273	};
7274
7275	return opt;
7276};
7277
7278jQuery.fn.extend( {
7279	fadeTo: function( speed, to, easing, callback ) {
7280
7281		// Show any hidden elements after setting opacity to 0
7282		return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
7283
7284			// Animate to the value specified
7285			.end().animate( { opacity: to }, speed, easing, callback );
7286	},
7287	animate: function( prop, speed, easing, callback ) {
7288		var empty = jQuery.isEmptyObject( prop ),
7289			optall = jQuery.speed( speed, easing, callback ),
7290			doAnimation = function() {
7291
7292				// Operate on a copy of prop so per-property easing won't be lost
7293				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7294
7295				// Empty animations, or finishing resolves immediately
7296				if ( empty || dataPriv.get( this, "finish" ) ) {
7297					anim.stop( true );
7298				}
7299			};
7300			doAnimation.finish = doAnimation;
7301
7302		return empty || optall.queue === false ?
7303			this.each( doAnimation ) :
7304			this.queue( optall.queue, doAnimation );
7305	},
7306	stop: function( type, clearQueue, gotoEnd ) {
7307		var stopQueue = function( hooks ) {
7308			var stop = hooks.stop;
7309			delete hooks.stop;
7310			stop( gotoEnd );
7311		};
7312
7313		if ( typeof type !== "string" ) {
7314			gotoEnd = clearQueue;
7315			clearQueue = type;
7316			type = undefined;
7317		}
7318		if ( clearQueue && type !== false ) {
7319			this.queue( type || "fx", [] );
7320		}
7321
7322		return this.each( function() {
7323			var dequeue = true,
7324				index = type != null && type + "queueHooks",
7325				timers = jQuery.timers,
7326				data = dataPriv.get( this );
7327
7328			if ( index ) {
7329				if ( data[ index ] && data[ index ].stop ) {
7330					stopQueue( data[ index ] );
7331				}
7332			} else {
7333				for ( index in data ) {
7334					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7335						stopQueue( data[ index ] );
7336					}
7337				}
7338			}
7339
7340			for ( index = timers.length; index--; ) {
7341				if ( timers[ index ].elem === this &&
7342					( type == null || timers[ index ].queue === type ) ) {
7343
7344					timers[ index ].anim.stop( gotoEnd );
7345					dequeue = false;
7346					timers.splice( index, 1 );
7347				}
7348			}
7349
7350			// Start the next in the queue if the last step wasn't forced.
7351			// Timers currently will call their complete callbacks, which
7352			// will dequeue but only if they were gotoEnd.
7353			if ( dequeue || !gotoEnd ) {
7354				jQuery.dequeue( this, type );
7355			}
7356		} );
7357	},
7358	finish: function( type ) {
7359		if ( type !== false ) {
7360			type = type || "fx";
7361		}
7362		return this.each( function() {
7363			var index,
7364				data = dataPriv.get( this ),
7365				queue = data[ type + "queue" ],
7366				hooks = data[ type + "queueHooks" ],
7367				timers = jQuery.timers,
7368				length = queue ? queue.length : 0;
7369
7370			// Enable finishing flag on private data
7371			data.finish = true;
7372
7373			// Empty the queue first
7374			jQuery.queue( this, type, [] );
7375
7376			if ( hooks && hooks.stop ) {
7377				hooks.stop.call( this, true );
7378			}
7379
7380			// Look for any active animations, and finish them
7381			for ( index = timers.length; index--; ) {
7382				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7383					timers[ index ].anim.stop( true );
7384					timers.splice( index, 1 );
7385				}
7386			}
7387
7388			// Look for any animations in the old queue and finish them
7389			for ( index = 0; index < length; index++ ) {
7390				if ( queue[ index ] && queue[ index ].finish ) {
7391					queue[ index ].finish.call( this );
7392				}
7393			}
7394
7395			// Turn off finishing flag
7396			delete data.finish;
7397		} );
7398	}
7399} );
7400
7401jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
7402	var cssFn = jQuery.fn[ name ];
7403	jQuery.fn[ name ] = function( speed, easing, callback ) {
7404		return speed == null || typeof speed === "boolean" ?
7405			cssFn.apply( this, arguments ) :
7406			this.animate( genFx( name, true ), speed, easing, callback );
7407	};
7408} );
7409
7410// Generate shortcuts for custom animations
7411jQuery.each( {
7412	slideDown: genFx( "show" ),
7413	slideUp: genFx( "hide" ),
7414	slideToggle: genFx( "toggle" ),
7415	fadeIn: { opacity: "show" },
7416	fadeOut: { opacity: "hide" },
7417	fadeToggle: { opacity: "toggle" }
7418}, function( name, props ) {
7419	jQuery.fn[ name ] = function( speed, easing, callback ) {
7420		return this.animate( props, speed, easing, callback );
7421	};
7422} );
7423
7424jQuery.timers = [];
7425jQuery.fx.tick = function() {
7426	var timer,
7427		i = 0,
7428		timers = jQuery.timers;
7429
7430	fxNow = Date.now();
7431
7432	for ( ; i < timers.length; i++ ) {
7433		timer = timers[ i ];
7434
7435		// Run the timer and safely remove it when done (allowing for external removal)
7436		if ( !timer() && timers[ i ] === timer ) {
7437			timers.splice( i--, 1 );
7438		}
7439	}
7440
7441	if ( !timers.length ) {
7442		jQuery.fx.stop();
7443	}
7444	fxNow = undefined;
7445};
7446
7447jQuery.fx.timer = function( timer ) {
7448	jQuery.timers.push( timer );
7449	jQuery.fx.start();
7450};
7451
7452jQuery.fx.interval = 13;
7453jQuery.fx.start = function() {
7454	if ( inProgress ) {
7455		return;
7456	}
7457
7458	inProgress = true;
7459	schedule();
7460};
7461
7462jQuery.fx.stop = function() {
7463	inProgress = null;
7464};
7465
7466jQuery.fx.speeds = {
7467	slow: 600,
7468	fast: 200,
7469
7470	// Default speed
7471	_default: 400
7472};
7473
7474
7475// Based off of the plugin by Clint Helfers, with permission.
7476// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
7477jQuery.fn.delay = function( time, type ) {
7478	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7479	type = type || "fx";
7480
7481	return this.queue( type, function( next, hooks ) {
7482		var timeout = window.setTimeout( next, time );
7483		hooks.stop = function() {
7484			window.clearTimeout( timeout );
7485		};
7486	} );
7487};
7488
7489
7490( function() {
7491	var input = document.createElement( "input" ),
7492		select = document.createElement( "select" ),
7493		opt = select.appendChild( document.createElement( "option" ) );
7494
7495	input.type = "checkbox";
7496
7497	// Support: Android <=4.3 only
7498	// Default value for a checkbox should be "on"
7499	support.checkOn = input.value !== "";
7500
7501	// Support: IE <=11 only
7502	// Must access selectedIndex to make default options select
7503	support.optSelected = opt.selected;
7504
7505	// Support: IE <=11 only
7506	// An input loses its value after becoming a radio
7507	input = document.createElement( "input" );
7508	input.value = "t";
7509	input.type = "radio";
7510	support.radioValue = input.value === "t";
7511} )();
7512
7513
7514var boolHook,
7515	attrHandle = jQuery.expr.attrHandle;
7516
7517jQuery.fn.extend( {
7518	attr: function( name, value ) {
7519		return access( this, jQuery.attr, name, value, arguments.length > 1 );
7520	},
7521
7522	removeAttr: function( name ) {
7523		return this.each( function() {
7524			jQuery.removeAttr( this, name );
7525		} );
7526	}
7527} );
7528
7529jQuery.extend( {
7530	attr: function( elem, name, value ) {
7531		var ret, hooks,
7532			nType = elem.nodeType;
7533
7534		// Don't get/set attributes on text, comment and attribute nodes
7535		if ( nType === 3 || nType === 8 || nType === 2 ) {
7536			return;
7537		}
7538
7539		// Fallback to prop when attributes are not supported
7540		if ( typeof elem.getAttribute === "undefined" ) {
7541			return jQuery.prop( elem, name, value );
7542		}
7543
7544		// Attribute hooks are determined by the lowercase version
7545		// Grab necessary hook if one is defined
7546		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7547			hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
7548				( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
7549		}
7550
7551		if ( value !== undefined ) {
7552			if ( value === null ) {
7553				jQuery.removeAttr( elem, name );
7554				return;
7555			}
7556
7557			if ( hooks && "set" in hooks &&
7558				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7559				return ret;
7560			}
7561
7562			elem.setAttribute( name, value + "" );
7563			return value;
7564		}
7565
7566		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7567			return ret;
7568		}
7569
7570		ret = jQuery.find.attr( elem, name );
7571
7572		// Non-existent attributes return null, we normalize to undefined
7573		return ret == null ? undefined : ret;
7574	},
7575
7576	attrHooks: {
7577		type: {
7578			set: function( elem, value ) {
7579				if ( !support.radioValue && value === "radio" &&
7580					nodeName( elem, "input" ) ) {
7581					var val = elem.value;
7582					elem.setAttribute( "type", value );
7583					if ( val ) {
7584						elem.value = val;
7585					}
7586					return value;
7587				}
7588			}
7589		}
7590	},
7591
7592	removeAttr: function( elem, value ) {
7593		var name,
7594			i = 0,
7595
7596			// Attribute names can contain non-HTML whitespace characters
7597			// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
7598			attrNames = value && value.match( rnothtmlwhite );
7599
7600		if ( attrNames && elem.nodeType === 1 ) {
7601			while ( ( name = attrNames[ i++ ] ) ) {
7602				elem.removeAttribute( name );
7603			}
7604		}
7605	}
7606} );
7607
7608// Hooks for boolean attributes
7609boolHook = {
7610	set: function( elem, value, name ) {
7611		if ( value === false ) {
7612
7613			// Remove boolean attributes when set to false
7614			jQuery.removeAttr( elem, name );
7615		} else {
7616			elem.setAttribute( name, name );
7617		}
7618		return name;
7619	}
7620};
7621
7622jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
7623	var getter = attrHandle[ name ] || jQuery.find.attr;
7624
7625	attrHandle[ name ] = function( elem, name, isXML ) {
7626		var ret, handle,
7627			lowercaseName = name.toLowerCase();
7628
7629		if ( !isXML ) {
7630
7631			// Avoid an infinite loop by temporarily removing this function from the getter
7632			handle = attrHandle[ lowercaseName ];
7633			attrHandle[ lowercaseName ] = ret;
7634			ret = getter( elem, name, isXML ) != null ?
7635				lowercaseName :
7636				null;
7637			attrHandle[ lowercaseName ] = handle;
7638		}
7639		return ret;
7640	};
7641} );
7642
7643
7644
7645
7646var rfocusable = /^(?:input|select|textarea|button)$/i,
7647	rclickable = /^(?:a|area)$/i;
7648
7649jQuery.fn.extend( {
7650	prop: function( name, value ) {
7651		return access( this, jQuery.prop, name, value, arguments.length > 1 );
7652	},
7653
7654	removeProp: function( name ) {
7655		return this.each( function() {
7656			delete this[ jQuery.propFix[ name ] || name ];
7657		} );
7658	}
7659} );
7660
7661jQuery.extend( {
7662	prop: function( elem, name, value ) {
7663		var ret, hooks,
7664			nType = elem.nodeType;
7665
7666		// Don't get/set properties on text, comment and attribute nodes
7667		if ( nType === 3 || nType === 8 || nType === 2 ) {
7668			return;
7669		}
7670
7671		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7672
7673			// Fix name and attach hooks
7674			name = jQuery.propFix[ name ] || name;
7675			hooks = jQuery.propHooks[ name ];
7676		}
7677
7678		if ( value !== undefined ) {
7679			if ( hooks && "set" in hooks &&
7680				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
7681				return ret;
7682			}
7683
7684			return ( elem[ name ] = value );
7685		}
7686
7687		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
7688			return ret;
7689		}
7690
7691		return elem[ name ];
7692	},
7693
7694	propHooks: {
7695		tabIndex: {
7696			get: function( elem ) {
7697
7698				// Support: IE <=9 - 11 only
7699				// elem.tabIndex doesn't always return the
7700				// correct value when it hasn't been explicitly set
7701				// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
7702				// Use proper attribute retrieval(#12072)
7703				var tabindex = jQuery.find.attr( elem, "tabindex" );
7704
7705				if ( tabindex ) {
7706					return parseInt( tabindex, 10 );
7707				}
7708
7709				if (
7710					rfocusable.test( elem.nodeName ) ||
7711					rclickable.test( elem.nodeName ) &&
7712					elem.href
7713				) {
7714					return 0;
7715				}
7716
7717				return -1;
7718			}
7719		}
7720	},
7721
7722	propFix: {
7723		"for": "htmlFor",
7724		"class": "className"
7725	}
7726} );
7727
7728// Support: IE <=11 only
7729// Accessing the selectedIndex property
7730// forces the browser to respect setting selected
7731// on the option
7732// The getter ensures a default option is selected
7733// when in an optgroup
7734// eslint rule "no-unused-expressions" is disabled for this code
7735// since it considers such accessions noop
7736if ( !support.optSelected ) {
7737	jQuery.propHooks.selected = {
7738		get: function( elem ) {
7739
7740			/* eslint no-unused-expressions: "off" */
7741
7742			var parent = elem.parentNode;
7743			if ( parent && parent.parentNode ) {
7744				parent.parentNode.selectedIndex;
7745			}
7746			return null;
7747		},
7748		set: function( elem ) {
7749
7750			/* eslint no-unused-expressions: "off" */
7751
7752			var parent = elem.parentNode;
7753			if ( parent ) {
7754				parent.selectedIndex;
7755
7756				if ( parent.parentNode ) {
7757					parent.parentNode.selectedIndex;
7758				}
7759			}
7760		}
7761	};
7762}
7763
7764jQuery.each( [
7765	"tabIndex",
7766	"readOnly",
7767	"maxLength",
7768	"cellSpacing",
7769	"cellPadding",
7770	"rowSpan",
7771	"colSpan",
7772	"useMap",
7773	"frameBorder",
7774	"contentEditable"
7775], function() {
7776	jQuery.propFix[ this.toLowerCase() ] = this;
7777} );
7778
7779
7780
7781
7782	// Strip and collapse whitespace according to HTML spec
7783	// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
7784	function stripAndCollapse( value ) {
7785		var tokens = value.match( rnothtmlwhite ) || [];
7786		return tokens.join( " " );
7787	}
7788
7789
7790function getClass( elem ) {
7791	return elem.getAttribute && elem.getAttribute( "class" ) || "";
7792}
7793
7794function classesToArray( value ) {
7795	if ( Array.isArray( value ) ) {
7796		return value;
7797	}
7798	if ( typeof value === "string" ) {
7799		return value.match( rnothtmlwhite ) || [];
7800	}
7801	return [];
7802}
7803
7804jQuery.fn.extend( {
7805	addClass: function( value ) {
7806		var classes, elem, cur, curValue, clazz, j, finalValue,
7807			i = 0;
7808
7809		if ( isFunction( value ) ) {
7810			return this.each( function( j ) {
7811				jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
7812			} );
7813		}
7814
7815		classes = classesToArray( value );
7816
7817		if ( classes.length ) {
7818			while ( ( elem = this[ i++ ] ) ) {
7819				curValue = getClass( elem );
7820				cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
7821
7822				if ( cur ) {
7823					j = 0;
7824					while ( ( clazz = classes[ j++ ] ) ) {
7825						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
7826							cur += clazz + " ";
7827						}
7828					}
7829
7830					// Only assign if different to avoid unneeded rendering.
7831					finalValue = stripAndCollapse( cur );
7832					if ( curValue !== finalValue ) {
7833						elem.setAttribute( "class", finalValue );
7834					}
7835				}
7836			}
7837		}
7838
7839		return this;
7840	},
7841
7842	removeClass: function( value ) {
7843		var classes, elem, cur, curValue, clazz, j, finalValue,
7844			i = 0;
7845
7846		if ( isFunction( value ) ) {
7847			return this.each( function( j ) {
7848				jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
7849			} );
7850		}
7851
7852		if ( !arguments.length ) {
7853			return this.attr( "class", "" );
7854		}
7855
7856		classes = classesToArray( value );
7857
7858		if ( classes.length ) {
7859			while ( ( elem = this[ i++ ] ) ) {
7860				curValue = getClass( elem );
7861
7862				// This expression is here for better compressibility (see addClass)
7863				cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
7864
7865				if ( cur ) {
7866					j = 0;
7867					while ( ( clazz = classes[ j++ ] ) ) {
7868
7869						// Remove *all* instances
7870						while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
7871							cur = cur.replace( " " + clazz + " ", " " );
7872						}
7873					}
7874
7875					// Only assign if different to avoid unneeded rendering.
7876					finalValue = stripAndCollapse( cur );
7877					if ( curValue !== finalValue ) {
7878						elem.setAttribute( "class", finalValue );
7879					}
7880				}
7881			}
7882		}
7883
7884		return this;
7885	},
7886
7887	toggleClass: function( value, stateVal ) {
7888		var type = typeof value,
7889			isValidValue = type === "string" || Array.isArray( value );
7890
7891		if ( typeof stateVal === "boolean" && isValidValue ) {
7892			return stateVal ? this.addClass( value ) : this.removeClass( value );
7893		}
7894
7895		if ( isFunction( value ) ) {
7896			return this.each( function( i ) {
7897				jQuery( this ).toggleClass(
7898					value.call( this, i, getClass( this ), stateVal ),
7899					stateVal
7900				);
7901			} );
7902		}
7903
7904		return this.each( function() {
7905			var className, i, self, classNames;
7906
7907			if ( isValidValue ) {
7908
7909				// Toggle individual class names
7910				i = 0;
7911				self = jQuery( this );
7912				classNames = classesToArray( value );
7913
7914				while ( ( className = classNames[ i++ ] ) ) {
7915
7916					// Check each className given, space separated list
7917					if ( self.hasClass( className ) ) {
7918						self.removeClass( className );
7919					} else {
7920						self.addClass( className );
7921					}
7922				}
7923
7924			// Toggle whole class name
7925			} else if ( value === undefined || type === "boolean" ) {
7926				className = getClass( this );
7927				if ( className ) {
7928
7929					// Store className if set
7930					dataPriv.set( this, "__className__", className );
7931				}
7932
7933				// If the element has a class name or if we're passed `false`,
7934				// then remove the whole classname (if there was one, the above saved it).
7935				// Otherwise bring back whatever was previously saved (if anything),
7936				// falling back to the empty string if nothing was stored.
7937				if ( this.setAttribute ) {
7938					this.setAttribute( "class",
7939						className || value === false ?
7940						"" :
7941						dataPriv.get( this, "__className__" ) || ""
7942					);
7943				}
7944			}
7945		} );
7946	},
7947
7948	hasClass: function( selector ) {
7949		var className, elem,
7950			i = 0;
7951
7952		className = " " + selector + " ";
7953		while ( ( elem = this[ i++ ] ) ) {
7954			if ( elem.nodeType === 1 &&
7955				( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
7956					return true;
7957			}
7958		}
7959
7960		return false;
vendor: 5,544 bytes, lines 7961-8196
7961	}
7962} );
7963
7964
7965
7966
7967var rreturn = /\r/g;
7968
7969jQuery.fn.extend( {
7970	val: function( value ) {
7971		var hooks, ret, valueIsFunction,
7972			elem = this[ 0 ];
7973
7974		if ( !arguments.length ) {
7975			if ( elem ) {
7976				hooks = jQuery.valHooks[ elem.type ] ||
7977					jQuery.valHooks[ elem.nodeName.toLowerCase() ];
7978
7979				if ( hooks &&
7980					"get" in hooks &&
7981					( ret = hooks.get( elem, "value" ) ) !== undefined
7982				) {
7983					return ret;
7984				}
7985
7986				ret = elem.value;
7987
7988				// Handle most common string cases
7989				if ( typeof ret === "string" ) {
7990					return ret.replace( rreturn, "" );
7991				}
7992
7993				// Handle cases where value is null/undef or number
7994				return ret == null ? "" : ret;
7995			}
7996
7997			return;
7998		}
7999
8000		valueIsFunction = isFunction( value );
8001
8002		return this.each( function( i ) {
8003			var val;
8004
8005			if ( this.nodeType !== 1 ) {
8006				return;
8007			}
8008
8009			if ( valueIsFunction ) {
8010				val = value.call( this, i, jQuery( this ).val() );
8011			} else {
8012				val = value;
8013			}
8014
8015			// Treat null/undefined as ""; convert numbers to string
8016			if ( val == null ) {
8017				val = "";
8018
8019			} else if ( typeof val === "number" ) {
8020				val += "";
8021
8022			} else if ( Array.isArray( val ) ) {
8023				val = jQuery.map( val, function( value ) {
8024					return value == null ? "" : value + "";
8025				} );
8026			}
8027
8028			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
8029
8030			// If set returns undefined, fall back to normal setting
8031			if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
8032				this.value = val;
8033			}
8034		} );
8035	}
8036} );
8037
8038jQuery.extend( {
8039	valHooks: {
8040		option: {
8041			get: function( elem ) {
8042
8043				var val = jQuery.find.attr( elem, "value" );
8044				return val != null ?
8045					val :
8046
8047					// Support: IE <=10 - 11 only
8048					// option.text throws exceptions (#14686, #14858)
8049					// Strip and collapse whitespace
8050					// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
8051					stripAndCollapse( jQuery.text( elem ) );
8052			}
8053		},
8054		select: {
8055			get: function( elem ) {
8056				var value, option, i,
8057					options = elem.options,
8058					index = elem.selectedIndex,
8059					one = elem.type === "select-one",
8060					values = one ? null : [],
8061					max = one ? index + 1 : options.length;
8062
8063				if ( index < 0 ) {
8064					i = max;
8065
8066				} else {
8067					i = one ? index : 0;
8068				}
8069
8070				// Loop through all the selected options
8071				for ( ; i < max; i++ ) {
8072					option = options[ i ];
8073
8074					// Support: IE <=9 only
8075					// IE8-9 doesn't update selected after form reset (#2551)
8076					if ( ( option.selected || i === index ) &&
8077
8078							// Don't return options that are disabled or in a disabled optgroup
8079							!option.disabled &&
8080							( !option.parentNode.disabled ||
8081								!nodeName( option.parentNode, "optgroup" ) ) ) {
8082
8083						// Get the specific value for the option
8084						value = jQuery( option ).val();
8085
8086						// We don't need an array for one selects
8087						if ( one ) {
8088							return value;
8089						}
8090
8091						// Multi-Selects return an array
8092						values.push( value );
8093					}
8094				}
8095
8096				return values;
8097			},
8098
8099			set: function( elem, value ) {
8100				var optionSet, option,
8101					options = elem.options,
8102					values = jQuery.makeArray( value ),
8103					i = options.length;
8104
8105				while ( i-- ) {
8106					option = options[ i ];
8107
8108					/* eslint-disable no-cond-assign */
8109
8110					if ( option.selected =
8111						jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
8112					) {
8113						optionSet = true;
8114					}
8115
8116					/* eslint-enable no-cond-assign */
8117				}
8118
8119				// Force browsers to behave consistently when non-matching value is set
8120				if ( !optionSet ) {
8121					elem.selectedIndex = -1;
8122				}
8123				return values;
8124			}
8125		}
8126	}
8127} );
8128
8129// Radios and checkboxes getter/setter
8130jQuery.each( [ "radio", "checkbox" ], function() {
8131	jQuery.valHooks[ this ] = {
8132		set: function( elem, value ) {
8133			if ( Array.isArray( value ) ) {
8134				return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
8135			}
8136		}
8137	};
8138	if ( !support.checkOn ) {
8139		jQuery.valHooks[ this ].get = function( elem ) {
8140			return elem.getAttribute( "value" ) === null ? "on" : elem.value;
8141		};
8142	}
8143} );
8144
8145
8146
8147
8148// Return jQuery for attributes-only inclusion
8149
8150
8151support.focusin = "onfocusin" in window;
8152
8153
8154var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
8155	stopPropagationCallback = function( e ) {
8156		e.stopPropagation();
8157	};
8158
8159jQuery.extend( jQuery.event, {
8160
8161	trigger: function( event, data, elem, onlyHandlers ) {
8162
8163		var i, cur, tmp, bubbleType, ontype, handle, special, lastElement,
8164			eventPath = [ elem || document ],
8165			type = hasOwn.call( event, "type" ) ? event.type : event,
8166			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
8167
8168		cur = lastElement = tmp = elem = elem || document;
8169
8170		// Don't do events on text and comment nodes
8171		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
8172			return;
8173		}
8174
8175		// focus/blur morphs to focusin/out; ensure we're not firing them right now
8176		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
8177			return;
8178		}
8179
8180		if ( type.indexOf( "." ) > -1 ) {
8181
8182			// Namespaced trigger; create a regexp to match event type in handle()
8183			namespaces = type.split( "." );
8184			type = namespaces.shift();
8185			namespaces.sort();
8186		}
8187		ontype = type.indexOf( ":" ) < 0 && "on" + type;
8188
8189		// Caller can pass in a jQuery.Event object, Object, or just an event type string
8190		event = event[ jQuery.expando ] ?
8191			event :
8192			new jQuery.Event( type, typeof event === "object" && event );
8193
8194		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
8195		event.isTrigger = onlyHandlers ? 2 : 3;
8196		event.namespace = namespaces.join( "." );
vendor: 32,532 bytes, lines 8197-9468
8197		event.rnamespace = event.namespace ?
8198			new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
8199			null;
8200
8201		// Clean up the event in case it is being reused
8202		event.result = undefined;
8203		if ( !event.target ) {
8204			event.target = elem;
8205		}
8206
8207		// Clone any incoming data and prepend the event, creating the handler arg list
8208		data = data == null ?
8209			[ event ] :
8210			jQuery.makeArray( data, [ event ] );
8211
8212		// Allow special events to draw outside the lines
8213		special = jQuery.event.special[ type ] || {};
8214		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
8215			return;
8216		}
8217
8218		// Determine event propagation path in advance, per W3C events spec (#9951)
8219		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
8220		if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {
8221
8222			bubbleType = special.delegateType || type;
8223			if ( !rfocusMorph.test( bubbleType + type ) ) {
8224				cur = cur.parentNode;
8225			}
8226			for ( ; cur; cur = cur.parentNode ) {
8227				eventPath.push( cur );
8228				tmp = cur;
8229			}
8230
8231			// Only add window if we got to document (e.g., not plain obj or detached DOM)
8232			if ( tmp === ( elem.ownerDocument || document ) ) {
8233				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
8234			}
8235		}
8236
8237		// Fire handlers on the event path
8238		i = 0;
8239		while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
8240			lastElement = cur;
8241			event.type = i > 1 ?
8242				bubbleType :
8243				special.bindType || type;
8244
8245			// jQuery handler
8246			handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
8247				dataPriv.get( cur, "handle" );
8248			if ( handle ) {
8249				handle.apply( cur, data );
8250			}
8251
8252			// Native handler
8253			handle = ontype && cur[ ontype ];
8254			if ( handle && handle.apply && acceptData( cur ) ) {
8255				event.result = handle.apply( cur, data );
8256				if ( event.result === false ) {
8257					event.preventDefault();
8258				}
8259			}
8260		}
8261		event.type = type;
8262
8263		// If nobody prevented the default action, do it now
8264		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
8265
8266			if ( ( !special._default ||
8267				special._default.apply( eventPath.pop(), data ) === false ) &&
8268				acceptData( elem ) ) {
8269
8270				// Call a native DOM method on the target with the same name as the event.
8271				// Don't do default actions on window, that's where global variables be (#6170)
8272				if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {
8273
8274					// Don't re-trigger an onFOO event when we call its FOO() method
8275					tmp = elem[ ontype ];
8276
8277					if ( tmp ) {
8278						elem[ ontype ] = null;
8279					}
8280
8281					// Prevent re-triggering of the same event, since we already bubbled it above
8282					jQuery.event.triggered = type;
8283
8284					if ( event.isPropagationStopped() ) {
8285						lastElement.addEventListener( type, stopPropagationCallback );
8286					}
8287
8288					elem[ type ]();
8289
8290					if ( event.isPropagationStopped() ) {
8291						lastElement.removeEventListener( type, stopPropagationCallback );
8292					}
8293
8294					jQuery.event.triggered = undefined;
8295
8296					if ( tmp ) {
8297						elem[ ontype ] = tmp;
8298					}
8299				}
8300			}
8301		}
8302
8303		return event.result;
8304	},
8305
8306	// Piggyback on a donor event to simulate a different one
8307	// Used only for `focus(in | out)` events
8308	simulate: function( type, elem, event ) {
8309		var e = jQuery.extend(
8310			new jQuery.Event(),
8311			event,
8312			{
8313				type: type,
8314				isSimulated: true
8315			}
8316		);
8317
8318		jQuery.event.trigger( e, null, elem );
8319	}
8320
8321} );
8322
8323jQuery.fn.extend( {
8324
8325	trigger: function( type, data ) {
8326		return this.each( function() {
8327			jQuery.event.trigger( type, data, this );
8328		} );
8329	},
8330	triggerHandler: function( type, data ) {
8331		var elem = this[ 0 ];
8332		if ( elem ) {
8333			return jQuery.event.trigger( type, data, elem, true );
8334		}
8335	}
8336} );
8337
8338
8339// Support: Firefox <=44
8340// Firefox doesn't have focus(in | out) events
8341// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
8342//
8343// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
8344// focus(in | out) events fire after focus & blur events,
8345// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
8346// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
8347if ( !support.focusin ) {
8348	jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
8349
8350		// Attach a single capturing handler on the document while someone wants focusin/focusout
8351		var handler = function( event ) {
8352			jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
8353		};
8354
8355		jQuery.event.special[ fix ] = {
8356			setup: function() {
8357				var doc = this.ownerDocument || this,
8358					attaches = dataPriv.access( doc, fix );
8359
8360				if ( !attaches ) {
8361					doc.addEventListener( orig, handler, true );
8362				}
8363				dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
8364			},
8365			teardown: function() {
8366				var doc = this.ownerDocument || this,
8367					attaches = dataPriv.access( doc, fix ) - 1;
8368
8369				if ( !attaches ) {
8370					doc.removeEventListener( orig, handler, true );
8371					dataPriv.remove( doc, fix );
8372
8373				} else {
8374					dataPriv.access( doc, fix, attaches );
8375				}
8376			}
8377		};
8378	} );
8379}
8380var location = window.location;
8381
8382var nonce = Date.now();
8383
8384var rquery = ( /\?/ );
8385
8386
8387
8388// Cross-browser xml parsing
8389jQuery.parseXML = function( data ) {
8390	var xml;
8391	if ( !data || typeof data !== "string" ) {
8392		return null;
8393	}
8394
8395	// Support: IE 9 - 11 only
8396	// IE throws on parseFromString with invalid input.
8397	try {
8398		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
8399	} catch ( e ) {
8400		xml = undefined;
8401	}
8402
8403	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
8404		jQuery.error( "Invalid XML: " + data );
8405	}
8406	return xml;
8407};
8408
8409
8410var
8411	rbracket = /\[\]$/,
8412	rCRLF = /\r?\n/g,
8413	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
8414	rsubmittable = /^(?:input|select|textarea|keygen)/i;
8415
8416function buildParams( prefix, obj, traditional, add ) {
8417	var name;
8418
8419	if ( Array.isArray( obj ) ) {
8420
8421		// Serialize array item.
8422		jQuery.each( obj, function( i, v ) {
8423			if ( traditional || rbracket.test( prefix ) ) {
8424
8425				// Treat each array item as a scalar.
8426				add( prefix, v );
8427
8428			} else {
8429
8430				// Item is non-scalar (array or object), encode its numeric index.
8431				buildParams(
8432					prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
8433					v,
8434					traditional,
8435					add
8436				);
8437			}
8438		} );
8439
8440	} else if ( !traditional && toType( obj ) === "object" ) {
8441
8442		// Serialize object item.
8443		for ( name in obj ) {
8444			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8445		}
8446
8447	} else {
8448
8449		// Serialize scalar item.
8450		add( prefix, obj );
8451	}
8452}
8453
8454// Serialize an array of form elements or a set of
8455// key/values into a query string
8456jQuery.param = function( a, traditional ) {
8457	var prefix,
8458		s = [],
8459		add = function( key, valueOrFunction ) {
8460
8461			// If value is a function, invoke it and use its return value
8462			var value = isFunction( valueOrFunction ) ?
8463				valueOrFunction() :
8464				valueOrFunction;
8465
8466			s[ s.length ] = encodeURIComponent( key ) + "=" +
8467				encodeURIComponent( value == null ? "" : value );
8468		};
8469
8470	// If an array was passed in, assume that it is an array of form elements.
8471	if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8472
8473		// Serialize the form elements
8474		jQuery.each( a, function() {
8475			add( this.name, this.value );
8476		} );
8477
8478	} else {
8479
8480		// If traditional, encode the "old" way (the way 1.3.2 or older
8481		// did it), otherwise encode params recursively.
8482		for ( prefix in a ) {
8483			buildParams( prefix, a[ prefix ], traditional, add );
8484		}
8485	}
8486
8487	// Return the resulting serialization
8488	return s.join( "&" );
8489};
8490
8491jQuery.fn.extend( {
8492	serialize: function() {
8493		return jQuery.param( this.serializeArray() );
8494	},
8495	serializeArray: function() {
8496		return this.map( function() {
8497
8498			// Can add propHook for "elements" to filter or add form elements
8499			var elements = jQuery.prop( this, "elements" );
8500			return elements ? jQuery.makeArray( elements ) : this;
8501		} )
8502		.filter( function() {
8503			var type = this.type;
8504
8505			// Use .is( ":disabled" ) so that fieldset[disabled] works
8506			return this.name && !jQuery( this ).is( ":disabled" ) &&
8507				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
8508				( this.checked || !rcheckableType.test( type ) );
8509		} )
8510		.map( function( i, elem ) {
8511			var val = jQuery( this ).val();
8512
8513			if ( val == null ) {
8514				return null;
8515			}
8516
8517			if ( Array.isArray( val ) ) {
8518				return jQuery.map( val, function( val ) {
8519					return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8520				} );
8521			}
8522
8523			return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
8524		} ).get();
8525	}
8526} );
8527
8528
8529var
8530	r20 = /%20/g,
8531	rhash = /#.*$/,
8532	rantiCache = /([?&])_=[^&]*/,
8533	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
8534
8535	// #7653, #8125, #8152: local protocol detection
8536	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8537	rnoContent = /^(?:GET|HEAD)$/,
8538	rprotocol = /^\/\//,
8539
8540	/* Prefilters
8541	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8542	 * 2) These are called:
8543	 *    - BEFORE asking for a transport
8544	 *    - AFTER param serialization (s.data is a string if s.processData is true)
8545	 * 3) key is the dataType
8546	 * 4) the catchall symbol "*" can be used
8547	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8548	 */
8549	prefilters = {},
8550
8551	/* Transports bindings
8552	 * 1) key is the dataType
8553	 * 2) the catchall symbol "*" can be used
8554	 * 3) selection will start with transport dataType and THEN go to "*" if needed
8555	 */
8556	transports = {},
8557
8558	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
8559	allTypes = "*/".concat( "*" ),
8560
8561	// Anchor tag for parsing the document origin
8562	originAnchor = document.createElement( "a" );
8563	originAnchor.href = location.href;
8564
8565// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8566function addToPrefiltersOrTransports( structure ) {
8567
8568	// dataTypeExpression is optional and defaults to "*"
8569	return function( dataTypeExpression, func ) {
8570
8571		if ( typeof dataTypeExpression !== "string" ) {
8572			func = dataTypeExpression;
8573			dataTypeExpression = "*";
8574		}
8575
8576		var dataType,
8577			i = 0,
8578			dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
8579
8580		if ( isFunction( func ) ) {
8581
8582			// For each dataType in the dataTypeExpression
8583			while ( ( dataType = dataTypes[ i++ ] ) ) {
8584
8585				// Prepend if requested
8586				if ( dataType[ 0 ] === "+" ) {
8587					dataType = dataType.slice( 1 ) || "*";
8588					( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
8589
8590				// Otherwise append
8591				} else {
8592					( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
8593				}
8594			}
8595		}
8596	};
8597}
8598
8599// Base inspection function for prefilters and transports
8600function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8601
8602	var inspected = {},
8603		seekingTransport = ( structure === transports );
8604
8605	function inspect( dataType ) {
8606		var selected;
8607		inspected[ dataType ] = true;
8608		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8609			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8610			if ( typeof dataTypeOrTransport === "string" &&
8611				!seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8612
8613				options.dataTypes.unshift( dataTypeOrTransport );
8614				inspect( dataTypeOrTransport );
8615				return false;
8616			} else if ( seekingTransport ) {
8617				return !( selected = dataTypeOrTransport );
8618			}
8619		} );
8620		return selected;
8621	}
8622
8623	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8624}
8625
8626// A special extend for ajax options
8627// that takes "flat" options (not to be deep extended)
8628// Fixes #9887
8629function ajaxExtend( target, src ) {
8630	var key, deep,
8631		flatOptions = jQuery.ajaxSettings.flatOptions || {};
8632
8633	for ( key in src ) {
8634		if ( src[ key ] !== undefined ) {
8635			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
8636		}
8637	}
8638	if ( deep ) {
8639		jQuery.extend( true, target, deep );
8640	}
8641
8642	return target;
8643}
8644
8645/* Handles responses to an ajax request:
8646 * - finds the right dataType (mediates between content-type and expected dataType)
8647 * - returns the corresponding response
8648 */
8649function ajaxHandleResponses( s, jqXHR, responses ) {
8650
8651	var ct, type, finalDataType, firstDataType,
8652		contents = s.contents,
8653		dataTypes = s.dataTypes;
8654
8655	// Remove auto dataType and get content-type in the process
8656	while ( dataTypes[ 0 ] === "*" ) {
8657		dataTypes.shift();
8658		if ( ct === undefined ) {
8659			ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
8660		}
8661	}
8662
8663	// Check if we're dealing with a known content-type
8664	if ( ct ) {
8665		for ( type in contents ) {
8666			if ( contents[ type ] && contents[ type ].test( ct ) ) {
8667				dataTypes.unshift( type );
8668				break;
8669			}
8670		}
8671	}
8672
8673	// Check to see if we have a response for the expected dataType
8674	if ( dataTypes[ 0 ] in responses ) {
8675		finalDataType = dataTypes[ 0 ];
8676	} else {
8677
8678		// Try convertible dataTypes
8679		for ( type in responses ) {
8680			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
8681				finalDataType = type;
8682				break;
8683			}
8684			if ( !firstDataType ) {
8685				firstDataType = type;
8686			}
8687		}
8688
8689		// Or just use first one
8690		finalDataType = finalDataType || firstDataType;
8691	}
8692
8693	// If we found a dataType
8694	// We add the dataType to the list if needed
8695	// and return the corresponding response
8696	if ( finalDataType ) {
8697		if ( finalDataType !== dataTypes[ 0 ] ) {
8698			dataTypes.unshift( finalDataType );
8699		}
8700		return responses[ finalDataType ];
8701	}
8702}
8703
8704/* Chain conversions given the request and the original response
8705 * Also sets the responseXXX fields on the jqXHR instance
8706 */
8707function ajaxConvert( s, response, jqXHR, isSuccess ) {
8708	var conv2, current, conv, tmp, prev,
8709		converters = {},
8710
8711		// Work with a copy of dataTypes in case we need to modify it for conversion
8712		dataTypes = s.dataTypes.slice();
8713
8714	// Create converters map with lowercased keys
8715	if ( dataTypes[ 1 ] ) {
8716		for ( conv in s.converters ) {
8717			converters[ conv.toLowerCase() ] = s.converters[ conv ];
8718		}
8719	}
8720
8721	current = dataTypes.shift();
8722
8723	// Convert to each sequential dataType
8724	while ( current ) {
8725
8726		if ( s.responseFields[ current ] ) {
8727			jqXHR[ s.responseFields[ current ] ] = response;
8728		}
8729
8730		// Apply the dataFilter if provided
8731		if ( !prev && isSuccess && s.dataFilter ) {
8732			response = s.dataFilter( response, s.dataType );
8733		}
8734
8735		prev = current;
8736		current = dataTypes.shift();
8737
8738		if ( current ) {
8739
8740			// There's only work to do if current dataType is non-auto
8741			if ( current === "*" ) {
8742
8743				current = prev;
8744
8745			// Convert response if prev dataType is non-auto and differs from current
8746			} else if ( prev !== "*" && prev !== current ) {
8747
8748				// Seek a direct converter
8749				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8750
8751				// If none found, seek a pair
8752				if ( !conv ) {
8753					for ( conv2 in converters ) {
8754
8755						// If conv2 outputs current
8756						tmp = conv2.split( " " );
8757						if ( tmp[ 1 ] === current ) {
8758
8759							// If prev can be converted to accepted input
8760							conv = converters[ prev + " " + tmp[ 0 ] ] ||
8761								converters[ "* " + tmp[ 0 ] ];
8762							if ( conv ) {
8763
8764								// Condense equivalence converters
8765								if ( conv === true ) {
8766									conv = converters[ conv2 ];
8767
8768								// Otherwise, insert the intermediate dataType
8769								} else if ( converters[ conv2 ] !== true ) {
8770									current = tmp[ 0 ];
8771									dataTypes.unshift( tmp[ 1 ] );
8772								}
8773								break;
8774							}
8775						}
8776					}
8777				}
8778
8779				// Apply converter (if not an equivalence)
8780				if ( conv !== true ) {
8781
8782					// Unless errors are allowed to bubble, catch and return them
8783					if ( conv && s.throws ) {
8784						response = conv( response );
8785					} else {
8786						try {
8787							response = conv( response );
8788						} catch ( e ) {
8789							return {
8790								state: "parsererror",
8791								error: conv ? e : "No conversion from " + prev + " to " + current
8792							};
8793						}
8794					}
8795				}
8796			}
8797		}
8798	}
8799
8800	return { state: "success", data: response };
8801}
8802
8803jQuery.extend( {
8804
8805	// Counter for holding the number of active queries
8806	active: 0,
8807
8808	// Last-Modified header cache for next request
8809	lastModified: {},
8810	etag: {},
8811
8812	ajaxSettings: {
8813		url: location.href,
8814		type: "GET",
8815		isLocal: rlocalProtocol.test( location.protocol ),
8816		global: true,
8817		processData: true,
8818		async: true,
8819		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
8820
8821		/*
8822		timeout: 0,
8823		data: null,
8824		dataType: null,
8825		username: null,
8826		password: null,
8827		cache: null,
8828		throws: false,
8829		traditional: false,
8830		headers: {},
8831		*/
8832
8833		accepts: {
8834			"*": allTypes,
8835			text: "text/plain",
8836			html: "text/html",
8837			xml: "application/xml, text/xml",
8838			json: "application/json, text/javascript"
8839		},
8840
8841		contents: {
8842			xml: /\bxml\b/,
8843			html: /\bhtml/,
8844			json: /\bjson\b/
8845		},
8846
8847		responseFields: {
8848			xml: "responseXML",
8849			text: "responseText",
8850			json: "responseJSON"
8851		},
8852
8853		// Data converters
8854		// Keys separate source (or catchall "*") and destination types with a single space
8855		converters: {
8856
8857			// Convert anything to text
8858			"* text": String,
8859
8860			// Text to html (true = no transformation)
8861			"text html": true,
8862
8863			// Evaluate text as a json expression
8864			"text json": JSON.parse,
8865
8866			// Parse text as xml
8867			"text xml": jQuery.parseXML
8868		},
8869
8870		// For options that shouldn't be deep extended:
8871		// you can add your own custom options here if
8872		// and when you create one that shouldn't be
8873		// deep extended (see ajaxExtend)
8874		flatOptions: {
8875			url: true,
8876			context: true
8877		}
8878	},
8879
8880	// Creates a full fledged settings object into target
8881	// with both ajaxSettings and settings fields.
8882	// If target is omitted, writes into ajaxSettings.
8883	ajaxSetup: function( target, settings ) {
8884		return settings ?
8885
8886			// Building a settings object
8887			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
8888
8889			// Extending ajaxSettings
8890			ajaxExtend( jQuery.ajaxSettings, target );
8891	},
8892
8893	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
8894	ajaxTransport: addToPrefiltersOrTransports( transports ),
8895
8896	// Main method
8897	ajax: function( url, options ) {
8898
8899		// If url is an object, simulate pre-1.5 signature
8900		if ( typeof url === "object" ) {
8901			options = url;
8902			url = undefined;
8903		}
8904
8905		// Force options to be an object
8906		options = options || {};
8907
8908		var transport,
8909
8910			// URL without anti-cache param
8911			cacheURL,
8912
8913			// Response headers
8914			responseHeadersString,
8915			responseHeaders,
8916
8917			// timeout handle
8918			timeoutTimer,
8919
8920			// Url cleanup var
8921			urlAnchor,
8922
8923			// Request state (becomes false upon send and true upon completion)
8924			completed,
8925
8926			// To know if global events are to be dispatched
8927			fireGlobals,
8928
8929			// Loop variable
8930			i,
8931
8932			// uncached part of the url
8933			uncached,
8934
8935			// Create the final options object
8936			s = jQuery.ajaxSetup( {}, options ),
8937
8938			// Callbacks context
8939			callbackContext = s.context || s,
8940
8941			// Context for global events is callbackContext if it is a DOM node or jQuery collection
8942			globalEventContext = s.context &&
8943				( callbackContext.nodeType || callbackContext.jquery ) ?
8944					jQuery( callbackContext ) :
8945					jQuery.event,
8946
8947			// Deferreds
8948			deferred = jQuery.Deferred(),
8949			completeDeferred = jQuery.Callbacks( "once memory" ),
8950
8951			// Status-dependent callbacks
8952			statusCode = s.statusCode || {},
8953
8954			// Headers (they are sent all at once)
8955			requestHeaders = {},
8956			requestHeadersNames = {},
8957
8958			// Default abort message
8959			strAbort = "canceled",
8960
8961			// Fake xhr
8962			jqXHR = {
8963				readyState: 0,
8964
8965				// Builds headers hashtable if needed
8966				getResponseHeader: function( key ) {
8967					var match;
8968					if ( completed ) {
8969						if ( !responseHeaders ) {
8970							responseHeaders = {};
8971							while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
8972								responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
8973							}
8974						}
8975						match = responseHeaders[ key.toLowerCase() ];
8976					}
8977					return match == null ? null : match;
8978				},
8979
8980				// Raw string
8981				getAllResponseHeaders: function() {
8982					return completed ? responseHeadersString : null;
8983				},
8984
8985				// Caches the header
8986				setRequestHeader: function( name, value ) {
8987					if ( completed == null ) {
8988						name = requestHeadersNames[ name.toLowerCase() ] =
8989							requestHeadersNames[ name.toLowerCase() ] || name;
8990						requestHeaders[ name ] = value;
8991					}
8992					return this;
8993				},
8994
8995				// Overrides response content-type header
8996				overrideMimeType: function( type ) {
8997					if ( completed == null ) {
8998						s.mimeType = type;
8999					}
9000					return this;
9001				},
9002
9003				// Status-dependent callbacks
9004				statusCode: function( map ) {
9005					var code;
9006					if ( map ) {
9007						if ( completed ) {
9008
9009							// Execute the appropriate callbacks
9010							jqXHR.always( map[ jqXHR.status ] );
9011						} else {
9012
9013							// Lazy-add the new callbacks in a way that preserves old ones
9014							for ( code in map ) {
9015								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9016							}
9017						}
9018					}
9019					return this;
9020				},
9021
9022				// Cancel the request
9023				abort: function( statusText ) {
9024					var finalText = statusText || strAbort;
9025					if ( transport ) {
9026						transport.abort( finalText );
9027					}
9028					done( 0, finalText );
9029					return this;
9030				}
9031			};
9032
9033		// Attach deferreds
9034		deferred.promise( jqXHR );
9035
9036		// Add protocol if not provided (prefilters might expect it)
9037		// Handle falsy url in the settings object (#10093: consistency with old signature)
9038		// We also use the url parameter if available
9039		s.url = ( ( url || s.url || location.href ) + "" )
9040			.replace( rprotocol, location.protocol + "//" );
9041
9042		// Alias method option to type as per ticket #12004
9043		s.type = options.method || options.type || s.method || s.type;
9044
9045		// Extract dataTypes list
9046		s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
9047
9048		// A cross-domain request is in order when the origin doesn't match the current origin.
9049		if ( s.crossDomain == null ) {
9050			urlAnchor = document.createElement( "a" );
9051
9052			// Support: IE <=8 - 11, Edge 12 - 15
9053			// IE throws exception on accessing the href property if url is malformed,
9054			// e.g. http://example.com:80x/
9055			try {
9056				urlAnchor.href = s.url;
9057
9058				// Support: IE <=8 - 11 only
9059				// Anchor's host property isn't correctly set when s.url is relative
9060				urlAnchor.href = urlAnchor.href;
9061				s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
9062					urlAnchor.protocol + "//" + urlAnchor.host;
9063			} catch ( e ) {
9064
9065				// If there is an error parsing the URL, assume it is crossDomain,
9066				// it can be rejected by the transport if it is invalid
9067				s.crossDomain = true;
9068			}
9069		}
9070
9071		// Convert data if not already a string
9072		if ( s.data && s.processData && typeof s.data !== "string" ) {
9073			s.data = jQuery.param( s.data, s.traditional );
9074		}
9075
9076		// Apply prefilters
9077		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9078
9079		// If request was aborted inside a prefilter, stop there
9080		if ( completed ) {
9081			return jqXHR;
9082		}
9083
9084		// We can fire global events as of now if asked to
9085		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
9086		fireGlobals = jQuery.event && s.global;
9087
9088		// Watch for a new set of requests
9089		if ( fireGlobals && jQuery.active++ === 0 ) {
9090			jQuery.event.trigger( "ajaxStart" );
9091		}
9092
9093		// Uppercase the type
9094		s.type = s.type.toUpperCase();
9095
9096		// Determine if request has content
9097		s.hasContent = !rnoContent.test( s.type );
9098
9099		// Save the URL in case we're toying with the If-Modified-Since
9100		// and/or If-None-Match header later on
9101		// Remove hash to simplify url manipulation
9102		cacheURL = s.url.replace( rhash, "" );
9103
9104		// More options handling for requests with no content
9105		if ( !s.hasContent ) {
9106
9107			// Remember the hash so we can put it back
9108			uncached = s.url.slice( cacheURL.length );
9109
9110			// If data is available and should be processed, append data to url
9111			if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
9112				cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
9113
9114				// #9682: remove data so that it's not used in an eventual retry
9115				delete s.data;
9116			}
9117
9118			// Add or update anti-cache param if needed
9119			if ( s.cache === false ) {
9120				cacheURL = cacheURL.replace( rantiCache, "$1" );
9121				uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
9122			}
9123
9124			// Put hash and anti-cache on the URL that will be requested (gh-1732)
9125			s.url = cacheURL + uncached;
9126
9127		// Change '%20' to '+' if this is encoded form body content (gh-2658)
9128		} else if ( s.data && s.processData &&
9129			( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
9130			s.data = s.data.replace( r20, "+" );
9131		}
9132
9133		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9134		if ( s.ifModified ) {
9135			if ( jQuery.lastModified[ cacheURL ] ) {
9136				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9137			}
9138			if ( jQuery.etag[ cacheURL ] ) {
9139				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9140			}
9141		}
9142
9143		// Set the correct header, if data is being sent
9144		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9145			jqXHR.setRequestHeader( "Content-Type", s.contentType );
9146		}
9147
9148		// Set the Accepts header for the server, depending on the dataType
9149		jqXHR.setRequestHeader(
9150			"Accept",
9151			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
9152				s.accepts[ s.dataTypes[ 0 ] ] +
9153					( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9154				s.accepts[ "*" ]
9155		);
9156
9157		// Check for headers option
9158		for ( i in s.headers ) {
9159			jqXHR.setRequestHeader( i, s.headers[ i ] );
9160		}
9161
9162		// Allow custom headers/mimetypes and early abort
9163		if ( s.beforeSend &&
9164			( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
9165
9166			// Abort if not done already and return
9167			return jqXHR.abort();
9168		}
9169
9170		// Aborting is no longer a cancellation
9171		strAbort = "abort";
9172
9173		// Install callbacks on deferreds
9174		completeDeferred.add( s.complete );
9175		jqXHR.done( s.success );
9176		jqXHR.fail( s.error );
9177
9178		// Get transport
9179		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9180
9181		// If no transport, we auto-abort
9182		if ( !transport ) {
9183			done( -1, "No Transport" );
9184		} else {
9185			jqXHR.readyState = 1;
9186
9187			// Send global event
9188			if ( fireGlobals ) {
9189				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9190			}
9191
9192			// If request was aborted inside ajaxSend, stop there
9193			if ( completed ) {
9194				return jqXHR;
9195			}
9196
9197			// Timeout
9198			if ( s.async && s.timeout > 0 ) {
9199				timeoutTimer = window.setTimeout( function() {
9200					jqXHR.abort( "timeout" );
9201				}, s.timeout );
9202			}
9203
9204			try {
9205				completed = false;
9206				transport.send( requestHeaders, done );
9207			} catch ( e ) {
9208
9209				// Rethrow post-completion exceptions
9210				if ( completed ) {
9211					throw e;
9212				}
9213
9214				// Propagate others as results
9215				done( -1, e );
9216			}
9217		}
9218
9219		// Callback for when everything is done
9220		function done( status, nativeStatusText, responses, headers ) {
9221			var isSuccess, success, error, response, modified,
9222				statusText = nativeStatusText;
9223
9224			// Ignore repeat invocations
9225			if ( completed ) {
9226				return;
9227			}
9228
9229			completed = true;
9230
9231			// Clear timeout if it exists
9232			if ( timeoutTimer ) {
9233				window.clearTimeout( timeoutTimer );
9234			}
9235
9236			// Dereference transport for early garbage collection
9237			// (no matter how long the jqXHR object will be used)
9238			transport = undefined;
9239
9240			// Cache response headers
9241			responseHeadersString = headers || "";
9242
9243			// Set readyState
9244			jqXHR.readyState = status > 0 ? 4 : 0;
9245
9246			// Determine if successful
9247			isSuccess = status >= 200 && status < 300 || status === 304;
9248
9249			// Get response data
9250			if ( responses ) {
9251				response = ajaxHandleResponses( s, jqXHR, responses );
9252			}
9253
9254			// Convert no matter what (that way responseXXX fields are always set)
9255			response = ajaxConvert( s, response, jqXHR, isSuccess );
9256
9257			// If successful, handle type chaining
9258			if ( isSuccess ) {
9259
9260				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9261				if ( s.ifModified ) {
9262					modified = jqXHR.getResponseHeader( "Last-Modified" );
9263					if ( modified ) {
9264						jQuery.lastModified[ cacheURL ] = modified;
9265					}
9266					modified = jqXHR.getResponseHeader( "etag" );
9267					if ( modified ) {
9268						jQuery.etag[ cacheURL ] = modified;
9269					}
9270				}
9271
9272				// if no content
9273				if ( status === 204 || s.type === "HEAD" ) {
9274					statusText = "nocontent";
9275
9276				// if not modified
9277				} else if ( status === 304 ) {
9278					statusText = "notmodified";
9279
9280				// If we have data, let's convert it
9281				} else {
9282					statusText = response.state;
9283					success = response.data;
9284					error = response.error;
9285					isSuccess = !error;
9286				}
9287			} else {
9288
9289				// Extract error from statusText and normalize for non-aborts
9290				error = statusText;
9291				if ( status || !statusText ) {
9292					statusText = "error";
9293					if ( status < 0 ) {
9294						status = 0;
9295					}
9296				}
9297			}
9298
9299			// Set data for the fake xhr object
9300			jqXHR.status = status;
9301			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9302
9303			// Success/Error
9304			if ( isSuccess ) {
9305				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9306			} else {
9307				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9308			}
9309
9310			// Status-dependent callbacks
9311			jqXHR.statusCode( statusCode );
9312			statusCode = undefined;
9313
9314			if ( fireGlobals ) {
9315				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9316					[ jqXHR, s, isSuccess ? success : error ] );
9317			}
9318
9319			// Complete
9320			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9321
9322			if ( fireGlobals ) {
9323				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9324
9325				// Handle the global AJAX counter
9326				if ( !( --jQuery.active ) ) {
9327					jQuery.event.trigger( "ajaxStop" );
9328				}
9329			}
9330		}
9331
9332		return jqXHR;
9333	},
9334
9335	getJSON: function( url, data, callback ) {
9336		return jQuery.get( url, data, callback, "json" );
9337	},
9338
9339	getScript: function( url, callback ) {
9340		return jQuery.get( url, undefined, callback, "script" );
9341	}
9342} );
9343
9344jQuery.each( [ "get", "post" ], function( i, method ) {
9345	jQuery[ method ] = function( url, data, callback, type ) {
9346
9347		// Shift arguments if data argument was omitted
9348		if ( isFunction( data ) ) {
9349			type = type || callback;
9350			callback = data;
9351			data = undefined;
9352		}
9353
9354		// The url can be an options object (which then must have .url)
9355		return jQuery.ajax( jQuery.extend( {
9356			url: url,
9357			type: method,
9358			dataType: type,
9359			data: data,
9360			success: callback
9361		}, jQuery.isPlainObject( url ) && url ) );
9362	};
9363} );
9364
9365
9366jQuery._evalUrl = function( url ) {
9367	return jQuery.ajax( {
9368		url: url,
9369
9370		// Make this explicit, since user can override this through ajaxSetup (#11264)
9371		type: "GET",
9372		dataType: "script",
9373		cache: true,
9374		async: false,
9375		global: false,
9376		"throws": true
9377	} );
9378};
9379
9380
9381jQuery.fn.extend( {
9382	wrapAll: function( html ) {
9383		var wrap;
9384
9385		if ( this[ 0 ] ) {
9386			if ( isFunction( html ) ) {
9387				html = html.call( this[ 0 ] );
9388			}
9389
9390			// The elements to wrap the target around
9391			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
9392
9393			if ( this[ 0 ].parentNode ) {
9394				wrap.insertBefore( this[ 0 ] );
9395			}
9396
9397			wrap.map( function() {
9398				var elem = this;
9399
9400				while ( elem.firstElementChild ) {
9401					elem = elem.firstElementChild;
9402				}
9403
9404				return elem;
9405			} ).append( this );
9406		}
9407
9408		return this;
9409	},
9410
9411	wrapInner: function( html ) {
9412		if ( isFunction( html ) ) {
9413			return this.each( function( i ) {
9414				jQuery( this ).wrapInner( html.call( this, i ) );
9415			} );
9416		}
9417
9418		return this.each( function() {
9419			var self = jQuery( this ),
9420				contents = self.contents();
9421
9422			if ( contents.length ) {
9423				contents.wrapAll( html );
9424
9425			} else {
9426				self.append( html );
9427			}
9428		} );
9429	},
9430
9431	wrap: function( html ) {
9432		var htmlIsFunction = isFunction( html );
9433
9434		return this.each( function( i ) {
9435			jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );
9436		} );
9437	},
9438
9439	unwrap: function( selector ) {
9440		this.parent( selector ).not( "body" ).each( function() {
9441			jQuery( this ).replaceWith( this.childNodes );
9442		} );
9443		return this;
9444	}
9445} );
9446
9447
9448jQuery.expr.pseudos.hidden = function( elem ) {
9449	return !jQuery.expr.pseudos.visible( elem );
9450};
9451jQuery.expr.pseudos.visible = function( elem ) {
9452	return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
9453};
9454
9455
9456
9457
9458jQuery.ajaxSettings.xhr = function() {
9459	try {
9460		return new window.XMLHttpRequest();
9461	} catch ( e ) {}
9462};
9463
9464var xhrSuccessStatus = {
9465
9466		// File protocol always yields status code 0, assume 200
9467		0: 200,
9468
vendor: 1,240 bytes, lines 9469-9511
9469		// Support: IE <=9 only
9470		// #1450: sometimes IE returns 1223 when it should be 204
9471		1223: 204
9472	},
9473	xhrSupported = jQuery.ajaxSettings.xhr();
9474
9475support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9476support.ajax = xhrSupported = !!xhrSupported;
9477
9478jQuery.ajaxTransport( function( options ) {
9479	var callback, errorCallback;
9480
9481	// Cross domain only allowed if supported through XMLHttpRequest
9482	if ( support.cors || xhrSupported && !options.crossDomain ) {
9483		return {
9484			send: function( headers, complete ) {
9485				var i,
9486					xhr = options.xhr();
9487
9488				xhr.open(
9489					options.type,
9490					options.url,
9491					options.async,
9492					options.username,
9493					options.password
9494				);
9495
9496				// Apply custom fields if provided
9497				if ( options.xhrFields ) {
9498					for ( i in options.xhrFields ) {
9499						xhr[ i ] = options.xhrFields[ i ];
9500					}
9501				}
9502
9503				// Override mime type if needed
9504				if ( options.mimeType && xhr.overrideMimeType ) {
9505					xhr.overrideMimeType( options.mimeType );
9506				}
9507
9508				// X-Requested-With header
9509				// For cross-domain requests, seeing as conditions for a preflight are
9510				// akin to a jigsaw puzzle, we simply never set it to be sure.
9511				// (it can always be set on a per-request basis or even using ajaxSetup)
vendor: 5,627 bytes, lines 9512-9733
9512				// For same-domain requests, won't change header if already provided.
9513				if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
9514					headers[ "X-Requested-With" ] = "XMLHttpRequest";
9515				}
9516
9517				// Set headers
9518				for ( i in headers ) {
9519					xhr.setRequestHeader( i, headers[ i ] );
9520				}
9521
9522				// Callback
9523				callback = function( type ) {
9524					return function() {
9525						if ( callback ) {
9526							callback = errorCallback = xhr.onload =
9527								xhr.onerror = xhr.onabort = xhr.ontimeout =
9528									xhr.onreadystatechange = null;
9529
9530							if ( type === "abort" ) {
9531								xhr.abort();
9532							} else if ( type === "error" ) {
9533
9534								// Support: IE <=9 only
9535								// On a manual native abort, IE9 throws
9536								// errors on any property access that is not readyState
9537								if ( typeof xhr.status !== "number" ) {
9538									complete( 0, "error" );
9539								} else {
9540									complete(
9541
9542										// File: protocol always yields status 0; see #8605, #14207
9543										xhr.status,
9544										xhr.statusText
9545									);
9546								}
9547							} else {
9548								complete(
9549									xhrSuccessStatus[ xhr.status ] || xhr.status,
9550									xhr.statusText,
9551
9552									// Support: IE <=9 only
9553									// IE9 has no XHR2 but throws on binary (trac-11426)
9554									// For XHR2 non-text, let the caller handle it (gh-2498)
9555									( xhr.responseType || "text" ) !== "text"  ||
9556									typeof xhr.responseText !== "string" ?
9557										{ binary: xhr.response } :
9558										{ text: xhr.responseText },
9559									xhr.getAllResponseHeaders()
9560								);
9561							}
9562						}
9563					};
9564				};
9565
9566				// Listen to events
9567				xhr.onload = callback();
9568				errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" );
9569
9570				// Support: IE 9 only
9571				// Use onreadystatechange to replace onabort
9572				// to handle uncaught aborts
9573				if ( xhr.onabort !== undefined ) {
9574					xhr.onabort = errorCallback;
9575				} else {
9576					xhr.onreadystatechange = function() {
9577
9578						// Check readyState before timeout as it changes
9579						if ( xhr.readyState === 4 ) {
9580
9581							// Allow onerror to be called first,
9582							// but that will not handle a native abort
9583							// Also, save errorCallback to a variable
9584							// as xhr.onerror cannot be accessed
9585							window.setTimeout( function() {
9586								if ( callback ) {
9587									errorCallback();
9588								}
9589							} );
9590						}
9591					};
9592				}
9593
9594				// Create the abort callback
9595				callback = callback( "abort" );
9596
9597				try {
9598
9599					// Do send the request (this may raise an exception)
9600					xhr.send( options.hasContent && options.data || null );
9601				} catch ( e ) {
9602
9603					// #14683: Only rethrow if this hasn't been notified as an error yet
9604					if ( callback ) {
9605						throw e;
9606					}
9607				}
9608			},
9609
9610			abort: function() {
9611				if ( callback ) {
9612					callback();
9613				}
9614			}
9615		};
9616	}
9617} );
9618
9619
9620
9621
9622// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
9623jQuery.ajaxPrefilter( function( s ) {
9624	if ( s.crossDomain ) {
9625		s.contents.script = false;
9626	}
9627} );
9628
9629// Install script dataType
9630jQuery.ajaxSetup( {
9631	accepts: {
9632		script: "text/javascript, application/javascript, " +
9633			"application/ecmascript, application/x-ecmascript"
9634	},
9635	contents: {
9636		script: /\b(?:java|ecma)script\b/
9637	},
9638	converters: {
9639		"text script": function( text ) {
9640			jQuery.globalEval( text );
9641			return text;
9642		}
9643	}
9644} );
9645
9646// Handle cache's special case and crossDomain
9647jQuery.ajaxPrefilter( "script", function( s ) {
9648	if ( s.cache === undefined ) {
9649		s.cache = false;
9650	}
9651	if ( s.crossDomain ) {
9652		s.type = "GET";
9653	}
9654} );
9655
9656// Bind script tag hack transport
9657jQuery.ajaxTransport( "script", function( s ) {
9658
9659	// This transport only deals with cross domain requests
9660	if ( s.crossDomain ) {
9661		var script, callback;
9662		return {
9663			send: function( _, complete ) {
9664				script = jQuery( "<script>" ).prop( {
9665					charset: s.scriptCharset,
9666					src: s.url
9667				} ).on(
9668					"load error",
9669					callback = function( evt ) {
9670						script.remove();
9671						callback = null;
9672						if ( evt ) {
9673							complete( evt.type === "error" ? 404 : 200, evt.type );
9674						}
9675					}
9676				);
9677
9678				// Use native DOM manipulation to avoid our domManip AJAX trickery
9679				document.head.appendChild( script[ 0 ] );
9680			},
9681			abort: function() {
9682				if ( callback ) {
9683					callback();
9684				}
9685			}
9686		};
9687	}
9688} );
9689
9690
9691
9692
9693var oldCallbacks = [],
9694	rjsonp = /(=)\?(?=&|$)|\?\?/;
9695
9696// Default jsonp settings
9697jQuery.ajaxSetup( {
9698	jsonp: "callback",
9699	jsonpCallback: function() {
9700		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
9701		this[ callback ] = true;
9702		return callback;
9703	}
9704} );
9705
9706// Detect, normalize options and install callbacks for jsonp requests
9707jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
9708
9709	var callbackName, overwritten, responseContainer,
9710		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
9711			"url" :
9712			typeof s.data === "string" &&
9713				( s.contentType || "" )
9714					.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
9715				rjsonp.test( s.data ) && "data"
9716		);
9717
9718	// Handle iff the expected data type is "jsonp" or we have a parameter to set
9719	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
9720
9721		// Get callback name, remembering preexisting value associated with it
9722		callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
9723			s.jsonpCallback() :
9724			s.jsonpCallback;
9725
9726		// Insert callback into url or form data
9727		if ( jsonProp ) {
9728			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
9729		} else if ( s.jsonp !== false ) {
9730			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
9731		}
9732
9733		// Use data converter to retrieve json after script execution
vendor: 2,987 bytes, lines 9734-9843
9734		s.converters[ "script json" ] = function() {
9735			if ( !responseContainer ) {
9736				jQuery.error( callbackName + " was not called" );
9737			}
9738			return responseContainer[ 0 ];
9739		};
9740
9741		// Force json dataType
9742		s.dataTypes[ 0 ] = "json";
9743
9744		// Install callback
9745		overwritten = window[ callbackName ];
9746		window[ callbackName ] = function() {
9747			responseContainer = arguments;
9748		};
9749
9750		// Clean-up function (fires after converters)
9751		jqXHR.always( function() {
9752
9753			// If previous value didn't exist - remove it
9754			if ( overwritten === undefined ) {
9755				jQuery( window ).removeProp( callbackName );
9756
9757			// Otherwise restore preexisting value
9758			} else {
9759				window[ callbackName ] = overwritten;
9760			}
9761
9762			// Save back as free
9763			if ( s[ callbackName ] ) {
9764
9765				// Make sure that re-using the options doesn't screw things around
9766				s.jsonpCallback = originalSettings.jsonpCallback;
9767
9768				// Save the callback name for future use
9769				oldCallbacks.push( callbackName );
9770			}
9771
9772			// Call if it was a function and we have a response
9773			if ( responseContainer && isFunction( overwritten ) ) {
9774				overwritten( responseContainer[ 0 ] );
9775			}
9776
9777			responseContainer = overwritten = undefined;
9778		} );
9779
9780		// Delegate to script
9781		return "script";
9782	}
9783} );
9784
9785
9786
9787
9788// Support: Safari 8 only
9789// In Safari 8 documents created via document.implementation.createHTMLDocument
9790// collapse sibling forms: the second one becomes a child of the first one.
9791// Because of that, this security measure has to be disabled in Safari 8.
9792// https://bugs.webkit.org/show_bug.cgi?id=137337
9793support.createHTMLDocument = ( function() {
9794	var body = document.implementation.createHTMLDocument( "" ).body;
9795	body.innerHTML = "<form></form><form></form>";
9796	return body.childNodes.length === 2;
9797} )();
9798
9799
9800// Argument "data" should be string of html
9801// context (optional): If specified, the fragment will be created in this context,
9802// defaults to document
9803// keepScripts (optional): If true, will include scripts passed in the html string
9804jQuery.parseHTML = function( data, context, keepScripts ) {
9805	if ( typeof data !== "string" ) {
9806		return [];
9807	}
9808	if ( typeof context === "boolean" ) {
9809		keepScripts = context;
9810		context = false;
9811	}
9812
9813	var base, parsed, scripts;
9814
9815	if ( !context ) {
9816
9817		// Stop scripts or inline event handlers from being executed immediately
9818		// by using document.implementation
9819		if ( support.createHTMLDocument ) {
9820			context = document.implementation.createHTMLDocument( "" );
9821
9822			// Set the base href for the created document
9823			// so any parsed elements with URLs
9824			// are based on the document's URL (gh-2965)
9825			base = context.createElement( "base" );
9826			base.href = document.location.href;
9827			context.head.appendChild( base );
9828		} else {
9829			context = document;
9830		}
9831	}
9832
9833	parsed = rsingleTag.exec( data );
9834	scripts = !keepScripts && [];
9835
9836	// Single tag
9837	if ( parsed ) {
9838		return [ context.createElement( parsed[ 1 ] ) ];
9839	}
9840
9841	parsed = buildFragment( [ data ], context, scripts );
9842
9843	if ( scripts && scripts.length ) {
vendor: 14,511 bytes, lines 9844-10364
9844		jQuery( scripts ).remove();
9845	}
9846
9847	return jQuery.merge( [], parsed.childNodes );
9848};
9849
9850
9851/**
9852 * Load a url into a page
9853 */
9854jQuery.fn.load = function( url, params, callback ) {
9855	var selector, type, response,
9856		self = this,
9857		off = url.indexOf( " " );
9858
9859	if ( off > -1 ) {
9860		selector = stripAndCollapse( url.slice( off ) );
9861		url = url.slice( 0, off );
9862	}
9863
9864	// If it's a function
9865	if ( isFunction( params ) ) {
9866
9867		// We assume that it's the callback
9868		callback = params;
9869		params = undefined;
9870
9871	// Otherwise, build a param string
9872	} else if ( params && typeof params === "object" ) {
9873		type = "POST";
9874	}
9875
9876	// If we have elements to modify, make the request
9877	if ( self.length > 0 ) {
9878		jQuery.ajax( {
9879			url: url,
9880
9881			// If "type" variable is undefined, then "GET" method will be used.
9882			// Make value of this field explicit since
9883			// user can override it through ajaxSetup method
9884			type: type || "GET",
9885			dataType: "html",
9886			data: params
9887		} ).done( function( responseText ) {
9888
9889			// Save response for use in complete callback
9890			response = arguments;
9891
9892			self.html( selector ?
9893
9894				// If a selector was specified, locate the right elements in a dummy div
9895				// Exclude scripts to avoid IE 'Permission Denied' errors
9896				jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
9897
9898				// Otherwise use the full result
9899				responseText );
9900
9901		// If the request succeeds, this function gets "data", "status", "jqXHR"
9902		// but they are ignored because response was set above.
9903		// If it fails, this function gets "jqXHR", "status", "error"
9904		} ).always( callback && function( jqXHR, status ) {
9905			self.each( function() {
9906				callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
9907			} );
9908		} );
9909	}
9910
9911	return this;
9912};
9913
9914
9915
9916
9917// Attach a bunch of functions for handling common AJAX events
9918jQuery.each( [
9919	"ajaxStart",
9920	"ajaxStop",
9921	"ajaxComplete",
9922	"ajaxError",
9923	"ajaxSuccess",
9924	"ajaxSend"
9925], function( i, type ) {
9926	jQuery.fn[ type ] = function( fn ) {
9927		return this.on( type, fn );
9928	};
9929} );
9930
9931
9932
9933
9934jQuery.expr.pseudos.animated = function( elem ) {
9935	return jQuery.grep( jQuery.timers, function( fn ) {
9936		return elem === fn.elem;
9937	} ).length;
9938};
9939
9940
9941
9942
9943jQuery.offset = {
9944	setOffset: function( elem, options, i ) {
9945		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
9946			position = jQuery.css( elem, "position" ),
9947			curElem = jQuery( elem ),
9948			props = {};
9949
9950		// Set position first, in-case top/left are set even on static elem
9951		if ( position === "static" ) {
9952			elem.style.position = "relative";
9953		}
9954
9955		curOffset = curElem.offset();
9956		curCSSTop = jQuery.css( elem, "top" );
9957		curCSSLeft = jQuery.css( elem, "left" );
9958		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
9959			( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
9960
9961		// Need to be able to calculate position if either
9962		// top or left is auto and position is either absolute or fixed
9963		if ( calculatePosition ) {
9964			curPosition = curElem.position();
9965			curTop = curPosition.top;
9966			curLeft = curPosition.left;
9967
9968		} else {
9969			curTop = parseFloat( curCSSTop ) || 0;
9970			curLeft = parseFloat( curCSSLeft ) || 0;
9971		}
9972
9973		if ( isFunction( options ) ) {
9974
9975			// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
9976			options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
9977		}
9978
9979		if ( options.top != null ) {
9980			props.top = ( options.top - curOffset.top ) + curTop;
9981		}
9982		if ( options.left != null ) {
9983			props.left = ( options.left - curOffset.left ) + curLeft;
9984		}
9985
9986		if ( "using" in options ) {
9987			options.using.call( elem, props );
9988
9989		} else {
9990			curElem.css( props );
9991		}
9992	}
9993};
9994
9995jQuery.fn.extend( {
9996
9997	// offset() relates an element's border box to the document origin
9998	offset: function( options ) {
9999
10000		// Preserve chaining for setter
10001		if ( arguments.length ) {
10002			return options === undefined ?
10003				this :
10004				this.each( function( i ) {
10005					jQuery.offset.setOffset( this, options, i );
10006				} );
10007		}
10008
10009		var rect, win,
10010			elem = this[ 0 ];
10011
10012		if ( !elem ) {
10013			return;
10014		}
10015
10016		// Return zeros for disconnected and hidden (display: none) elements (gh-2310)
10017		// Support: IE <=11 only
10018		// Running getBoundingClientRect on a
10019		// disconnected node in IE throws an error
10020		if ( !elem.getClientRects().length ) {
10021			return { top: 0, left: 0 };
10022		}
10023
10024		// Get document-relative position by adding viewport scroll to viewport-relative gBCR
10025		rect = elem.getBoundingClientRect();
10026		win = elem.ownerDocument.defaultView;
10027		return {
10028			top: rect.top + win.pageYOffset,
10029			left: rect.left + win.pageXOffset
10030		};
10031	},
10032
10033	// position() relates an element's margin box to its offset parent's padding box
10034	// This corresponds to the behavior of CSS absolute positioning
10035	position: function() {
10036		if ( !this[ 0 ] ) {
10037			return;
10038		}
10039
10040		var offsetParent, offset, doc,
10041			elem = this[ 0 ],
10042			parentOffset = { top: 0, left: 0 };
10043
10044		// position:fixed elements are offset from the viewport, which itself always has zero offset
10045		if ( jQuery.css( elem, "position" ) === "fixed" ) {
10046
10047			// Assume position:fixed implies availability of getBoundingClientRect
10048			offset = elem.getBoundingClientRect();
10049
10050		} else {
10051			offset = this.offset();
10052
10053			// Account for the *real* offset parent, which can be the document or its root element
10054			// when a statically positioned element is identified
10055			doc = elem.ownerDocument;
10056			offsetParent = elem.offsetParent || doc.documentElement;
10057			while ( offsetParent &&
10058				( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
10059				jQuery.css( offsetParent, "position" ) === "static" ) {
10060
10061				offsetParent = offsetParent.parentNode;
10062			}
10063			if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {
10064
10065				// Incorporate borders into its offset, since they are outside its content origin
10066				parentOffset = jQuery( offsetParent ).offset();
10067				parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
10068				parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
10069			}
10070		}
10071
10072		// Subtract parent offsets and element margins
10073		return {
10074			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10075			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
10076		};
10077	},
10078
10079	// This method will return documentElement in the following cases:
10080	// 1) For the element inside the iframe without offsetParent, this method will return
10081	//    documentElement of the parent window
10082	// 2) For the hidden or detached element
10083	// 3) For body or html element, i.e. in case of the html node - it will return itself
10084	//
10085	// but those exceptions were never presented as a real life use-cases
10086	// and might be considered as more preferable results.
10087	//
10088	// This logic, however, is not guaranteed and can change at any point in the future
10089	offsetParent: function() {
10090		return this.map( function() {
10091			var offsetParent = this.offsetParent;
10092
10093			while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
10094				offsetParent = offsetParent.offsetParent;
10095			}
10096
10097			return offsetParent || documentElement;
10098		} );
10099	}
10100} );
10101
10102// Create scrollLeft and scrollTop methods
10103jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10104	var top = "pageYOffset" === prop;
10105
10106	jQuery.fn[ method ] = function( val ) {
10107		return access( this, function( elem, method, val ) {
10108
10109			// Coalesce documents and windows
10110			var win;
10111			if ( isWindow( elem ) ) {
10112				win = elem;
10113			} else if ( elem.nodeType === 9 ) {
10114				win = elem.defaultView;
10115			}
10116
10117			if ( val === undefined ) {
10118				return win ? win[ prop ] : elem[ method ];
10119			}
10120
10121			if ( win ) {
10122				win.scrollTo(
10123					!top ? val : win.pageXOffset,
10124					top ? val : win.pageYOffset
10125				);
10126
10127			} else {
10128				elem[ method ] = val;
10129			}
10130		}, method, val, arguments.length );
10131	};
10132} );
10133
10134// Support: Safari <=7 - 9.1, Chrome <=37 - 49
10135// Add the top/left cssHooks using jQuery.fn.position
10136// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10137// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
10138// getComputedStyle returns percent when specified for top/left/bottom/right;
10139// rather than make the css module depend on the offset module, just check for it here
10140jQuery.each( [ "top", "left" ], function( i, prop ) {
10141	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10142		function( elem, computed ) {
10143			if ( computed ) {
10144				computed = curCSS( elem, prop );
10145
10146				// If curCSS returns percentage, fallback to offset
10147				return rnumnonpx.test( computed ) ?
10148					jQuery( elem ).position()[ prop ] + "px" :
10149					computed;
10150			}
10151		}
10152	);
10153} );
10154
10155
10156// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10157jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10158	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
10159		function( defaultExtra, funcName ) {
10160
10161		// Margin is only for outerHeight, outerWidth
10162		jQuery.fn[ funcName ] = function( margin, value ) {
10163			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10164				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10165
10166			return access( this, function( elem, type, value ) {
10167				var doc;
10168
10169				if ( isWindow( elem ) ) {
10170
10171					// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
10172					return funcName.indexOf( "outer" ) === 0 ?
10173						elem[ "inner" + name ] :
10174						elem.document.documentElement[ "client" + name ];
10175				}
10176
10177				// Get document width or height
10178				if ( elem.nodeType === 9 ) {
10179					doc = elem.documentElement;
10180
10181					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
10182					// whichever is greatest
10183					return Math.max(
10184						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10185						elem.body[ "offset" + name ], doc[ "offset" + name ],
10186						doc[ "client" + name ]
10187					);
10188				}
10189
10190				return value === undefined ?
10191
10192					// Get width or height on the element, requesting but not forcing parseFloat
10193					jQuery.css( elem, type, extra ) :
10194
10195					// Set width or height on the element
10196					jQuery.style( elem, type, value, extra );
10197			}, type, chainable ? margin : undefined, chainable );
10198		};
10199	} );
10200} );
10201
10202
10203jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
10204	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
10205	"change select submit keydown keypress keyup contextmenu" ).split( " " ),
10206	function( i, name ) {
10207
10208	// Handle event binding
10209	jQuery.fn[ name ] = function( data, fn ) {
10210		return arguments.length > 0 ?
10211			this.on( name, null, data, fn ) :
10212			this.trigger( name );
10213	};
10214} );
10215
10216jQuery.fn.extend( {
10217	hover: function( fnOver, fnOut ) {
10218		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
10219	}
10220} );
10221
10222
10223
10224
10225jQuery.fn.extend( {
10226
10227	bind: function( types, data, fn ) {
10228		return this.on( types, null, data, fn );
10229	},
10230	unbind: function( types, fn ) {
10231		return this.off( types, null, fn );
10232	},
10233
10234	delegate: function( selector, types, data, fn ) {
10235		return this.on( types, selector, data, fn );
10236	},
10237	undelegate: function( selector, types, fn ) {
10238
10239		// ( namespace ) or ( selector, types [, fn] )
10240		return arguments.length === 1 ?
10241			this.off( selector, "**" ) :
10242			this.off( types, selector || "**", fn );
10243	}
10244} );
10245
10246// Bind a function to a context, optionally partially applying any
10247// arguments.
10248// jQuery.proxy is deprecated to promote standards (specifically Function#bind)
10249// However, it is not slated for removal any time soon
10250jQuery.proxy = function( fn, context ) {
10251	var tmp, args, proxy;
10252
10253	if ( typeof context === "string" ) {
10254		tmp = fn[ context ];
10255		context = fn;
10256		fn = tmp;
10257	}
10258
10259	// Quick check to determine if target is callable, in the spec
10260	// this throws a TypeError, but we will just return undefined.
10261	if ( !isFunction( fn ) ) {
10262		return undefined;
10263	}
10264
10265	// Simulated bind
10266	args = slice.call( arguments, 2 );
10267	proxy = function() {
10268		return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
10269	};
10270
10271	// Set the guid of unique handler to the same of original handler, so it can be removed
10272	proxy.guid = fn.guid = fn.guid || jQuery.guid++;
10273
10274	return proxy;
10275};
10276
10277jQuery.holdReady = function( hold ) {
10278	if ( hold ) {
10279		jQuery.readyWait++;
10280	} else {
10281		jQuery.ready( true );
10282	}
10283};
10284jQuery.isArray = Array.isArray;
10285jQuery.parseJSON = JSON.parse;
10286jQuery.nodeName = nodeName;
10287jQuery.isFunction = isFunction;
10288jQuery.isWindow = isWindow;
10289jQuery.camelCase = camelCase;
10290jQuery.type = toType;
10291
10292jQuery.now = Date.now;
10293
10294jQuery.isNumeric = function( obj ) {
10295
10296	// As of jQuery 3.0, isNumeric is limited to
10297	// strings and numbers (primitives or objects)
10298	// that can be coerced to finite numbers (gh-2662)
10299	var type = jQuery.type( obj );
10300	return ( type === "number" || type === "string" ) &&
10301
10302		// parseFloat NaNs numeric-cast false positives ("")
10303		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
10304		// subtraction forces infinities to NaN
10305		!isNaN( obj - parseFloat( obj ) );
10306};
10307
10308
10309
10310
10311// Register as a named AMD module, since jQuery can be concatenated with other
10312// files that may use define, but not via a proper concatenation script that
10313// understands anonymous AMD modules. A named AMD is safest and most robust
10314// way to register. Lowercase jquery is used because AMD module names are
10315// derived from file names, and jQuery is normally delivered in a lowercase
10316// file name. Do this after creating the global so that if an AMD module wants
10317// to call noConflict to hide this version of jQuery, it will work.
10318
10319// Note that for maximum portability, libraries that are not jQuery should
10320// declare themselves as anonymous modules, and avoid setting a global if an
10321// AMD loader is present. jQuery is a special case. For more information, see
10322// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10323
10324if ( typeof define === "function" && define.amd ) {
10325	define( "jquery", [], function() {
10326		return jQuery;
10327	} );
10328}
10329
10330
10331
10332
10333var
10334
10335	// Map over jQuery in case of overwrite
10336	_jQuery = window.jQuery,
10337
10338	// Map over the $ in case of overwrite
10339	_$ = window.$;
10340
10341jQuery.noConflict = function( deep ) {
10342	if ( window.$ === jQuery ) {
10343		window.$ = _$;
10344	}
10345
10346	if ( deep && window.jQuery === jQuery ) {
10347		window.jQuery = _jQuery;
10348	}
10349
10350	return jQuery;
10351};
10352
10353// Expose jQuery and $ identifiers, even in AMD
10354// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
10355// and CommonJS for browser emulators (#13566)
10356if ( !noGlobal ) {
10357	window.jQuery = window.$ = jQuery;
10358}
10359
10360
10361
10362
10363return jQuery;
10364} );
vendor: 4,680 bytes, lines 10365-10524
10365
10366
10367/**!
10368 * @fileOverview Kickass library to create and place poppers near their reference elements.
10369 * @version 1.14.7
10370 * @license
10371 * Copyright (c) 2016 Federico Zivolo and contributors
10372 *
10373 * Permission is hereby granted, free of charge, to any person obtaining a copy
10374 * of this software and associated documentation files (the "Software"), to deal
10375 * in the Software without restriction, including without limitation the rights
10376 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10377 * copies of the Software, and to permit persons to whom the Software is
10378 * furnished to do so, subject to the following conditions:
10379 *
10380 * The above copyright notice and this permission notice shall be included in all
10381 * copies or substantial portions of the Software.
10382 *
10383 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10384 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10385 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10386 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
10387 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
10388 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
10389 * SOFTWARE.
10390 */
10391(function (global, factory) {
10392	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
10393	typeof define === 'function' && define.amd ? define(factory) :
10394	(global.Popper = factory());
10395}(this, (function () { 'use strict';
10396
10397var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
10398
10399var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
10400var timeoutDuration = 0;
10401for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
10402  if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
10403    timeoutDuration = 1;
10404    break;
10405  }
10406}
10407
10408function microtaskDebounce(fn) {
10409  var called = false;
10410  return function () {
10411    if (called) {
10412      return;
10413    }
10414    called = true;
10415    window.Promise.resolve().then(function () {
10416      called = false;
10417      fn();
10418    });
10419  };
10420}
10421
10422function taskDebounce(fn) {
10423  var scheduled = false;
10424  return function () {
10425    if (!scheduled) {
10426      scheduled = true;
10427      setTimeout(function () {
10428        scheduled = false;
10429        fn();
10430      }, timeoutDuration);
10431    }
10432  };
10433}
10434
10435var supportsMicroTasks = isBrowser && window.Promise;
10436
10437/**
10438* Create a debounced version of a method, that's asynchronously deferred
10439* but called in the minimum time possible.
10440*
10441* @method
10442* @memberof Popper.Utils
10443* @argument {Function} fn
10444* @returns {Function}
10445*/
10446var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
10447
10448/**
10449 * Check if the given variable is a function
10450 * @method
10451 * @memberof Popper.Utils
10452 * @argument {Any} functionToCheck - variable to check
10453 * @returns {Boolean} answer to: is a function?
10454 */
10455function isFunction(functionToCheck) {
10456  var getType = {};
10457  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
10458}
10459
10460/**
10461 * Get CSS computed property of the given element
10462 * @method
10463 * @memberof Popper.Utils
10464 * @argument {Eement} element
10465 * @argument {String} property
10466 */
10467function getStyleComputedProperty(element, property) {
10468  if (element.nodeType !== 1) {
10469    return [];
10470  }
10471  // NOTE: 1 DOM access here
10472  var window = element.ownerDocument.defaultView;
10473  var css = window.getComputedStyle(element, null);
10474  return property ? css[property] : css;
10475}
10476
10477/**
10478 * Returns the parentNode or the host of the element
10479 * @method
10480 * @memberof Popper.Utils
10481 * @argument {Element} element
10482 * @returns {Element} parent
10483 */
10484function getParentNode(element) {
10485  if (element.nodeName === 'HTML') {
10486    return element;
10487  }
10488  return element.parentNode || element.host;
10489}
10490
10491/**
10492 * Returns the scrolling parent of the given element
10493 * @method
10494 * @memberof Popper.Utils
10495 * @argument {Element} element
10496 * @returns {Element} scroll parent
10497 */
10498function getScrollParent(element) {
10499  // Return body, `getScroll` will take care to get the correct `scrollTop` from it
10500  if (!element) {
10501    return document.body;
10502  }
10503
10504  switch (element.nodeName) {
10505    case 'HTML':
10506    case 'BODY':
10507      return element.ownerDocument.body;
10508    case '#document':
10509      return element.body;
10510  }
10511
10512  // Firefox want us to check `-x` and `-y` variations as well
10513
10514  var _getStyleComputedProp = getStyleComputedProperty(element),
10515      overflow = _getStyleComputedProp.overflow,
10516      overflowX = _getStyleComputedProp.overflowX,
10517      overflowY = _getStyleComputedProp.overflowY;
10518
10519  if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
10520    return element;
10521  }
10522
10523  return getScrollParent(getParentNode(element));
10524}
vendor: 3,047 bytes, lines 10524-10630
10524
10525
10526var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
10527var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
10528
10529/**
10530 * Determines if the browser is Internet Explorer
10531 * @method
10532 * @memberof Popper.Utils
10533 * @param {Number} version to check
10534 * @returns {Boolean} isIE
10535 */
10536function isIE(version) {
10537  if (version === 11) {
10538    return isIE11;
10539  }
10540  if (version === 10) {
10541    return isIE10;
10542  }
10543  return isIE11 || isIE10;
10544}
10545
10546/**
10547 * Returns the offset parent of the given element
10548 * @method
10549 * @memberof Popper.Utils
10550 * @argument {Element} element
10551 * @returns {Element} offset parent
10552 */
10553function getOffsetParent(element) {
10554  if (!element) {
10555    return document.documentElement;
10556  }
10557
10558  var noOffsetParent = isIE(10) ? document.body : null;
10559
10560  // NOTE: 1 DOM access here
10561  var offsetParent = element.offsetParent || null;
10562  // Skip hidden elements which don't have an offsetParent
10563  while (offsetParent === noOffsetParent && element.nextElementSibling) {
10564    offsetParent = (element = element.nextElementSibling).offsetParent;
10565  }
10566
10567  var nodeName = offsetParent && offsetParent.nodeName;
10568
10569  if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
10570    return element ? element.ownerDocument.documentElement : document.documentElement;
10571  }
10572
10573  // .offsetParent will return the closest TH, TD or TABLE in case
10574  // no offsetParent is present, I hate this job...
10575  if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
10576    return getOffsetParent(offsetParent);
10577  }
10578
10579  return offsetParent;
10580}
10581
10582function isOffsetContainer(element) {
10583  var nodeName = element.nodeName;
10584
10585  if (nodeName === 'BODY') {
10586    return false;
10587  }
10588  return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
10589}
10590
10591/**
10592 * Finds the root node (document, shadowDOM root) of the given element
10593 * @method
10594 * @memberof Popper.Utils
10595 * @argument {Element} node
10596 * @returns {Element} root node
10597 */
10598function getRoot(node) {
10599  if (node.parentNode !== null) {
10600    return getRoot(node.parentNode);
10601  }
10602
10603  return node;
10604}
10605
10606/**
10607 * Finds the offset parent common to the two provided nodes
10608 * @method
10609 * @memberof Popper.Utils
10610 * @argument {Element} element1
10611 * @argument {Element} element2
10612 * @returns {Element} common offset parent
10613 */
10614function findCommonOffsetParent(element1, element2) {
10615  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
10616  if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
10617    return document.documentElement;
10618  }
10619
10620  // Here we make sure to give as "start" the element that comes first in the DOM
10621  var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
10622  var start = order ? element1 : element2;
10623  var end = order ? element2 : element1;
10624
10625  // Get common ancestor container
10626  var range = document.createRange();
10627  range.setStart(start, 0);
10628  range.setEnd(end, 0);
10629  var commonAncestorContainer = range.commonAncestorContainer;
10630
vendor: 45,382 bytes, lines 10631-11978
10631  // Both nodes are inside #document
10632
10633  if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
10634    if (isOffsetContainer(commonAncestorContainer)) {
10635      return commonAncestorContainer;
10636    }
10637
10638    return getOffsetParent(commonAncestorContainer);
10639  }
10640
10641  // one of the nodes is inside shadowDOM, find which one
10642  var element1root = getRoot(element1);
10643  if (element1root.host) {
10644    return findCommonOffsetParent(element1root.host, element2);
10645  } else {
10646    return findCommonOffsetParent(element1, getRoot(element2).host);
10647  }
10648}
10649
10650/**
10651 * Gets the scroll value of the given element in the given side (top and left)
10652 * @method
10653 * @memberof Popper.Utils
10654 * @argument {Element} element
10655 * @argument {String} side `top` or `left`
10656 * @returns {number} amount of scrolled pixels
10657 */
10658function getScroll(element) {
10659  var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
10660
10661  var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
10662  var nodeName = element.nodeName;
10663
10664  if (nodeName === 'BODY' || nodeName === 'HTML') {
10665    var html = element.ownerDocument.documentElement;
10666    var scrollingElement = element.ownerDocument.scrollingElement || html;
10667    return scrollingElement[upperSide];
10668  }
10669
10670  return element[upperSide];
10671}
10672
10673/*
10674 * Sum or subtract the element scroll values (left and top) from a given rect object
10675 * @method
10676 * @memberof Popper.Utils
10677 * @param {Object} rect - Rect object you want to change
10678 * @param {HTMLElement} element - The element from the function reads the scroll values
10679 * @param {Boolean} subtract - set to true if you want to subtract the scroll values
10680 * @return {Object} rect - The modifier rect object
10681 */
10682function includeScroll(rect, element) {
10683  var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
10684
10685  var scrollTop = getScroll(element, 'top');
10686  var scrollLeft = getScroll(element, 'left');
10687  var modifier = subtract ? -1 : 1;
10688  rect.top += scrollTop * modifier;
10689  rect.bottom += scrollTop * modifier;
10690  rect.left += scrollLeft * modifier;
10691  rect.right += scrollLeft * modifier;
10692  return rect;
10693}
10694
10695/*
10696 * Helper to detect borders of a given element
10697 * @method
10698 * @memberof Popper.Utils
10699 * @param {CSSStyleDeclaration} styles
10700 * Result of `getStyleComputedProperty` on the given element
10701 * @param {String} axis - `x` or `y`
10702 * @return {number} borders - The borders size of the given axis
10703 */
10704
10705function getBordersSize(styles, axis) {
10706  var sideA = axis === 'x' ? 'Left' : 'Top';
10707  var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
10708
10709  return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
10710}
10711
10712function getSize(axis, body, html, computedStyle) {
10713  return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
10714}
10715
10716function getWindowSizes(document) {
10717  var body = document.body;
10718  var html = document.documentElement;
10719  var computedStyle = isIE(10) && getComputedStyle(html);
10720
10721  return {
10722    height: getSize('Height', body, html, computedStyle),
10723    width: getSize('Width', body, html, computedStyle)
10724  };
10725}
10726
10727var classCallCheck = function (instance, Constructor) {
10728  if (!(instance instanceof Constructor)) {
10729    throw new TypeError("Cannot call a class as a function");
10730  }
10731};
10732
10733var createClass = function () {
10734  function defineProperties(target, props) {
10735    for (var i = 0; i < props.length; i++) {
10736      var descriptor = props[i];
10737      descriptor.enumerable = descriptor.enumerable || false;
10738      descriptor.configurable = true;
10739      if ("value" in descriptor) descriptor.writable = true;
10740      Object.defineProperty(target, descriptor.key, descriptor);
10741    }
10742  }
10743
10744  return function (Constructor, protoProps, staticProps) {
10745    if (protoProps) defineProperties(Constructor.prototype, protoProps);
10746    if (staticProps) defineProperties(Constructor, staticProps);
10747    return Constructor;
10748  };
10749}();
10750
10751
10752
10753
10754
10755var defineProperty = function (obj, key, value) {
10756  if (key in obj) {
10757    Object.defineProperty(obj, key, {
10758      value: value,
10759      enumerable: true,
10760      configurable: true,
10761      writable: true
10762    });
10763  } else {
10764    obj[key] = value;
10765  }
10766
10767  return obj;
10768};
10769
10770var _extends = Object.assign || function (target) {
10771  for (var i = 1; i < arguments.length; i++) {
10772    var source = arguments[i];
10773
10774    for (var key in source) {
10775      if (Object.prototype.hasOwnProperty.call(source, key)) {
10776        target[key] = source[key];
10777      }
10778    }
10779  }
10780
10781  return target;
10782};
10783
10784/**
10785 * Given element offsets, generate an output similar to getBoundingClientRect
10786 * @method
10787 * @memberof Popper.Utils
10788 * @argument {Object} offsets
10789 * @returns {Object} ClientRect like output
10790 */
10791function getClientRect(offsets) {
10792  return _extends({}, offsets, {
10793    right: offsets.left + offsets.width,
10794    bottom: offsets.top + offsets.height
10795  });
10796}
10797
10798/**
10799 * Get bounding client rect of given element
10800 * @method
10801 * @memberof Popper.Utils
10802 * @param {HTMLElement} element
10803 * @return {Object} client rect
10804 */
10805function getBoundingClientRect(element) {
10806  var rect = {};
10807
10808  // IE10 10 FIX: Please, don't ask, the element isn't
10809  // considered in DOM in some circumstances...
10810  // This isn't reproducible in IE10 compatibility mode of IE11
10811  try {
10812    if (isIE(10)) {
10813      rect = element.getBoundingClientRect();
10814      var scrollTop = getScroll(element, 'top');
10815      var scrollLeft = getScroll(element, 'left');
10816      rect.top += scrollTop;
10817      rect.left += scrollLeft;
10818      rect.bottom += scrollTop;
10819      rect.right += scrollLeft;
10820    } else {
10821      rect = element.getBoundingClientRect();
10822    }
10823  } catch (e) {}
10824
10825  var result = {
10826    left: rect.left,
10827    top: rect.top,
10828    width: rect.right - rect.left,
10829    height: rect.bottom - rect.top
10830  };
10831
10832  // subtract scrollbar size from sizes
10833  var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
10834  var width = sizes.width || element.clientWidth || result.right - result.left;
10835  var height = sizes.height || element.clientHeight || result.bottom - result.top;
10836
10837  var horizScrollbar = element.offsetWidth - width;
10838  var vertScrollbar = element.offsetHeight - height;
10839
10840  // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
10841  // we make this check conditional for performance reasons
10842  if (horizScrollbar || vertScrollbar) {
10843    var styles = getStyleComputedProperty(element);
10844    horizScrollbar -= getBordersSize(styles, 'x');
10845    vertScrollbar -= getBordersSize(styles, 'y');
10846
10847    result.width -= horizScrollbar;
10848    result.height -= vertScrollbar;
10849  }
10850
10851  return getClientRect(result);
10852}
10853
10854function getOffsetRectRelativeToArbitraryNode(children, parent) {
10855  var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
10856
10857  var isIE10 = isIE(10);
10858  var isHTML = parent.nodeName === 'HTML';
10859  var childrenRect = getBoundingClientRect(children);
10860  var parentRect = getBoundingClientRect(parent);
10861  var scrollParent = getScrollParent(children);
10862
10863  var styles = getStyleComputedProperty(parent);
10864  var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
10865  var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
10866
10867  // In cases where the parent is fixed, we must ignore negative scroll in offset calc
10868  if (fixedPosition && isHTML) {
10869    parentRect.top = Math.max(parentRect.top, 0);
10870    parentRect.left = Math.max(parentRect.left, 0);
10871  }
10872  var offsets = getClientRect({
10873    top: childrenRect.top - parentRect.top - borderTopWidth,
10874    left: childrenRect.left - parentRect.left - borderLeftWidth,
10875    width: childrenRect.width,
10876    height: childrenRect.height
10877  });
10878  offsets.marginTop = 0;
10879  offsets.marginLeft = 0;
10880
10881  // Subtract margins of documentElement in case it's being used as parent
10882  // we do this only on HTML because it's the only element that behaves
10883  // differently when margins are applied to it. The margins are included in
10884  // the box of the documentElement, in the other cases not.
10885  if (!isIE10 && isHTML) {
10886    var marginTop = parseFloat(styles.marginTop, 10);
10887    var marginLeft = parseFloat(styles.marginLeft, 10);
10888
10889    offsets.top -= borderTopWidth - marginTop;
10890    offsets.bottom -= borderTopWidth - marginTop;
10891    offsets.left -= borderLeftWidth - marginLeft;
10892    offsets.right -= borderLeftWidth - marginLeft;
10893
10894    // Attach marginTop and marginLeft because in some circumstances we may need them
10895    offsets.marginTop = marginTop;
10896    offsets.marginLeft = marginLeft;
10897  }
10898
10899  if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
10900    offsets = includeScroll(offsets, parent);
10901  }
10902
10903  return offsets;
10904}
10905
10906function getViewportOffsetRectRelativeToArtbitraryNode(element) {
10907  var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
10908
10909  var html = element.ownerDocument.documentElement;
10910  var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
10911  var width = Math.max(html.clientWidth, window.innerWidth || 0);
10912  var height = Math.max(html.clientHeight, window.innerHeight || 0);
10913
10914  var scrollTop = !excludeScroll ? getScroll(html) : 0;
10915  var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
10916
10917  var offset = {
10918    top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
10919    left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
10920    width: width,
10921    height: height
10922  };
10923
10924  return getClientRect(offset);
10925}
10926
10927/**
10928 * Check if the given element is fixed or is inside a fixed parent
10929 * @method
10930 * @memberof Popper.Utils
10931 * @argument {Element} element
10932 * @argument {Element} customContainer
10933 * @returns {Boolean} answer to "isFixed?"
10934 */
10935function isFixed(element) {
10936  var nodeName = element.nodeName;
10937  if (nodeName === 'BODY' || nodeName === 'HTML') {
10938    return false;
10939  }
10940  if (getStyleComputedProperty(element, 'position') === 'fixed') {
10941    return true;
10942  }
10943  var parentNode = getParentNode(element);
10944  if (!parentNode) {
10945    return false;
10946  }
10947  return isFixed(parentNode);
10948}
10949
10950/**
10951 * Finds the first parent of an element that has a transformed property defined
10952 * @method
10953 * @memberof Popper.Utils
10954 * @argument {Element} element
10955 * @returns {Element} first transformed parent or documentElement
10956 */
10957
10958function getFixedPositionOffsetParent(element) {
10959  // This check is needed to avoid errors in case one of the elements isn't defined for any reason
10960  if (!element || !element.parentElement || isIE()) {
10961    return document.documentElement;
10962  }
10963  var el = element.parentElement;
10964  while (el && getStyleComputedProperty(el, 'transform') === 'none') {
10965    el = el.parentElement;
10966  }
10967  return el || document.documentElement;
10968}
10969
10970/**
10971 * Computed the boundaries limits and return them
10972 * @method
10973 * @memberof Popper.Utils
10974 * @param {HTMLElement} popper
10975 * @param {HTMLElement} reference
10976 * @param {number} padding
10977 * @param {HTMLElement} boundariesElement - Element used to define the boundaries
10978 * @param {Boolean} fixedPosition - Is in fixed position mode
10979 * @returns {Object} Coordinates of the boundaries
10980 */
10981function getBoundaries(popper, reference, padding, boundariesElement) {
10982  var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
10983
10984  // NOTE: 1 DOM access here
10985
10986  var boundaries = { top: 0, left: 0 };
10987  var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
10988
10989  // Handle viewport case
10990  if (boundariesElement === 'viewport') {
10991    boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
10992  } else {
10993    // Handle other cases based on DOM element used as boundaries
10994    var boundariesNode = void 0;
10995    if (boundariesElement === 'scrollParent') {
10996      boundariesNode = getScrollParent(getParentNode(reference));
10997      if (boundariesNode.nodeName === 'BODY') {
10998        boundariesNode = popper.ownerDocument.documentElement;
10999      }
11000    } else if (boundariesElement === 'window') {
11001      boundariesNode = popper.ownerDocument.documentElement;
11002    } else {
11003      boundariesNode = boundariesElement;
11004    }
11005
11006    var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);
11007
11008    // In case of HTML, we need a different computation
11009    if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
11010      var _getWindowSizes = getWindowSizes(popper.ownerDocument),
11011          height = _getWindowSizes.height,
11012          width = _getWindowSizes.width;
11013
11014      boundaries.top += offsets.top - offsets.marginTop;
11015      boundaries.bottom = height + offsets.top;
11016      boundaries.left += offsets.left - offsets.marginLeft;
11017      boundaries.right = width + offsets.left;
11018    } else {
11019      // for all the other DOM elements, this one is good
11020      boundaries = offsets;
11021    }
11022  }
11023
11024  // Add paddings
11025  padding = padding || 0;
11026  var isPaddingNumber = typeof padding === 'number';
11027  boundaries.left += isPaddingNumber ? padding : padding.left || 0;
11028  boundaries.top += isPaddingNumber ? padding : padding.top || 0;
11029  boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
11030  boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
11031
11032  return boundaries;
11033}
11034
11035function getArea(_ref) {
11036  var width = _ref.width,
11037      height = _ref.height;
11038
11039  return width * height;
11040}
11041
11042/**
11043 * Utility used to transform the `auto` placement to the placement with more
11044 * available space.
11045 * @method
11046 * @memberof Popper.Utils
11047 * @argument {Object} data - The data object generated by update method
11048 * @argument {Object} options - Modifiers configuration and options
11049 * @returns {Object} The data object, properly modified
11050 */
11051function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
11052  var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
11053
11054  if (placement.indexOf('auto') === -1) {
11055    return placement;
11056  }
11057
11058  var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
11059
11060  var rects = {
11061    top: {
11062      width: boundaries.width,
11063      height: refRect.top - boundaries.top
11064    },
11065    right: {
11066      width: boundaries.right - refRect.right,
11067      height: boundaries.height
11068    },
11069    bottom: {
11070      width: boundaries.width,
11071      height: boundaries.bottom - refRect.bottom
11072    },
11073    left: {
11074      width: refRect.left - boundaries.left,
11075      height: boundaries.height
11076    }
11077  };
11078
11079  var sortedAreas = Object.keys(rects).map(function (key) {
11080    return _extends({
11081      key: key
11082    }, rects[key], {
11083      area: getArea(rects[key])
11084    });
11085  }).sort(function (a, b) {
11086    return b.area - a.area;
11087  });
11088
11089  var filteredAreas = sortedAreas.filter(function (_ref2) {
11090    var width = _ref2.width,
11091        height = _ref2.height;
11092    return width >= popper.clientWidth && height >= popper.clientHeight;
11093  });
11094
11095  var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
11096
11097  var variation = placement.split('-')[1];
11098
11099  return computedPlacement + (variation ? '-' + variation : '');
11100}
11101
11102/**
11103 * Get offsets to the reference element
11104 * @method
11105 * @memberof Popper.Utils
11106 * @param {Object} state
11107 * @param {Element} popper - the popper element
11108 * @param {Element} reference - the reference element (the popper will be relative to this)
11109 * @param {Element} fixedPosition - is in fixed position mode
11110 * @returns {Object} An object containing the offsets which will be applied to the popper
11111 */
11112function getReferenceOffsets(state, popper, reference) {
11113  var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
11114
11115  var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
11116  return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
11117}
11118
11119/**
11120 * Get the outer sizes of the given element (offset size + margins)
11121 * @method
11122 * @memberof Popper.Utils
11123 * @argument {Element} element
11124 * @returns {Object} object containing width and height properties
11125 */
11126function getOuterSizes(element) {
11127  var window = element.ownerDocument.defaultView;
11128  var styles = window.getComputedStyle(element);
11129  var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
11130  var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
11131  var result = {
11132    width: element.offsetWidth + y,
11133    height: element.offsetHeight + x
11134  };
11135  return result;
11136}
11137
11138/**
11139 * Get the opposite placement of the given one
11140 * @method
11141 * @memberof Popper.Utils
11142 * @argument {String} placement
11143 * @returns {String} flipped placement
11144 */
11145function getOppositePlacement(placement) {
11146  var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
11147  return placement.replace(/left|right|bottom|top/g, function (matched) {
11148    return hash[matched];
11149  });
11150}
11151
11152/**
11153 * Get offsets to the popper
11154 * @method
11155 * @memberof Popper.Utils
11156 * @param {Object} position - CSS position the Popper will get applied
11157 * @param {HTMLElement} popper - the popper element
11158 * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
11159 * @param {String} placement - one of the valid placement options
11160 * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
11161 */
11162function getPopperOffsets(popper, referenceOffsets, placement) {
11163  placement = placement.split('-')[0];
11164
11165  // Get popper node sizes
11166  var popperRect = getOuterSizes(popper);
11167
11168  // Add position, width and height to our offsets object
11169  var popperOffsets = {
11170    width: popperRect.width,
11171    height: popperRect.height
11172  };
11173
11174  // depending by the popper placement we have to compute its offsets slightly differently
11175  var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
11176  var mainSide = isHoriz ? 'top' : 'left';
11177  var secondarySide = isHoriz ? 'left' : 'top';
11178  var measurement = isHoriz ? 'height' : 'width';
11179  var secondaryMeasurement = !isHoriz ? 'height' : 'width';
11180
11181  popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
11182  if (placement === secondarySide) {
11183    popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
11184  } else {
11185    popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
11186  }
11187
11188  return popperOffsets;
11189}
11190
11191/**
11192 * Mimics the `find` method of Array
11193 * @method
11194 * @memberof Popper.Utils
11195 * @argument {Array} arr
11196 * @argument prop
11197 * @argument value
11198 * @returns index or -1
11199 */
11200function find(arr, check) {
11201  // use native find if supported
11202  if (Array.prototype.find) {
11203    return arr.find(check);
11204  }
11205
11206  // use `filter` to obtain the same behavior of `find`
11207  return arr.filter(check)[0];
11208}
11209
11210/**
11211 * Return the index of the matching object
11212 * @method
11213 * @memberof Popper.Utils
11214 * @argument {Array} arr
11215 * @argument prop
11216 * @argument value
11217 * @returns index or -1
11218 */
11219function findIndex(arr, prop, value) {
11220  // use native findIndex if supported
11221  if (Array.prototype.findIndex) {
11222    return arr.findIndex(function (cur) {
11223      return cur[prop] === value;
11224    });
11225  }
11226
11227  // use `find` + `indexOf` if `findIndex` isn't supported
11228  var match = find(arr, function (obj) {
11229    return obj[prop] === value;
11230  });
11231  return arr.indexOf(match);
11232}
11233
11234/**
11235 * Loop trough the list of modifiers and run them in order,
11236 * each of them will then edit the data object.
11237 * @method
11238 * @memberof Popper.Utils
11239 * @param {dataObject} data
11240 * @param {Array} modifiers
11241 * @param {String} ends - Optional modifier name used as stopper
11242 * @returns {dataObject}
11243 */
11244function runModifiers(modifiers, data, ends) {
11245  var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
11246
11247  modifiersToRun.forEach(function (modifier) {
11248    if (modifier['function']) {
11249      // eslint-disable-line dot-notation
11250      console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
11251    }
11252    var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
11253    if (modifier.enabled && isFunction(fn)) {
11254      // Add properties to offsets to make them a complete clientRect object
11255      // we do this before each modifier to make sure the previous one doesn't
11256      // mess with these values
11257      data.offsets.popper = getClientRect(data.offsets.popper);
11258      data.offsets.reference = getClientRect(data.offsets.reference);
11259
11260      data = fn(data, modifier);
11261    }
11262  });
11263
11264  return data;
11265}
11266
11267/**
11268 * Updates the position of the popper, computing the new offsets and applying
11269 * the new style.<br />
11270 * Prefer `scheduleUpdate` over `update` because of performance reasons.
11271 * @method
11272 * @memberof Popper
11273 */
11274function update() {
11275  // if popper is destroyed, don't perform any further update
11276  if (this.state.isDestroyed) {
11277    return;
11278  }
11279
11280  var data = {
11281    instance: this,
11282    styles: {},
11283    arrowStyles: {},
11284    attributes: {},
11285    flipped: false,
11286    offsets: {}
11287  };
11288
11289  // compute reference element offsets
11290  data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);
11291
11292  // compute auto placement, store placement inside the data object,
11293  // modifiers will be able to edit `placement` if needed
11294  // and refer to originalPlacement to know the original value
11295  data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
11296
11297  // store the computed placement inside `originalPlacement`
11298  data.originalPlacement = data.placement;
11299
11300  data.positionFixed = this.options.positionFixed;
11301
11302  // compute the popper offsets
11303  data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
11304
11305  data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';
11306
11307  // run the modifiers
11308  data = runModifiers(this.modifiers, data);
11309
11310  // the first `update` will call `onCreate` callback
11311  // the other ones will call `onUpdate` callback
11312  if (!this.state.isCreated) {
11313    this.state.isCreated = true;
11314    this.options.onCreate(data);
11315  } else {
11316    this.options.onUpdate(data);
11317  }
11318}
11319
11320/**
11321 * Helper used to know if the given modifier is enabled.
11322 * @method
11323 * @memberof Popper.Utils
11324 * @returns {Boolean}
11325 */
11326function isModifierEnabled(modifiers, modifierName) {
11327  return modifiers.some(function (_ref) {
11328    var name = _ref.name,
11329        enabled = _ref.enabled;
11330    return enabled && name === modifierName;
11331  });
11332}
11333
11334/**
11335 * Get the prefixed supported property name
11336 * @method
11337 * @memberof Popper.Utils
11338 * @argument {String} property (camelCase)
11339 * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
11340 */
11341function getSupportedPropertyName(property) {
11342  var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
11343  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
11344
11345  for (var i = 0; i < prefixes.length; i++) {
11346    var prefix = prefixes[i];
11347    var toCheck = prefix ? '' + prefix + upperProp : property;
11348    if (typeof document.body.style[toCheck] !== 'undefined') {
11349      return toCheck;
11350    }
11351  }
11352  return null;
11353}
11354
11355/**
11356 * Destroys the popper.
11357 * @method
11358 * @memberof Popper
11359 */
11360function destroy() {
11361  this.state.isDestroyed = true;
11362
11363  // touch DOM only if `applyStyle` modifier is enabled
11364  if (isModifierEnabled(this.modifiers, 'applyStyle')) {
11365    this.popper.removeAttribute('x-placement');
11366    this.popper.style.position = '';
11367    this.popper.style.top = '';
11368    this.popper.style.left = '';
11369    this.popper.style.right = '';
11370    this.popper.style.bottom = '';
11371    this.popper.style.willChange = '';
11372    this.popper.style[getSupportedPropertyName('transform')] = '';
11373  }
11374
11375  this.disableEventListeners();
11376
11377  // remove the popper if user explicity asked for the deletion on destroy
11378  // do not use `remove` because IE11 doesn't support it
11379  if (this.options.removeOnDestroy) {
11380    this.popper.parentNode.removeChild(this.popper);
11381  }
11382  return this;
11383}
11384
11385/**
11386 * Get the window associated with the element
11387 * @argument {Element} element
11388 * @returns {Window}
11389 */
11390function getWindow(element) {
11391  var ownerDocument = element.ownerDocument;
11392  return ownerDocument ? ownerDocument.defaultView : window;
11393}
11394
11395function attachToScrollParents(scrollParent, event, callback, scrollParents) {
11396  var isBody = scrollParent.nodeName === 'BODY';
11397  var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
11398  target.addEventListener(event, callback, { passive: true });
11399
11400  if (!isBody) {
11401    attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
11402  }
11403  scrollParents.push(target);
11404}
11405
11406/**
11407 * Setup needed event listeners used to update the popper position
11408 * @method
11409 * @memberof Popper.Utils
11410 * @private
11411 */
11412function setupEventListeners(reference, options, state, updateBound) {
11413  // Resize event listener on window
11414  state.updateBound = updateBound;
11415  getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
11416
11417  // Scroll event listener on scroll parents
11418  var scrollElement = getScrollParent(reference);
11419  attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
11420  state.scrollElement = scrollElement;
11421  state.eventsEnabled = true;
11422
11423  return state;
11424}
11425
11426/**
11427 * It will add resize/scroll events and start recalculating
11428 * position of the popper element when they are triggered.
11429 * @method
11430 * @memberof Popper
11431 */
11432function enableEventListeners() {
11433  if (!this.state.eventsEnabled) {
11434    this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
11435  }
11436}
11437
11438/**
11439 * Remove event listeners used to update the popper position
11440 * @method
11441 * @memberof Popper.Utils
11442 * @private
11443 */
11444function removeEventListeners(reference, state) {
11445  // Remove resize event listener on window
11446  getWindow(reference).removeEventListener('resize', state.updateBound);
11447
11448  // Remove scroll event listener on scroll parents
11449  state.scrollParents.forEach(function (target) {
11450    target.removeEventListener('scroll', state.updateBound);
11451  });
11452
11453  // Reset state
11454  state.updateBound = null;
11455  state.scrollParents = [];
11456  state.scrollElement = null;
11457  state.eventsEnabled = false;
11458  return state;
11459}
11460
11461/**
11462 * It will remove resize/scroll events and won't recalculate popper position
11463 * when they are triggered. It also won't trigger `onUpdate` callback anymore,
11464 * unless you call `update` method manually.
11465 * @method
11466 * @memberof Popper
11467 */
11468function disableEventListeners() {
11469  if (this.state.eventsEnabled) {
11470    cancelAnimationFrame(this.scheduleUpdate);
11471    this.state = removeEventListeners(this.reference, this.state);
11472  }
11473}
11474
11475/**
11476 * Tells if a given input is a number
11477 * @method
11478 * @memberof Popper.Utils
11479 * @param {*} input to check
11480 * @return {Boolean}
11481 */
11482function isNumeric(n) {
11483  return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
11484}
11485
11486/**
11487 * Set the style to the given popper
11488 * @method
11489 * @memberof Popper.Utils
11490 * @argument {Element} element - Element to apply the style to
11491 * @argument {Object} styles
11492 * Object with a list of properties and values which will be applied to the element
11493 */
11494function setStyles(element, styles) {
11495  Object.keys(styles).forEach(function (prop) {
11496    var unit = '';
11497    // add unit if the value is numeric and is one of the following
11498    if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
11499      unit = 'px';
11500    }
11501    element.style[prop] = styles[prop] + unit;
11502  });
11503}
11504
11505/**
11506 * Set the attributes to the given popper
11507 * @method
11508 * @memberof Popper.Utils
11509 * @argument {Element} element - Element to apply the attributes to
11510 * @argument {Object} styles
11511 * Object with a list of properties and values which will be applied to the element
11512 */
11513function setAttributes(element, attributes) {
11514  Object.keys(attributes).forEach(function (prop) {
11515    var value = attributes[prop];
11516    if (value !== false) {
11517      element.setAttribute(prop, attributes[prop]);
11518    } else {
11519      element.removeAttribute(prop);
11520    }
11521  });
11522}
11523
11524/**
11525 * @function
11526 * @memberof Modifiers
11527 * @argument {Object} data - The data object generated by `update` method
11528 * @argument {Object} data.styles - List of style properties - values to apply to popper element
11529 * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
11530 * @argument {Object} options - Modifiers configuration and options
11531 * @returns {Object} The same data object
11532 */
11533function applyStyle(data) {
11534  // any property present in `data.styles` will be applied to the popper,
11535  // in this way we can make the 3rd party modifiers add custom styles to it
11536  // Be aware, modifiers could override the properties defined in the previous
11537  // lines of this modifier!
11538  setStyles(data.instance.popper, data.styles);
11539
11540  // any property present in `data.attributes` will be applied to the popper,
11541  // they will be set as HTML attributes of the element
11542  setAttributes(data.instance.popper, data.attributes);
11543
11544  // if arrowElement is defined and arrowStyles has some properties
11545  if (data.arrowElement && Object.keys(data.arrowStyles).length) {
11546    setStyles(data.arrowElement, data.arrowStyles);
11547  }
11548
11549  return data;
11550}
11551
11552/**
11553 * Set the x-placement attribute before everything else because it could be used
11554 * to add margins to the popper margins needs to be calculated to get the
11555 * correct popper offsets.
11556 * @method
11557 * @memberof Popper.modifiers
11558 * @param {HTMLElement} reference - The reference element used to position the popper
11559 * @param {HTMLElement} popper - The HTML element used as popper
11560 * @param {Object} options - Popper.js options
11561 */
11562function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
11563  // compute reference element offsets
11564  var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);
11565
11566  // compute auto placement, store placement inside the data object,
11567  // modifiers will be able to edit `placement` if needed
11568  // and refer to originalPlacement to know the original value
11569  var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
11570
11571  popper.setAttribute('x-placement', placement);
11572
11573  // Apply `position` to popper before anything else because
11574  // without the position applied we can't guarantee correct computations
11575  setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });
11576
11577  return options;
11578}
11579
11580/**
11581 * @function
11582 * @memberof Popper.Utils
11583 * @argument {Object} data - The data object generated by `update` method
11584 * @argument {Boolean} shouldRound - If the offsets should be rounded at all
11585 * @returns {Object} The popper's position offsets rounded
11586 *
11587 * The tale of pixel-perfect positioning. It's still not 100% perfect, but as
11588 * good as it can be within reason.
11589 * Discussion here: https://github.com/FezVrasta/popper.js/pull/715
11590 *
11591 * Low DPI screens cause a popper to be blurry if not using full pixels (Safari
11592 * as well on High DPI screens).
11593 *
11594 * Firefox prefers no rounding for positioning and does not have blurriness on
11595 * high DPI screens.
11596 *
11597 * Only horizontal placement and left/right values need to be considered.
11598 */
11599function getRoundedOffsets(data, shouldRound) {
11600  var _data$offsets = data.offsets,
11601      popper = _data$offsets.popper,
11602      reference = _data$offsets.reference;
11603  var round = Math.round,
11604      floor = Math.floor;
11605
11606  var noRound = function noRound(v) {
11607    return v;
11608  };
11609
11610  var referenceWidth = round(reference.width);
11611  var popperWidth = round(popper.width);
11612
11613  var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
11614  var isVariation = data.placement.indexOf('-') !== -1;
11615  var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
11616  var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
11617
11618  var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
11619  var verticalToInteger = !shouldRound ? noRound : round;
11620
11621  return {
11622    left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
11623    top: verticalToInteger(popper.top),
11624    bottom: verticalToInteger(popper.bottom),
11625    right: horizontalToInteger(popper.right)
11626  };
11627}
11628
11629var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
11630
11631/**
11632 * @function
11633 * @memberof Modifiers
11634 * @argument {Object} data - The data object generated by `update` method
11635 * @argument {Object} options - Modifiers configuration and options
11636 * @returns {Object} The data object, properly modified
11637 */
11638function computeStyle(data, options) {
11639  var x = options.x,
11640      y = options.y;
11641  var popper = data.offsets.popper;
11642
11643  // Remove this legacy support in Popper.js v2
11644
11645  var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
11646    return modifier.name === 'applyStyle';
11647  }).gpuAcceleration;
11648  if (legacyGpuAccelerationOption !== undefined) {
11649    console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
11650  }
11651  var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
11652
11653  var offsetParent = getOffsetParent(data.instance.popper);
11654  var offsetParentRect = getBoundingClientRect(offsetParent);
11655
11656  // Styles
11657  var styles = {
11658    position: popper.position
11659  };
11660
11661  var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
11662
11663  var sideA = x === 'bottom' ? 'top' : 'bottom';
11664  var sideB = y === 'right' ? 'left' : 'right';
11665
11666  // if gpuAcceleration is set to `true` and transform is supported,
11667  //  we use `translate3d` to apply the position to the popper we
11668  // automatically use the supported prefixed version if needed
11669  var prefixedProperty = getSupportedPropertyName('transform');
11670
11671  // now, let's make a step back and look at this code closely (wtf?)
11672  // If the content of the popper grows once it's been positioned, it
11673  // may happen that the popper gets misplaced because of the new content
11674  // overflowing its reference element
11675  // To avoid this problem, we provide two options (x and y), which allow
11676  // the consumer to define the offset origin.
11677  // If we position a popper on top of a reference element, we can set
11678  // `x` to `top` to make the popper grow towards its top instead of
11679  // its bottom.
11680  var left = void 0,
11681      top = void 0;
11682  if (sideA === 'bottom') {
11683    // when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
11684    // and not the bottom of the html element
11685    if (offsetParent.nodeName === 'HTML') {
11686      top = -offsetParent.clientHeight + offsets.bottom;
11687    } else {
11688      top = -offsetParentRect.height + offsets.bottom;
11689    }
11690  } else {
11691    top = offsets.top;
11692  }
11693  if (sideB === 'right') {
11694    if (offsetParent.nodeName === 'HTML') {
11695      left = -offsetParent.clientWidth + offsets.right;
11696    } else {
11697      left = -offsetParentRect.width + offsets.right;
11698    }
11699  } else {
11700    left = offsets.left;
11701  }
11702  if (gpuAcceleration && prefixedProperty) {
11703    styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
11704    styles[sideA] = 0;
11705    styles[sideB] = 0;
11706    styles.willChange = 'transform';
11707  } else {
11708    // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
11709    var invertTop = sideA === 'bottom' ? -1 : 1;
11710    var invertLeft = sideB === 'right' ? -1 : 1;
11711    styles[sideA] = top * invertTop;
11712    styles[sideB] = left * invertLeft;
11713    styles.willChange = sideA + ', ' + sideB;
11714  }
11715
11716  // Attributes
11717  var attributes = {
11718    'x-placement': data.placement
11719  };
11720
11721  // Update `data` attributes, styles and arrowStyles
11722  data.attributes = _extends({}, attributes, data.attributes);
11723  data.styles = _extends({}, styles, data.styles);
11724  data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
11725
11726  return data;
11727}
11728
11729/**
11730 * Helper used to know if the given modifier depends from another one.<br />
11731 * It checks if the needed modifier is listed and enabled.
11732 * @method
11733 * @memberof Popper.Utils
11734 * @param {Array} modifiers - list of modifiers
11735 * @param {String} requestingName - name of requesting modifier
11736 * @param {String} requestedName - name of requested modifier
11737 * @returns {Boolean}
11738 */
11739function isModifierRequired(modifiers, requestingName, requestedName) {
11740  var requesting = find(modifiers, function (_ref) {
11741    var name = _ref.name;
11742    return name === requestingName;
11743  });
11744
11745  var isRequired = !!requesting && modifiers.some(function (modifier) {
11746    return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
11747  });
11748
11749  if (!isRequired) {
11750    var _requesting = '`' + requestingName + '`';
11751    var requested = '`' + requestedName + '`';
11752    console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
11753  }
11754  return isRequired;
11755}
11756
11757/**
11758 * @function
11759 * @memberof Modifiers
11760 * @argument {Object} data - The data object generated by update method
11761 * @argument {Object} options - Modifiers configuration and options
11762 * @returns {Object} The data object, properly modified
11763 */
11764function arrow(data, options) {
11765  var _data$offsets$arrow;
11766
11767  // arrow depends on keepTogether in order to work
11768  if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
11769    return data;
11770  }
11771
11772  var arrowElement = options.element;
11773
11774  // if arrowElement is a string, suppose it's a CSS selector
11775  if (typeof arrowElement === 'string') {
11776    arrowElement = data.instance.popper.querySelector(arrowElement);
11777
11778    // if arrowElement is not found, don't run the modifier
11779    if (!arrowElement) {
11780      return data;
11781    }
11782  } else {
11783    // if the arrowElement isn't a query selector we must check that the
11784    // provided DOM node is child of its popper node
11785    if (!data.instance.popper.contains(arrowElement)) {
11786      console.warn('WARNING: `arrow.element` must be child of its popper element!');
11787      return data;
11788    }
11789  }
11790
11791  var placement = data.placement.split('-')[0];
11792  var _data$offsets = data.offsets,
11793      popper = _data$offsets.popper,
11794      reference = _data$offsets.reference;
11795
11796  var isVertical = ['left', 'right'].indexOf(placement) !== -1;
11797
11798  var len = isVertical ? 'height' : 'width';
11799  var sideCapitalized = isVertical ? 'Top' : 'Left';
11800  var side = sideCapitalized.toLowerCase();
11801  var altSide = isVertical ? 'left' : 'top';
11802  var opSide = isVertical ? 'bottom' : 'right';
11803  var arrowElementSize = getOuterSizes(arrowElement)[len];
11804
11805  //
11806  // extends keepTogether behavior making sure the popper and its
11807  // reference have enough pixels in conjunction
11808  //
11809
11810  // top/left side
11811  if (reference[opSide] - arrowElementSize < popper[side]) {
11812    data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
11813  }
11814  // bottom/right side
11815  if (reference[side] + arrowElementSize > popper[opSide]) {
11816    data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
11817  }
11818  data.offsets.popper = getClientRect(data.offsets.popper);
11819
11820  // compute center of the popper
11821  var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
11822
11823  // Compute the sideValue using the updated popper offsets
11824  // take popper margin in account because we don't have this info available
11825  var css = getStyleComputedProperty(data.instance.popper);
11826  var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
11827  var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
11828  var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
11829
11830  // prevent arrowElement from being placed not contiguously to its popper
11831  sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
11832
11833  data.arrowElement = arrowElement;
11834  data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
11835
11836  return data;
11837}
11838
11839/**
11840 * Get the opposite placement variation of the given one
11841 * @method
11842 * @memberof Popper.Utils
11843 * @argument {String} placement variation
11844 * @returns {String} flipped placement variation
11845 */
11846function getOppositeVariation(variation) {
11847  if (variation === 'end') {
11848    return 'start';
11849  } else if (variation === 'start') {
11850    return 'end';
11851  }
11852  return variation;
11853}
11854
11855/**
11856 * List of accepted placements to use as values of the `placement` option.<br />
11857 * Valid placements are:
11858 * - `auto`
11859 * - `top`
11860 * - `right`
11861 * - `bottom`
11862 * - `left`
11863 *
11864 * Each placement can have a variation from this list:
11865 * - `-start`
11866 * - `-end`
11867 *
11868 * Variations are interpreted easily if you think of them as the left to right
11869 * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
11870 * is right.<br />
11871 * Vertically (`left` and `right`), `start` is top and `end` is bottom.
11872 *
11873 * Some valid examples are:
11874 * - `top-end` (on top of reference, right aligned)
11875 * - `right-start` (on right of reference, top aligned)
11876 * - `bottom` (on bottom, centered)
11877 * - `auto-end` (on the side with more space available, alignment depends by placement)
11878 *
11879 * @static
11880 * @type {Array}
11881 * @enum {String}
11882 * @readonly
11883 * @method placements
11884 * @memberof Popper
11885 */
11886var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];
11887
11888// Get rid of `auto` `auto-start` and `auto-end`
11889var validPlacements = placements.slice(3);
11890
11891/**
11892 * Given an initial placement, returns all the subsequent placements
11893 * clockwise (or counter-clockwise).
11894 *
11895 * @method
11896 * @memberof Popper.Utils
11897 * @argument {String} placement - A valid placement (it accepts variations)
11898 * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
11899 * @returns {Array} placements including their variations
11900 */
11901function clockwise(placement) {
11902  var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
11903
11904  var index = validPlacements.indexOf(placement);
11905  var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
11906  return counter ? arr.reverse() : arr;
11907}
11908
11909var BEHAVIORS = {
11910  FLIP: 'flip',
11911  CLOCKWISE: 'clockwise',
11912  COUNTERCLOCKWISE: 'counterclockwise'
11913};
11914
11915/**
11916 * @function
11917 * @memberof Modifiers
11918 * @argument {Object} data - The data object generated by update method
11919 * @argument {Object} options - Modifiers configuration and options
11920 * @returns {Object} The data object, properly modified
11921 */
11922function flip(data, options) {
11923  // if `inner` modifier is enabled, we can't use the `flip` modifier
11924  if (isModifierEnabled(data.instance.modifiers, 'inner')) {
11925    return data;
11926  }
11927
11928  if (data.flipped && data.placement === data.originalPlacement) {
11929    // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
11930    return data;
11931  }
11932
11933  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
11934
11935  var placement = data.placement.split('-')[0];
11936  var placementOpposite = getOppositePlacement(placement);
11937  var variation = data.placement.split('-')[1] || '';
11938
11939  var flipOrder = [];
11940
11941  switch (options.behavior) {
11942    case BEHAVIORS.FLIP:
11943      flipOrder = [placement, placementOpposite];
11944      break;
11945    case BEHAVIORS.CLOCKWISE:
11946      flipOrder = clockwise(placement);
11947      break;
11948    case BEHAVIORS.COUNTERCLOCKWISE:
11949      flipOrder = clockwise(placement, true);
11950      break;
11951    default:
11952      flipOrder = options.behavior;
11953  }
11954
11955  flipOrder.forEach(function (step, index) {
11956    if (placement !== step || flipOrder.length === index + 1) {
11957      return data;
11958    }
11959
11960    placement = data.placement.split('-')[0];
11961    placementOpposite = getOppositePlacement(placement);
11962
11963    var popperOffsets = data.offsets.popper;
11964    var refOffsets = data.offsets.reference;
11965
11966    // using floor because the reference offsets may contain decimals we are not going to consider here
11967    var floor = Math.floor;
11968    var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
11969
11970    var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
11971    var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
11972    var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
11973    var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
11974
11975    var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
11976
11977    // flip the variation if required
11978    var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
11979    var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom)
vendor: 21,083 bytes, lines 11979-12586
11979;
11980
11981    if (overlapsRef || overflowsBoundaries || flippedVariation) {
11982      // this boolean to detect any flip loop
11983      data.flipped = true;
11984
11985      if (overlapsRef || overflowsBoundaries) {
11986        placement = flipOrder[index + 1];
11987      }
11988
11989      if (flippedVariation) {
11990        variation = getOppositeVariation(variation);
11991      }
11992
11993      data.placement = placement + (variation ? '-' + variation : '');
11994
11995      // this object contains `position`, we want to preserve it along with
11996      // any additional property we may add in the future
11997      data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
11998
11999      data = runModifiers(data.instance.modifiers, data, 'flip');
12000    }
12001  });
12002  return data;
12003}
12004
12005/**
12006 * @function
12007 * @memberof Modifiers
12008 * @argument {Object} data - The data object generated by update method
12009 * @argument {Object} options - Modifiers configuration and options
12010 * @returns {Object} The data object, properly modified
12011 */
12012function keepTogether(data) {
12013  var _data$offsets = data.offsets,
12014      popper = _data$offsets.popper,
12015      reference = _data$offsets.reference;
12016
12017  var placement = data.placement.split('-')[0];
12018  var floor = Math.floor;
12019  var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
12020  var side = isVertical ? 'right' : 'bottom';
12021  var opSide = isVertical ? 'left' : 'top';
12022  var measurement = isVertical ? 'width' : 'height';
12023
12024  if (popper[side] < floor(reference[opSide])) {
12025    data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
12026  }
12027  if (popper[opSide] > floor(reference[side])) {
12028    data.offsets.popper[opSide] = floor(reference[side]);
12029  }
12030
12031  return data;
12032}
12033
12034/**
12035 * Converts a string containing value + unit into a px value number
12036 * @function
12037 * @memberof {modifiers~offset}
12038 * @private
12039 * @argument {String} str - Value + unit string
12040 * @argument {String} measurement - `height` or `width`
12041 * @argument {Object} popperOffsets
12042 * @argument {Object} referenceOffsets
12043 * @returns {Number|String}
12044 * Value in pixels, or original string if no values were extracted
12045 */
12046function toValue(str, measurement, popperOffsets, referenceOffsets) {
12047  // separate value from unit
12048  var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
12049  var value = +split[1];
12050  var unit = split[2];
12051
12052  // If it's not a number it's an operator, I guess
12053  if (!value) {
12054    return str;
12055  }
12056
12057  if (unit.indexOf('%') === 0) {
12058    var element = void 0;
12059    switch (unit) {
12060      case '%p':
12061        element = popperOffsets;
12062        break;
12063      case '%':
12064      case '%r':
12065      default:
12066        element = referenceOffsets;
12067    }
12068
12069    var rect = getClientRect(element);
12070    return rect[measurement] / 100 * value;
12071  } else if (unit === 'vh' || unit === 'vw') {
12072    // if is a vh or vw, we calculate the size based on the viewport
12073    var size = void 0;
12074    if (unit === 'vh') {
12075      size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
12076    } else {
12077      size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
12078    }
12079    return size / 100 * value;
12080  } else {
12081    // if is an explicit pixel unit, we get rid of the unit and keep the value
12082    // if is an implicit unit, it's px, and we return just the value
12083    return value;
12084  }
12085}
12086
12087/**
12088 * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
12089 * @function
12090 * @memberof {modifiers~offset}
12091 * @private
12092 * @argument {String} offset
12093 * @argument {Object} popperOffsets
12094 * @argument {Object} referenceOffsets
12095 * @argument {String} basePlacement
12096 * @returns {Array} a two cells array with x and y offsets in numbers
12097 */
12098function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
12099  var offsets = [0, 0];
12100
12101  // Use height if placement is left or right and index is 0 otherwise use width
12102  // in this way the first offset will use an axis and the second one
12103  // will use the other one
12104  var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
12105
12106  // Split the offset string to obtain a list of values and operands
12107  // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
12108  var fragments = offset.split(/(\+|\-)/).map(function (frag) {
12109    return frag.trim();
12110  });
12111
12112  // Detect if the offset string contains a pair of values or a single one
12113  // they could be separated by comma or space
12114  var divider = fragments.indexOf(find(fragments, function (frag) {
12115    return frag.search(/,|\s/) !== -1;
12116  }));
12117
12118  if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
12119    console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
12120  }
12121
12122  // If divider is found, we divide the list of values and operands to divide
12123  // them by ofset X and Y.
12124  var splitRegex = /\s*,\s*|\s+/;
12125  var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
12126
12127  // Convert the values with units to absolute pixels to allow our computations
12128  ops = ops.map(function (op, index) {
12129    // Most of the units rely on the orientation of the popper
12130    var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
12131    var mergeWithPrevious = false;
12132    return op
12133    // This aggregates any `+` or `-` sign that aren't considered operators
12134    // e.g.: 10 + +5 => [10, +, +5]
12135    .reduce(function (a, b) {
12136      if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
12137        a[a.length - 1] = b;
12138        mergeWithPrevious = true;
12139        return a;
12140      } else if (mergeWithPrevious) {
12141        a[a.length - 1] += b;
12142        mergeWithPrevious = false;
12143        return a;
12144      } else {
12145        return a.concat(b);
12146      }
12147    }, [])
12148    // Here we convert the string values into number values (in px)
12149    .map(function (str) {
12150      return toValue(str, measurement, popperOffsets, referenceOffsets);
12151    });
12152  });
12153
12154  // Loop trough the offsets arrays and execute the operations
12155  ops.forEach(function (op, index) {
12156    op.forEach(function (frag, index2) {
12157      if (isNumeric(frag)) {
12158        offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
12159      }
12160    });
12161  });
12162  return offsets;
12163}
12164
12165/**
12166 * @function
12167 * @memberof Modifiers
12168 * @argument {Object} data - The data object generated by update method
12169 * @argument {Object} options - Modifiers configuration and options
12170 * @argument {Number|String} options.offset=0
12171 * The offset value as described in the modifier description
12172 * @returns {Object} The data object, properly modified
12173 */
12174function offset(data, _ref) {
12175  var offset = _ref.offset;
12176  var placement = data.placement,
12177      _data$offsets = data.offsets,
12178      popper = _data$offsets.popper,
12179      reference = _data$offsets.reference;
12180
12181  var basePlacement = placement.split('-')[0];
12182
12183  var offsets = void 0;
12184  if (isNumeric(+offset)) {
12185    offsets = [+offset, 0];
12186  } else {
12187    offsets = parseOffset(offset, popper, reference, basePlacement);
12188  }
12189
12190  if (basePlacement === 'left') {
12191    popper.top += offsets[0];
12192    popper.left -= offsets[1];
12193  } else if (basePlacement === 'right') {
12194    popper.top += offsets[0];
12195    popper.left += offsets[1];
12196  } else if (basePlacement === 'top') {
12197    popper.left += offsets[0];
12198    popper.top -= offsets[1];
12199  } else if (basePlacement === 'bottom') {
12200    popper.left += offsets[0];
12201    popper.top += offsets[1];
12202  }
12203
12204  data.popper = popper;
12205  return data;
12206}
12207
12208/**
12209 * @function
12210 * @memberof Modifiers
12211 * @argument {Object} data - The data object generated by `update` method
12212 * @argument {Object} options - Modifiers configuration and options
12213 * @returns {Object} The data object, properly modified
12214 */
12215function preventOverflow(data, options) {
12216  var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
12217
12218  // If offsetParent is the reference element, we really want to
12219  // go one step up and use the next offsetParent as reference to
12220  // avoid to make this modifier completely useless and look like broken
12221  if (data.instance.reference === boundariesElement) {
12222    boundariesElement = getOffsetParent(boundariesElement);
12223  }
12224
12225  // NOTE: DOM access here
12226  // resets the popper's position so that the document size can be calculated excluding
12227  // the size of the popper element itself
12228  var transformProp = getSupportedPropertyName('transform');
12229  var popperStyles = data.instance.popper.style; // assignment to help minification
12230  var top = popperStyles.top,
12231      left = popperStyles.left,
12232      transform = popperStyles[transformProp];
12233
12234  popperStyles.top = '';
12235  popperStyles.left = '';
12236  popperStyles[transformProp] = '';
12237
12238  var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);
12239
12240  // NOTE: DOM access here
12241  // restores the original style properties after the offsets have been computed
12242  popperStyles.top = top;
12243  popperStyles.left = left;
12244  popperStyles[transformProp] = transform;
12245
12246  options.boundaries = boundaries;
12247
12248  var order = options.priority;
12249  var popper = data.offsets.popper;
12250
12251  var check = {
12252    primary: function primary(placement) {
12253      var value = popper[placement];
12254      if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
12255        value = Math.max(popper[placement], boundaries[placement]);
12256      }
12257      return defineProperty({}, placement, value);
12258    },
12259    secondary: function secondary(placement) {
12260      var mainSide = placement === 'right' ? 'left' : 'top';
12261      var value = popper[mainSide];
12262      if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
12263        value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
12264      }
12265      return defineProperty({}, mainSide, value);
12266    }
12267  };
12268
12269  order.forEach(function (placement) {
12270    var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
12271    popper = _extends({}, popper, check[side](placement));
12272  });
12273
12274  data.offsets.popper = popper;
12275
12276  return data;
12277}
12278
12279/**
12280 * @function
12281 * @memberof Modifiers
12282 * @argument {Object} data - The data object generated by `update` method
12283 * @argument {Object} options - Modifiers configuration and options
12284 * @returns {Object} The data object, properly modified
12285 */
12286function shift(data) {
12287  var placement = data.placement;
12288  var basePlacement = placement.split('-')[0];
12289  var shiftvariation = placement.split('-')[1];
12290
12291  // if shift shiftvariation is specified, run the modifier
12292  if (shiftvariation) {
12293    var _data$offsets = data.offsets,
12294        reference = _data$offsets.reference,
12295        popper = _data$offsets.popper;
12296
12297    var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
12298    var side = isVertical ? 'left' : 'top';
12299    var measurement = isVertical ? 'width' : 'height';
12300
12301    var shiftOffsets = {
12302      start: defineProperty({}, side, reference[side]),
12303      end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
12304    };
12305
12306    data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
12307  }
12308
12309  return data;
12310}
12311
12312/**
12313 * @function
12314 * @memberof Modifiers
12315 * @argument {Object} data - The data object generated by update method
12316 * @argument {Object} options - Modifiers configuration and options
12317 * @returns {Object} The data object, properly modified
12318 */
12319function hide(data) {
12320  if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
12321    return data;
12322  }
12323
12324  var refRect = data.offsets.reference;
12325  var bound = find(data.instance.modifiers, function (modifier) {
12326    return modifier.name === 'preventOverflow';
12327  }).boundaries;
12328
12329  if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
12330    // Avoid unnecessary DOM access if visibility hasn't changed
12331    if (data.hide === true) {
12332      return data;
12333    }
12334
12335    data.hide = true;
12336    data.attributes['x-out-of-boundaries'] = '';
12337  } else {
12338    // Avoid unnecessary DOM access if visibility hasn't changed
12339    if (data.hide === false) {
12340      return data;
12341    }
12342
12343    data.hide = false;
12344    data.attributes['x-out-of-boundaries'] = false;
12345  }
12346
12347  return data;
12348}
12349
12350/**
12351 * @function
12352 * @memberof Modifiers
12353 * @argument {Object} data - The data object generated by `update` method
12354 * @argument {Object} options - Modifiers configuration and options
12355 * @returns {Object} The data object, properly modified
12356 */
12357function inner(data) {
12358  var placement = data.placement;
12359  var basePlacement = placement.split('-')[0];
12360  var _data$offsets = data.offsets,
12361      popper = _data$offsets.popper,
12362      reference = _data$offsets.reference;
12363
12364  var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
12365
12366  var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
12367
12368  popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
12369
12370  data.placement = getOppositePlacement(placement);
12371  data.offsets.popper = getClientRect(popper);
12372
12373  return data;
12374}
12375
12376/**
12377 * Modifier function, each modifier can have a function of this type assigned
12378 * to its `fn` property.<br />
12379 * These functions will be called on each update, this means that you must
12380 * make sure they are performant enough to avoid performance bottlenecks.
12381 *
12382 * @function ModifierFn
12383 * @argument {dataObject} data - The data object generated by `update` method
12384 * @argument {Object} options - Modifiers configuration and options
12385 * @returns {dataObject} The data object, properly modified
12386 */
12387
12388/**
12389 * Modifiers are plugins used to alter the behavior of your poppers.<br />
12390 * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
12391 * needed by the library.
12392 *
12393 * Usually you don't want to override the `order`, `fn` and `onLoad` props.
12394 * All the other properties are configurations that could be tweaked.
12395 * @namespace modifiers
12396 */
12397var modifiers = {
12398  /**
12399   * Modifier used to shift the popper on the start or end of its reference
12400   * element.<br />
12401   * It will read the variation of the `placement` property.<br />
12402   * It can be one either `-end` or `-start`.
12403   * @memberof modifiers
12404   * @inner
12405   */
12406  shift: {
12407    /** @prop {number} order=100 - Index used to define the order of execution */
12408    order: 100,
12409    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12410    enabled: true,
12411    /** @prop {ModifierFn} */
12412    fn: shift
12413  },
12414
12415  /**
12416   * The `offset` modifier can shift your popper on both its axis.
12417   *
12418   * It accepts the following units:
12419   * - `px` or unit-less, interpreted as pixels
12420   * - `%` or `%r`, percentage relative to the length of the reference element
12421   * - `%p`, percentage relative to the length of the popper element
12422   * - `vw`, CSS viewport width unit
12423   * - `vh`, CSS viewport height unit
12424   *
12425   * For length is intended the main axis relative to the placement of the popper.<br />
12426   * This means that if the placement is `top` or `bottom`, the length will be the
12427   * `width`. In case of `left` or `right`, it will be the `height`.
12428   *
12429   * You can provide a single value (as `Number` or `String`), or a pair of values
12430   * as `String` divided by a comma or one (or more) white spaces.<br />
12431   * The latter is a deprecated method because it leads to confusion and will be
12432   * removed in v2.<br />
12433   * Additionally, it accepts additions and subtractions between different units.
12434   * Note that multiplications and divisions aren't supported.
12435   *
12436   * Valid examples are:
12437   * ```
12438   * 10
12439   * '10%'
12440   * '10, 10'
12441   * '10%, 10'
12442   * '10 + 10%'
12443   * '10 - 5vh + 3%'
12444   * '-10px + 5vh, 5px - 6%'
12445   * ```
12446   * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
12447   * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
12448   * > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
12449   *
12450   * @memberof modifiers
12451   * @inner
12452   */
12453  offset: {
12454    /** @prop {number} order=200 - Index used to define the order of execution */
12455    order: 200,
12456    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12457    enabled: true,
12458    /** @prop {ModifierFn} */
12459    fn: offset,
12460    /** @prop {Number|String} offset=0
12461     * The offset value as described in the modifier description
12462     */
12463    offset: 0
12464  },
12465
12466  /**
12467   * Modifier used to prevent the popper from being positioned outside the boundary.
12468   *
12469   * A scenario exists where the reference itself is not within the boundaries.<br />
12470   * We can say it has "escaped the boundaries" — or just "escaped".<br />
12471   * In this case we need to decide whether the popper should either:
12472   *
12473   * - detach from the reference and remain "trapped" in the boundaries, or
12474   * - if it should ignore the boundary and "escape with its reference"
12475   *
12476   * When `escapeWithReference` is set to`true` and reference is completely
12477   * outside its boundaries, the popper will overflow (or completely leave)
12478   * the boundaries in order to remain attached to the edge of the reference.
12479   *
12480   * @memberof modifiers
12481   * @inner
12482   */
12483  preventOverflow: {
12484    /** @prop {number} order=300 - Index used to define the order of execution */
12485    order: 300,
12486    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12487    enabled: true,
12488    /** @prop {ModifierFn} */
12489    fn: preventOverflow,
12490    /**
12491     * @prop {Array} [priority=['left','right','top','bottom']]
12492     * Popper will try to prevent overflow following these priorities by default,
12493     * then, it could overflow on the left and on top of the `boundariesElement`
12494     */
12495    priority: ['left', 'right', 'top', 'bottom'],
12496    /**
12497     * @prop {number} padding=5
12498     * Amount of pixel used to define a minimum distance between the boundaries
12499     * and the popper. This makes sure the popper always has a little padding
12500     * between the edges of its container
12501     */
12502    padding: 5,
12503    /**
12504     * @prop {String|HTMLElement} boundariesElement='scrollParent'
12505     * Boundaries used by the modifier. Can be `scrollParent`, `window`,
12506     * `viewport` or any DOM element.
12507     */
12508    boundariesElement: 'scrollParent'
12509  },
12510
12511  /**
12512   * Modifier used to make sure the reference and its popper stay near each other
12513   * without leaving any gap between the two. Especially useful when the arrow is
12514   * enabled and you want to ensure that it points to its reference element.
12515   * It cares only about the first axis. You can still have poppers with margin
12516   * between the popper and its reference element.
12517   * @memberof modifiers
12518   * @inner
12519   */
12520  keepTogether: {
12521    /** @prop {number} order=400 - Index used to define the order of execution */
12522    order: 400,
12523    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12524    enabled: true,
12525    /** @prop {ModifierFn} */
12526    fn: keepTogether
12527  },
12528
12529  /**
12530   * This modifier is used to move the `arrowElement` of the popper to make
12531   * sure it is positioned between the reference element and its popper element.
12532   * It will read the outer size of the `arrowElement` node to detect how many
12533   * pixels of conjunction are needed.
12534   *
12535   * It has no effect if no `arrowElement` is provided.
12536   * @memberof modifiers
12537   * @inner
12538   */
12539  arrow: {
12540    /** @prop {number} order=500 - Index used to define the order of execution */
12541    order: 500,
12542    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12543    enabled: true,
12544    /** @prop {ModifierFn} */
12545    fn: arrow,
12546    /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
12547    element: '[x-arrow]'
12548  },
12549
12550  /**
12551   * Modifier used to flip the popper's placement when it starts to overlap its
12552   * reference element.
12553   *
12554   * Requires the `preventOverflow` modifier before it in order to work.
12555   *
12556   * **NOTE:** this modifier will interrupt the current update cycle and will
12557   * restart it if it detects the need to flip the placement.
12558   * @memberof modifiers
12559   * @inner
12560   */
12561  flip: {
12562    /** @prop {number} order=600 - Index used to define the order of execution */
12563    order: 600,
12564    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12565    enabled: true,
12566    /** @prop {ModifierFn} */
12567    fn: flip,
12568    /**
12569     * @prop {String|Array} behavior='flip'
12570     * The behavior used to change the popper's placement. It can be one of
12571     * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
12572     * placements (with optional variations)
12573     */
12574    behavior: 'flip',
12575    /**
12576     * @prop {number} padding=5
12577     * The popper will flip if it hits the edges of the `boundariesElement`
12578     */
12579    padding: 5,
12580    /**
12581     * @prop {String|HTMLElement} boundariesElement='viewport'
12582     * The element which will define the boundaries of the popper position.
12583     * The popper will never be placed outside of the defined boundaries
12584     * (except if `keepTogether` is enabled)
12585     */
12586    boundariesElement: 'viewport'
12586
12587  },
12588
12589  /**
12590   * Modifier used to make the popper flow toward the inner of the reference element.
12591   * By default, when this modifier is disabled, the popper will be placed outside
12592   * the reference element.
12593   * @memberof modifiers
12594   * @inner
12595   */
12596  inner: {
12597    /** @prop {number} order=700 - Index used to define the order of execution */
12598    order: 700,
12599    /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
12600    enabled: false,
12601    /** @prop {ModifierFn} */
12602    fn: inner
12603  },
12604
12605  /**
12606   * Modifier used to hide the popper when its reference element is outside of the
12607   * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
12608   * be used to hide with a CSS selector the popper when its reference is
12609   * out of boundaries.
12610   *
12611   * Requires the `preventOverflow` modifier before it in order to work.
12612   * @memberof modifiers
12613   * @inner
12614   */
12615  hide: {
12616    /** @prop {number} order=800 - Index used to define the order of execution */
12617    order: 800,
12618    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12619    enabled: true,
12620    /** @prop {ModifierFn} */
12621    fn: hide
12622  },
12623
12624  /**
12625   * Computes the style that will be applied to the popper element to gets
12626   * properly positioned.
12627   *
12628   * Note that this modifier will not touch the DOM, it just prepares the styles
12629   * so that `applyStyle` modifier can apply it. This separation is useful
12630   * in case you need to replace `applyStyle` with a custom implementation.
12631   *
12632   * This modifier has `850` as `order` value to maintain backward compatibility
12633   * with previous versions of Popper.js. Expect the modifiers ordering method
12634   * to change in future major versions of the library.
12635   *
12636   * @memberof modifiers
12637   * @inner
12638   */
12639  computeStyle: {
12640    /** @prop {number} order=850 - Index used to define the order of execution */
12641    order: 850,
12642    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12643    enabled: true,
12644    /** @prop {ModifierFn} */
12645    fn: computeStyle,
12646    /**
12647     * @prop {Boolean} gpuAcceleration=true
12648     * If true, it uses the CSS 3D transformation to position the popper.
12649     * Otherwise, it will use the `top` and `left` properties
12650     */
12651    gpuAcceleration: true,
12652    /**
12653     * @prop {string} [x='bottom']
12654     * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
12655     * Change this if your popper should grow in a direction different from `bottom`
12656     */
12657    x: 'bottom',
12658    /**
12659     * @prop {string} [x='left']
12660     * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
12661     * Change this if your popper should grow in a direction different from `right`
12662     */
12663    y: 'right'
12664  },
12665
12666  /**
12667   * Applies the computed styles to the popper element.
12668   *
12669   * All the DOM manipulations are limited to this modifier. This is useful in case
12670   * you want to integrate Popper.js inside a framework or view library and you
12671   * want to delegate all the DOM manipulations to it.
12672   *
12673   * Note that if you disable this modifier, you must make sure the popper element
12674   * has its position set to `absolute` before Popper.js can do its work!
12675   *
12676   * Just disable this modifier and define your own to achieve the desired effect.
12677   *
12678   * @memberof modifiers
12679   * @inner
12680   */
12681  applyStyle: {
12682    /** @prop {number} order=900 - Index used to define the order of execution */
12683    order: 900,
12684    /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
12685    enabled: true,
12686    /** @prop {ModifierFn} */
vendor: 4,830 bytes, lines 12687-12825
12687    fn: applyStyle,
12688    /** @prop {Function} */
12689    onLoad: applyStyleOnLoad,
12690    /**
12691     * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
12692     * @prop {Boolean} gpuAcceleration=true
12693     * If true, it uses the CSS 3D transformation to position the popper.
12694     * Otherwise, it will use the `top` and `left` properties
12695     */
12696    gpuAcceleration: undefined
12697  }
12698};
12699
12700/**
12701 * The `dataObject` is an object containing all the information used by Popper.js.
12702 * This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
12703 * @name dataObject
12704 * @property {Object} data.instance The Popper.js instance
12705 * @property {String} data.placement Placement applied to popper
12706 * @property {String} data.originalPlacement Placement originally defined on init
12707 * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
12708 * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
12709 * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
12710 * @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
12711 * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
12712 * @property {Object} data.boundaries Offsets of the popper boundaries
12713 * @property {Object} data.offsets The measurements of popper, reference and arrow elements
12714 * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
12715 * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
12716 * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
12717 */
12718
12719/**
12720 * Default options provided to Popper.js constructor.<br />
12721 * These can be overridden using the `options` argument of Popper.js.<br />
12722 * To override an option, simply pass an object with the same
12723 * structure of the `options` object, as the 3rd argument. For example:
12724 * ```
12725 * new Popper(ref, pop, {
12726 *   modifiers: {
12727 *     preventOverflow: { enabled: false }
12728 *   }
12729 * })
12730 * ```
12731 * @type {Object}
12732 * @static
12733 * @memberof Popper
12734 */
12735var Defaults = {
12736  /**
12737   * Popper's placement.
12738   * @prop {Popper.placements} placement='bottom'
12739   */
12740  placement: 'bottom',
12741
12742  /**
12743   * Set this to true if you want popper to position it self in 'fixed' mode
12744   * @prop {Boolean} positionFixed=false
12745   */
12746  positionFixed: false,
12747
12748  /**
12749   * Whether events (resize, scroll) are initially enabled.
12750   * @prop {Boolean} eventsEnabled=true
12751   */
12752  eventsEnabled: true,
12753
12754  /**
12755   * Set to true if you want to automatically remove the popper when
12756   * you call the `destroy` method.
12757   * @prop {Boolean} removeOnDestroy=false
12758   */
12759  removeOnDestroy: false,
12760
12761  /**
12762   * Callback called when the popper is created.<br />
12763   * By default, it is set to no-op.<br />
12764   * Access Popper.js instance with `data.instance`.
12765   * @prop {onCreate}
12766   */
12767  onCreate: function onCreate() {},
12768
12769  /**
12770   * Callback called when the popper is updated. This callback is not called
12771   * on the initialization/creation of the popper, but only on subsequent
12772   * updates.<br />
12773   * By default, it is set to no-op.<br />
12774   * Access Popper.js instance with `data.instance`.
12775   * @prop {onUpdate}
12776   */
12777  onUpdate: function onUpdate() {},
12778
12779  /**
12780   * List of modifiers used to modify the offsets before they are applied to the popper.
12781   * They provide most of the functionalities of Popper.js.
12782   * @prop {modifiers}
12783   */
12784  modifiers: modifiers
12785};
12786
12787/**
12788 * @callback onCreate
12789 * @param {dataObject} data
12790 */
12791
12792/**
12793 * @callback onUpdate
12794 * @param {dataObject} data
12795 */
12796
12797// Utils
12798// Methods
12799var Popper = function () {
12800  /**
12801   * Creates a new Popper.js instance.
12802   * @class Popper
12803   * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper
12804   * @param {HTMLElement} popper - The HTML element used as the popper
12805   * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
12806   * @return {Object} instance - The generated Popper.js instance
12807   */
12808  function Popper(reference, popper) {
12809    var _this = this;
12810
12811    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
12812    classCallCheck(this, Popper);
12813
12814    this.scheduleUpdate = function () {
12815      return requestAnimationFrame(_this.update);
12816    };
12817
12818    // make update() debounced, so that it only runs at most once-per-tick
12819    this.update = debounce(this.update.bind(this));
12820
12821    // with {} we create a new object with the options inside it
12822    this.options = _extends({}, Popper.Defaults, options);
12823
12824    // init state
12825    this.state = {
vendor: 5,112 bytes, lines 12826-12976
12826      isDestroyed: false,
12827      isCreated: false,
12828      scrollParents: []
12829    };
12830
12831    // get reference and popper elements (allow jQuery wrappers)
12832    this.reference = reference && reference.jquery ? reference[0] : reference;
12833    this.popper = popper && popper.jquery ? popper[0] : popper;
12834
12835    // Deep merge modifiers options
12836    this.options.modifiers = {};
12837    Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
12838      _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
12839    });
12840
12841    // Refactoring modifiers' list (Object => Array)
12842    this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
12843      return _extends({
12844        name: name
12845      }, _this.options.modifiers[name]);
12846    })
12847    // sort the modifiers by order
12848    .sort(function (a, b) {
12849      return a.order - b.order;
12850    });
12851
12852    // modifiers have the ability to execute arbitrary code when Popper.js get inited
12853    // such code is executed in the same order of its modifier
12854    // they could add new properties to their options configuration
12855    // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
12856    this.modifiers.forEach(function (modifierOptions) {
12857      if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
12858        modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
12859      }
12860    });
12861
12862    // fire the first update to position the popper in the right place
12863    this.update();
12864
12865    var eventsEnabled = this.options.eventsEnabled;
12866    if (eventsEnabled) {
12867      // setup event listeners, they will take care of update the position in specific situations
12868      this.enableEventListeners();
12869    }
12870
12871    this.state.eventsEnabled = eventsEnabled;
12872  }
12873
12874  // We can't use class properties because they don't get listed in the
12875  // class prototype and break stuff like Sinon stubs
12876
12877
12878  createClass(Popper, [{
12879    key: 'update',
12880    value: function update$$1() {
12881      return update.call(this);
12882    }
12883  }, {
12884    key: 'destroy',
12885    value: function destroy$$1() {
12886      return destroy.call(this);
12887    }
12888  }, {
12889    key: 'enableEventListeners',
12890    value: function enableEventListeners$$1() {
12891      return enableEventListeners.call(this);
12892    }
12893  }, {
12894    key: 'disableEventListeners',
12895    value: function disableEventListeners$$1() {
12896      return disableEventListeners.call(this);
12897    }
12898
12899    /**
12900     * Schedules an update. It will run on the next UI update available.
12901     * @method scheduleUpdate
12902     * @memberof Popper
12903     */
12904
12905
12906    /**
12907     * Collection of utilities useful when writing custom modifiers.
12908     * Starting from version 1.7, this method is available only if you
12909     * include `popper-utils.js` before `popper.js`.
12910     *
12911     * **DEPRECATION**: This way to access PopperUtils is deprecated
12912     * and will be removed in v2! Use the PopperUtils module directly instead.
12913     * Due to the high instability of the methods contained in Utils, we can't
12914     * guarantee them to follow semver. Use them at your own risk!
12915     * @static
12916     * @private
12917     * @type {Object}
12918     * @deprecated since version 1.8
12919     * @member Utils
12920     * @memberof Popper
12921     */
12922
12923  }]);
12924  return Popper;
12925}();
12926
12927/**
12928 * The `referenceObject` is an object that provides an interface compatible with Popper.js
12929 * and lets you use it as replacement of a real DOM node.<br />
12930 * You can use this method to position a popper relatively to a set of coordinates
12931 * in case you don't have a DOM node to use as reference.
12932 *
12933 * ```
12934 * new Popper(referenceObject, popperNode);
12935 * ```
12936 *
12937 * NB: This feature isn't supported in Internet Explorer 10.
12938 * @name referenceObject
12939 * @property {Function} data.getBoundingClientRect
12940 * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
12941 * @property {number} data.clientWidth
12942 * An ES6 getter that will return the width of the virtual reference element.
12943 * @property {number} data.clientHeight
12944 * An ES6 getter that will return the height of the virtual reference element.
12945 */
12946
12947
12948Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
12949Popper.placements = placements;
12950Popper.Defaults = Defaults;
12951
12952return Popper;
12953
12954})));
12955//# sourceMappingURL=popper.js.map
12956
12957
12958/**
12959 * --------------------------------------------------------------------------
12960 * Bootstrap (v4.3.1): index.js
12961 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12962 * --------------------------------------------------------------------------
12963 */
12964(function ($) {
12965  if (typeof $ === 'undefined') {
12966    throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.');
12967  }
12968
12969  var version = $.fn.jquery.split(' ')[0].split('.');
12970  var minMajor = 1;
12971  var ltMajor = 2;
12972  var minMinor = 9;
12973  var minPatch = 1;
12974  var maxMajor = 4;
12975
12976  if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >
vendor: 11,653 bytes, lines 12976-13325
12976= maxMajor) {
12977    throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');
12978  }
12979})($);
12980//# sourceMappingURL=index.js.map
12981
12982/*!
12983  * Bootstrap util.js v4.3.1 (https://getbootstrap.com/)
12984  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
12985  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12986  */
12987(function (global, factory) {
12988  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :
12989  typeof define === 'function' && define.amd ? define(['jquery'], factory) :
12990  (global = global || self, global.Util = factory(global.jQuery));
12991}(this, function ($) { 'use strict';
12992
12993  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
12994
12995  /**
12996   * --------------------------------------------------------------------------
12997   * Bootstrap (v4.3.1): util.js
12998   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
12999   * --------------------------------------------------------------------------
13000   */
13001  /**
13002   * ------------------------------------------------------------------------
13003   * Private TransitionEnd Helpers
13004   * ------------------------------------------------------------------------
13005   */
13006
13007  var TRANSITION_END = 'transitionend';
13008  var MAX_UID = 1000000;
13009  var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp)
13010
13011  function toType(obj) {
13012    return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase();
13013  }
13014
13015  function getSpecialTransitionEndEvent() {
13016    return {
13017      bindType: TRANSITION_END,
13018      delegateType: TRANSITION_END,
13019      handle: function handle(event) {
13020        if ($(event.target).is(this)) {
13021          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
13022        }
13023
13024        return undefined; // eslint-disable-line no-undefined
13025      }
13026    };
13027  }
13028
13029  function transitionEndEmulator(duration) {
13030    var _this = this;
13031
13032    var called = false;
13033    $(this).one(Util.TRANSITION_END, function () {
13034      called = true;
13035    });
13036    setTimeout(function () {
13037      if (!called) {
13038        Util.triggerTransitionEnd(_this);
13039      }
13040    }, duration);
13041    return this;
13042  }
13043
13044  function setTransitionEndSupport() {
13045    $.fn.emulateTransitionEnd = transitionEndEmulator;
13046    $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
13047  }
13048  /**
13049   * --------------------------------------------------------------------------
13050   * Public Util Api
13051   * --------------------------------------------------------------------------
13052   */
13053
13054
13055  var Util = {
13056    TRANSITION_END: 'bsTransitionEnd',
13057    getUID: function getUID(prefix) {
13058      do {
13059        // eslint-disable-next-line no-bitwise
13060        prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
13061      } while (document.getElementById(prefix));
13062
13063      return prefix;
13064    },
13065    getSelectorFromElement: function getSelectorFromElement(element) {
13066      var selector = element.getAttribute('data-target');
13067
13068      if (!selector || selector === '#') {
13069        var hrefAttr = element.getAttribute('href');
13070        selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : '';
13071      }
13072
13073      try {
13074        return document.querySelector(selector) ? selector : null;
13075      } catch (err) {
13076        return null;
13077      }
13078    },
13079    getTransitionDurationFromElement: function getTransitionDurationFromElement(element) {
13080      if (!element) {
13081        return 0;
13082      } // Get transition-duration of the element
13083
13084
13085      var transitionDuration = $(element).css('transition-duration');
13086      var transitionDelay = $(element).css('transition-delay');
13087      var floatTransitionDuration = parseFloat(transitionDuration);
13088      var floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found
13089
13090      if (!floatTransitionDuration && !floatTransitionDelay) {
13091        return 0;
13092      } // If multiple durations are defined, take the first
13093
13094
13095      transitionDuration = transitionDuration.split(',')[0];
13096      transitionDelay = transitionDelay.split(',')[0];
13097      return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
13098    },
13099    reflow: function reflow(element) {
13100      return element.offsetHeight;
13101    },
13102    triggerTransitionEnd: function triggerTransitionEnd(element) {
13103      $(element).trigger(TRANSITION_END);
13104    },
13105    // TODO: Remove in v5
13106    supportsTransitionEnd: function supportsTransitionEnd() {
13107      return Boolean(TRANSITION_END);
13108    },
13109    isElement: function isElement(obj) {
13110      return (obj[0] || obj).nodeType;
13111    },
13112    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
13113      for (var property in configTypes) {
13114        if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
13115          var expectedTypes = configTypes[property];
13116          var value = config[property];
13117          var valueType = value && Util.isElement(value) ? 'element' : toType(value);
13118
13119          if (!new RegExp(expectedTypes).test(valueType)) {
13120            throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\"."));
13121          }
13122        }
13123      }
13124    },
13125    findShadowRoot: function findShadowRoot(element) {
13126      if (!document.documentElement.attachShadow) {
13127        return null;
13128      } // Can find the shadow root otherwise it'll return the document
13129
13130
13131      if (typeof element.getRootNode === 'function') {
13132        var root = element.getRootNode();
13133        return root instanceof ShadowRoot ? root : null;
13134      }
13135
13136      if (element instanceof ShadowRoot) {
13137        return element;
13138      } // when we don't find a shadow root
13139
13140
13141      if (!element.parentNode) {
13142        return null;
13143      }
13144
13145      return Util.findShadowRoot(element.parentNode);
13146    }
13147  };
13148  setTransitionEndSupport();
13149
13150  return Util;
13151
13152}));
13153//# sourceMappingURL=util.js.map
13154
13155
13156/*!
13157  * Bootstrap tab.js v4.3.1 (https://getbootstrap.com/)
13158  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
13159  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13160  */
13161(function (global, factory) {
13162  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
13163  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
13164  (global = global || self, global.Tab = factory(global.jQuery, global.Util));
13165}(this, function ($, Util) { 'use strict';
13166
13167  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
13168  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;
13169
13170  function _defineProperties(target, props) {
13171    for (var i = 0; i < props.length; i++) {
13172      var descriptor = props[i];
13173      descriptor.enumerable = descriptor.enumerable || false;
13174      descriptor.configurable = true;
13175      if ("value" in descriptor) descriptor.writable = true;
13176      Object.defineProperty(target, descriptor.key, descriptor);
13177    }
13178  }
13179
13180  function _createClass(Constructor, protoProps, staticProps) {
13181    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
13182    if (staticProps) _defineProperties(Constructor, staticProps);
13183    return Constructor;
13184  }
13185
13186  /**
13187   * ------------------------------------------------------------------------
13188   * Constants
13189   * ------------------------------------------------------------------------
13190   */
13191
13192  var NAME = 'tab';
13193  var VERSION = '4.3.1';
13194  var DATA_KEY = 'bs.tab';
13195  var EVENT_KEY = "." + DATA_KEY;
13196  var DATA_API_KEY = '.data-api';
13197  var JQUERY_NO_CONFLICT = $.fn[NAME];
13198  var Event = {
13199    HIDE: "hide" + EVENT_KEY,
13200    HIDDEN: "hidden" + EVENT_KEY,
13201    SHOW: "show" + EVENT_KEY,
13202    SHOWN: "shown" + EVENT_KEY,
13203    CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
13204  };
13205  var ClassName = {
13206    DROPDOWN_MENU: 'dropdown-menu',
13207    ACTIVE: 'active',
13208    DISABLED: 'disabled',
13209    FADE: 'fade',
13210    SHOW: 'show'
13211  };
13212  var Selector = {
13213    DROPDOWN: '.dropdown',
13214    NAV_LIST_GROUP: '.nav, .list-group',
13215    ACTIVE: '.active',
13216    ACTIVE_UL: '> li > .active',
13217    DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',
13218    DROPDOWN_TOGGLE: '.dropdown-toggle',
13219    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
13220    /**
13221     * ------------------------------------------------------------------------
13222     * Class Definition
13223     * ------------------------------------------------------------------------
13224     */
13225
13226  };
13227
13228  var Tab =
13229  /*#__PURE__*/
13230  function () {
13231    function Tab(element) {
13232      this._element = element;
13233    } // Getters
13234
13235
13236    var _proto = Tab.prototype;
13237
13238    // Public
13239    _proto.show = function show() {
13240      var _this = this;
13241
13242      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE) || $(this._element).hasClass(ClassName.DISABLED)) {
13243        return;
13244      }
13245
13246      var target;
13247      var previous;
13248      var listElement = $(this._element).closest(Selector.NAV_LIST_GROUP)[0];
13249      var selector = Util.getSelectorFromElement(this._element);
13250
13251      if (listElement) {
13252        var itemSelector = listElement.nodeName === 'UL' || listElement.nodeName === 'OL' ? Selector.ACTIVE_UL : Selector.ACTIVE;
13253        previous = $.makeArray($(listElement).find(itemSelector));
13254        previous = previous[previous.length - 1];
13255      }
13256
13257      var hideEvent = $.Event(Event.HIDE, {
13258        relatedTarget: this._element
13259      });
13260      var showEvent = $.Event(Event.SHOW, {
13261        relatedTarget: previous
13262      });
13263
13264      if (previous) {
13265        $(previous).trigger(hideEvent);
13266      }
13267
13268      $(this._element).trigger(showEvent);
13269
13270      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
13271        return;
13272      }
13273
13274      if (selector) {
13275        target = document.querySelector(selector);
13276      }
13277
13278      this._activate(this._element, listElement);
13279
13280      var complete = function complete() {
13281        var hiddenEvent = $.Event(Event.HIDDEN, {
13282          relatedTarget: _this._element
13283        });
13284        var shownEvent = $.Event(Event.SHOWN, {
13285          relatedTarget: previous
13286        });
13287        $(previous).trigger(hiddenEvent);
13288        $(_this._element).trigger(shownEvent);
13289      };
13290
13291      if (target) {
13292        this._activate(target, target.parentNode, complete);
13293      } else {
13294        complete();
13295      }
13296    };
13297
13298    _proto.dispose = function dispose() {
13299      $.removeData(this._element, DATA_KEY);
13300      this._element = null;
13301    } // Private
13302    ;
13303
13304    _proto._activate = function _activate(element, container, callback) {
13305      var _this2 = this;
13306
13307      var activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $(container).find(Selector.ACTIVE_UL) : $(container).children(Selector.ACTIVE);
13308      var active = activeElements[0];
13309      var isTransitioning = callback && active && $(active).hasClass(ClassName.FADE);
13310
13311      var complete = function complete() {
13312        return _this2._transitionComplete(element, active, callback);
13313      };
13314
13315      if (active && isTransitioning) {
13316        var transitionDuration = Util.getTransitionDurationFromElement(active);
13317        $(active).removeClass(ClassName.SHOW).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
13318      } else {
13319        complete();
13320      }
13321    };
13322
13323    _proto._transitionComplete = function _transitionComplete(element, active, callback) {
13324      if (active) {
13325        $(active).removeClass(ClassName.ACTIVE);
vendor: 5,584 bytes, lines 13326-13524
13326        var dropdownChild = $(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
13327
13328        if (dropdownChild) {
13329          $(dropdownChild).removeClass(ClassName.ACTIVE);
13330        }
13331
13332        if (active.getAttribute('role') === 'tab') {
13333          active.setAttribute('aria-selected', false);
13334        }
13335      }
13336
13337      $(element).addClass(ClassName.ACTIVE);
13338
13339      if (element.getAttribute('role') === 'tab') {
13340        element.setAttribute('aria-selected', true);
13341      }
13342
13343      Util.reflow(element);
13344
13345      if (element.classList.contains(ClassName.FADE)) {
13346        element.classList.add(ClassName.SHOW);
13347      }
13348
13349      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
13350        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];
13351
13352        if (dropdownElement) {
13353          var dropdownToggleList = [].slice.call(dropdownElement.querySelectorAll(Selector.DROPDOWN_TOGGLE));
13354          $(dropdownToggleList).addClass(ClassName.ACTIVE);
13355        }
13356
13357        element.setAttribute('aria-expanded', true);
13358      }
13359
13360      if (callback) {
13361        callback();
13362      }
13363    } // Static
13364    ;
13365
13366    Tab._jQueryInterface = function _jQueryInterface(config) {
13367      return this.each(function () {
13368        var $this = $(this);
13369        var data = $this.data(DATA_KEY);
13370
13371        if (!data) {
13372          data = new Tab(this);
13373          $this.data(DATA_KEY, data);
13374        }
13375
13376        if (typeof config === 'string') {
13377          if (typeof data[config] === 'undefined') {
13378            throw new TypeError("No method named \"" + config + "\"");
13379          }
13380
13381          data[config]();
13382        }
13383      });
13384    };
13385
13386    _createClass(Tab, null, [{
13387      key: "VERSION",
13388      get: function get() {
13389        return VERSION;
13390      }
13391    }]);
13392
13393    return Tab;
13394  }();
13395  /**
13396   * ------------------------------------------------------------------------
13397   * Data Api implementation
13398   * ------------------------------------------------------------------------
13399   */
13400
13401
13402  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
13403    event.preventDefault();
13404
13405    Tab._jQueryInterface.call($(this), 'show');
13406  });
13407  /**
13408   * ------------------------------------------------------------------------
13409   * jQuery
13410   * ------------------------------------------------------------------------
13411   */
13412
13413  $.fn[NAME] = Tab._jQueryInterface;
13414  $.fn[NAME].Constructor = Tab;
13415
13416  $.fn[NAME].noConflict = function () {
13417    $.fn[NAME] = JQUERY_NO_CONFLICT;
13418    return Tab._jQueryInterface;
13419  };
13420
13421  return Tab;
13422
13423}));
13424//# sourceMappingURL=tab.js.map
13425
13426
13427/*!
13428  * Bootstrap alert.js v4.3.1 (https://getbootstrap.com/)
13429  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
13430  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13431  */
13432(function (global, factory) {
13433  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
13434  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
13435  (global = global || self, global.Alert = factory(global.jQuery, global.Util));
13436}(this, function ($, Util) { 'use strict';
13437
13438  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
13439  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;
13440
13441  function _defineProperties(target, props) {
13442    for (var i = 0; i < props.length; i++) {
13443      var descriptor = props[i];
13444      descriptor.enumerable = descriptor.enumerable || false;
13445      descriptor.configurable = true;
13446      if ("value" in descriptor) descriptor.writable = true;
13447      Object.defineProperty(target, descriptor.key, descriptor);
13448    }
13449  }
13450
13451  function _createClass(Constructor, protoProps, staticProps) {
13452    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
13453    if (staticProps) _defineProperties(Constructor, staticProps);
13454    return Constructor;
13455  }
13456
13457  /**
13458   * ------------------------------------------------------------------------
13459   * Constants
13460   * ------------------------------------------------------------------------
13461   */
13462
13463  var NAME = 'alert';
13464  var VERSION = '4.3.1';
13465  var DATA_KEY = 'bs.alert';
13466  var EVENT_KEY = "." + DATA_KEY;
13467  var DATA_API_KEY = '.data-api';
13468  var JQUERY_NO_CONFLICT = $.fn[NAME];
13469  var Selector = {
13470    DISMISS: '[data-dismiss="alert"]'
13471  };
13472  var Event = {
13473    CLOSE: "close" + EVENT_KEY,
13474    CLOSED: "closed" + EVENT_KEY,
13475    CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
13476  };
13477  var ClassName = {
13478    ALERT: 'alert',
13479    FADE: 'fade',
13480    SHOW: 'show'
13481    /**
13482     * ------------------------------------------------------------------------
13483     * Class Definition
13484     * ------------------------------------------------------------------------
13485     */
13486
13487  };
13488
13489  var Alert =
13490  /*#__PURE__*/
13491  function () {
13492    function Alert(element) {
13493      this._element = element;
13494    } // Getters
13495
13496
13497    var _proto = Alert.prototype;
13498
13499    // Public
13500    _proto.close = function close(element) {
13501      var rootElement = this._element;
13502
13503      if (element) {
13504        rootElement = this._getRootElement(element);
13505      }
13506
13507      var customEvent = this._triggerCloseEvent(rootElement);
13508
13509      if (customEvent.isDefaultPrevented()) {
13510        return;
13511      }
13512
13513      this._removeElement(rootElement);
13514    };
13515
13516    _proto.dispose = function dispose() {
13517      $.removeData(this._element, DATA_KEY);
13518      this._element = null;
13519    } // Private
13520    ;
13521
13522    _proto._getRootElement = function _getRootElement(element) {
13523      var selector = Util.getSelectorFromElement(element);
13524      var parent = false;
13525
13526      if (selector) {
13527        parent = document.querySelector(selector);
13528      }
13529
13530      if (!parent) {
13531        parent = $(element).closest("." + ClassName.ALERT)[0];
13532      }
13533
13534      return parent;
13535    };
13536
13537    _proto._triggerCloseEvent = function _triggerCloseEvent(element) {
13538      var closeEvent = $.Event(Event.CLOSE);
13539      $(element).trigger(closeEvent);
13540      return closeEvent;
13541    };
13542
13543    _proto._removeElement = function _removeElement(element) {
13544      var _this = this;
13545
13546      $(element).removeClass(ClassName.SHOW);
13547
13548      if (!$(element).hasClass(ClassName.FADE)) {
13549        this._destroyElement(element);
13550
13551        return;
13552      }
13553
13554      var transitionDuration = Util.getTransitionDurationFromElement(element);
13555      $(element).one(Util.TRANSITION_END, function (event) {
13556        return _this._destroyElement(element, event);
13557      }).emulateTransitionEnd(transitionDuration);
13558    };
13559
13560    _proto._destroyElement = function _destroyElement(element) {
13561      $(element).detach().trigger(Event.CLOSED).remove();
13562    } // Static
13563    ;
13564
13565    Alert._jQueryInterface = function _jQueryInterface(config) {
13566      return this.each(function () {
13567        var $element = $(this);
13568        var data = $element.data(DATA_KEY);
13569
13570        if (!data) {
13571          data = new Alert(this);
13572          $element.data(DATA_KEY, data);
13573        }
13574
13575        if (config === 'close') {
13576          data[config](this);
13577        }
13578      });
13579    };
13580
13581    Alert._handleDismiss = function _handleDismiss(alertInstance) {
13582      return function (event) {
13583        if (event) {
13584          event.preventDefault();
13585        }
13586
13587        alertInstance.close(this);
13588      };
13589    };
13590
13591    _createClass(Alert, null, [{
13592      key: "VERSION",
13593      get: function get() {
13594        return VERSION;
13595      }
13596    }]);
13597
13598    return Alert;
13599  }();
13600  /**
13601   * ------------------------------------------------------------------------
13602   * Data Api implementation
13603   * ------------------------------------------------------------------------
13604   */
13605
13606
13607  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
13608  /**
13609   * ------------------------------------------------------------------------
13610   * jQuery
13611   * ------------------------------------------------------------------------
13612   */
13613
13614  $.fn[NAME] = Alert._jQueryInterface;
13615  $.fn[NAME].Constructor = Alert;
13616
13617  $.fn[NAME].noConflict = function () {
13618    $.fn[NAME] = JQUERY_NO_CONFLICT;
13619    return Alert._jQueryInterface;
13620  };
13621
13622  return Alert;
13623
13624}));
13625//# sourceMappingURL=alert.js.map
13626
13627
13628/*!
13629  * Bootstrap collapse.js v4.3.1 (https://getbootstrap.com/)
13630  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
13631  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
13632  */
13633(function (global, factory) {
13634  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
13635  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
13636  (global = global || self, global.Collapse = factory(global.jQuery, global.Util));
13637}(this, function ($, Util) { 'use strict';
13638
13639  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
13640  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;
13641
13642  function _defineProperties(target, props) {
13643    for (var i = 0; i < props.length; i++) {
13644      var descriptor = props[i];
13645      descriptor.enumerable = descriptor.enumerable || false;
13646      descriptor.configurable = true;
13647      if ("value" in descriptor) descriptor.writable = true;
13648      Object.defineProperty(target, descriptor.key, descriptor);
13649    }
13650  }
13651
13652  function _createClass(Constructor, protoProps, staticProps) {
13653    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
13654    if (staticProps) _defineProperties(Constructor, staticProps);
13655    return Constructor;
13656  }
13657
13658  function _defineProperty(obj, key, value) {
13659    if (key in obj) {
13660      Object.defineProperty(obj, key, {
13661        value: value,
13662        enumerable: true,
13663        configurable: true,
13664        writable: true
13665      });
13666    } else {
13667      obj[key] = value;
13668    }
13669
13670    return obj;
13671  }
13672
13673  function _objectSpread(target) {
13674    for (var i = 1; i < arguments.length; i++) {
13675      var source = arguments[i] != null ? arguments[i] : {};
13676      var ownKeys = Object.keys(source);
13677
13678      if (typeof Object.getOwnPropertySymbols === 'function') {
13679        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
13680          return Object.getOwnPropertyDescriptor(source, sym).enumerable;
13681        }));
13682      }
13683
13684      ownKeys.forEach(function (key) {
13685        _defineProperty(target, key, source[key]);
13686      });
13687    }
13688
13689    return target;
13690  }
13691
13692  /**
13693   * ------------------------------------------------------------------------
13694   * Constants
13695   * ------------------------------------------------------------------------
13696   */
13697
13698  var NAME = 'collapse';
13699  var VERSION = '4.3.1';
13700  var DATA_KEY = 'bs.collapse';
13701  var EVENT_KEY = "." + DATA_KEY;
13702  var DATA_API_KEY = '.data-api';
13703  var JQUERY_NO_CONFLICT = $.fn[NAME];
13704  var Default = {
13705    toggle: true,
13706    parent: ''
13707  };
13708  var DefaultType = {
13709    toggle: 'boolean',
13710    parent: '(string|element)'
13711  };
13712  var Event = {
13713    SHOW: "show" + EVENT_KEY,
13714    SHOWN: "shown" + EVENT_KEY,
13715    HIDE: "hide" + EVENT_KEY,
13716    HIDDEN: "hidden" + EVENT_KEY,
13717    CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
13718  };
13719  var ClassName = {
13720    SHOW: 'show',
13721    COLLAPSE: 'collapse',
13722    COLLAPSING: 'collapsing',
13723    COLLAPSED: 'collapsed'
13724  };
13725  var Dimension = {
13726    WIDTH: 'width',
13727    HEIGHT: 'height'
13728  };
13729  var Selector = {
13730    ACTIVES: '.show, .collapsing',
13731    DATA_TOGGLE: '[data-toggle="collapse"]'
13732    /**
13733     * ------------------------------------------------------------------------
13734     * Class Definition
13735     * ------------------------------------------------------------------------
13736     */
13737
13738  };
13739
13740  var Collapse =
13741  /*#__PURE__*/
13742  function () {
13743    function Collapse(element, config) {
13744      this._isTransitioning = false;
13745      this._element = element;
13746      this._config = this._getConfig(config);
13747      this._triggerArray = [].slice.call(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]")));
13748      var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE));
13749
13750      for (var i = 0, len = toggleList.length; i < len; i++) {
13751        var elem = toggleList[i];
13752        var selector = Util.getSelectorFromElement(elem);
13753        var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) {
13754          return foundElem === element;
13755        });
13756
13757        if (selector !== null && filterElement.length > 0) {
13758          this._selector = selector;
13759
13760          this._triggerArray.push(elem);
13761        }
13762      }
13763
13764      this._parent = this._config.parent ? this._getParent() : null;
13765
13766      if (!this._config.parent) {
13767        this._addAriaAndCollapsedClass(this._element, this._triggerArray);
13768      }
13769
13770      if (this._config.toggle) {
13771        this.toggle();
13772      }
13773    } // Getters
13774
13775
13776    var _proto = Collapse.prototype;
13777
13778    // Public
13779    _proto.toggle = function toggle() {
13780      if ($(this._element).hasClass(ClassName.SHOW)) {
13781        this.hide();
13782      } else {
13783        this.show();
13784      }
13785    };
13786
13787    _proto.show = function show() {
13788      var _this = this;
13789
13790      if (this._isTransitioning || $(this._element).hasClass(ClassName.SHOW)) {
13791        return;
13792      }
13793
13794      var actives;
13795      var activesData;
13796
13797      if (this._parent) {
13798        actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) {
13799          if (typeof _this._config.parent === 'string') {
13800            return elem.getAttribute('data-parent') === _this._config.parent;
13801          }
13802
13803          return elem.classList.contains(ClassName.COLLAPSE);
13804        });
13805
13806        if (actives.length === 0) {
13807          actives = null;
13808        }
13809      }
13810
13811      if (actives) {
13812        activesData = $(actives).not(this._selector).data(DATA_KEY);
13813
13814        if (activesData && activesData._isTransitioning) {
13815          return;
13816        }
13817      }
13818
13819      var startEvent = $.Event(Event.SHOW);
13820      $(this._element).trigger(startEvent);
13821
13822      if (startEvent.isDefaultPrevented()) {
13823        return;
13824      }
13825
13826      if (actives) {
13827        Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide');
13828
13829        if (!activesData) {
13830          $(actives).data(DATA_KEY, null);
13831        }
13832      }
13833
13834      var dimension = this._getDimension();
13835
13836      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
13837      this._element.style[dimension] = 0;
13838
13839      if (this._triggerArray.length) {
13840        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
13841      }
13842
13843      this.setTransitioning(true);
13844
13845      var complete = function complete() {
13846        $(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW);
13847        _this._element.style[dimension] = '';
13848
13849        _this.setTransitioning(false);
13850
13851        $(_this._element).trigger(Event.SHOWN);
13852      };
13853
13854      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
13855      var scrollSize = "scroll" + capitalizedDimension;
13856      var transitionDuration = Util.getTransitionDurationFromElement(this._element);
13857      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
13858      this._element.style[dimension] = this._element[scrollSize] + "px";
13859    };
13860
13861    _proto.hide = function hide() {
13862      var _this2 = this;
13863
13864      if (this._isTransitioning || !$(this._element).hasClass(ClassName.SHOW)) {
13865        return;
13866      }
13867
13868      var startEvent = $.Event(Event.HIDE);
13869      $(this._element).trigger(startEvent);
13870
13871      if (startEvent.isDefaultPrevented()) {
13872        return;
13873      }
13874
13875      var dimension = this._getDimension();
13876
13877      this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px";
13878      Util.reflow(this._element);
13879      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);
13880      var triggerArrayLength = this._triggerArray.length;
13881
13882      if (triggerArrayLength > 0) {
13883        for (var i = 0; i < triggerArrayLength; i++) {
13884          var trigger = this._triggerArray[i];
13885          var selector = Util.getSelectorFromElement(trigger);
13886
13887          if (selector !== null) {
13888            var $elem = $([].slice.call(document.querySelectorAll(selector)));
13889
13890            if (!$elem.hasClass(ClassName.SHOW)) {
13891              $(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
13892            }
13893          }
13894        }
13895      }
13896
13897      this.setTransitioning(true);
13898
13899      var complete = function complete() {
13900        _this2.setTransitioning(false);
13901
13902        $(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
13903      };
13904
13905      this._element.style[dimension] = '';
13906      var transitionDuration = Util.getTransitionDurationFromElement(this._element);
13907      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
13908    };
13909
13910    _proto.setTransitioning = function setTransitioning(isTransitioning) {
13911      this._isTransitioning = isTransitioning;
13912    };
13913
13914    _proto.dispose = function dispose() {
13915      $.removeData(this._element, DATA_KEY);
13916      this._config = null;
13917      this._parent = null;
13918      this._element = null;
13919      this._triggerArray = null;
13920      this._isTransitioning = null;
13921    } // Private
13922    ;
13923
13924    _proto._getConfig = function _getConfig(config) {
13925      config = _objectSpread({}, Default, config);
13926      config.toggle = Boolean(config.toggle); // Coerce string values
13927
13928      Util.typeCheckConfig(NAME, config, DefaultType);
13929      return config;
13930    };
13931
13932    _proto._getDimension = function _getDimension() {
13933      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);
13934      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
13935    };
13936
13937    _proto._getParent = function _getParent() {
13938      var _this3 = this;
13939
13940      var parent;
13941
13942      if (Util.isElement(this._config.parent)) {
13943        parent = this._config.parent; // It's a jQuery object
13944
13945        if (typeof this._config.parent.jquery !== 'undefined') {
13946          parent = this._config.parent[0];
13947        }
13948      } else {
13949        parent = document.querySelector(this._config.parent);
13950      }
13951
13952      var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]";
13953      var children = [].slice.call(parent.querySelectorAll(selector));
13954      $(children).each(function (i, element) {
13955        _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
13956      });
13957      return parent;
13958    };
13959
13960    _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
13961      var isOpen = $(element).hasClass(ClassName.SHOW);
13962
13963      if (triggerArray.length) {
13964        $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
13965      }
13966    } // Static
13967    ;
13968
13969    Collapse._getTargetFromElement = function _getTargetFromElement(element) {
13970      var selector = Util.getSelectorFromElement(element);
13971      return selector ? document.querySelector(selector) : null;
13972    };
13973
13974    Collapse._jQueryInterface = function _jQueryInterface(config) {
13975      return this.each(function () {
13976        var $this = $(this);
13977        var data = $this.data(DATA_KEY);
13978
13979        var _config = _objectSpread({}, Default, $this.data(), typeof config === 'object' && config ? config : {});
13980
13981        if (!data && _config.toggle && /show|hide/.test(config)) {
13982          _config.toggle = false;
13983        }
13984
13985        if (!data) {
13986          data = new Collapse(this, _config);
13987          $this.data(DATA_KEY, data);
13988        }
13989
13990        if (typeof config === 'string') {
13991          if (typeof data[config] === 'undefined') {
13992            throw new TypeError("No method named \"" + config + "\"");
13993          }
13994
13995          data[config]();
13996        }
13997      });
13998    };
13999
14000    _createClass(Collapse, null, [{
14001      key: "VERSION",
14002      get: function get() {
14003        return VERSION;
14004      }
14005    }, {
14006      key: "Default",
14007      get: function get() {
14008        return Default;
14009      }
14010    }]);
14011
14012    return Collapse;
14013  }();
14014  /**
14015   * ------------------------------------------------------------------------
14016   * Data Api implementation
14017   * ------------------------------------------------------------------------
14018   */
14019
14020
14021  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
14022    // preventDefault only for <a> elements (which change the URL) not inside the collapsible element
14023    if (event.currentTarget.tagName === 'A') {
14024      event.preventDefault();
14025    }
14026
14027    var $trigger = $(this);
14028    var selector = Util.getSelectorFromElement(this);
14029    var selectors = [].slice.call(document.querySelectorAll(selector));
14030    $(selectors).each(function () {
14031      var $target = $(this);
14032      var data = $target.data(DATA_KEY);
14033      var config = data ? 'toggle' : $trigger.data();
14034
14035      Collapse._jQueryInterface.call($target, config);
14036    });
14037  });
14038  /**
14039   * ------------------------------------------------------------------------
14040   * jQuery
14041   * ------------------------------------------------------------------------
14042   */
14043
14044  $.fn[NAME] = Collapse._jQueryInterface;
14045  $.fn[NAME].Constructor = Collapse;
14046
14047  $.fn[NAME].noConflict = function () {
14048    $.fn[NAME] = JQUERY_NO_CONFLICT;
14049    return Collapse._jQueryInterface;
14050  };
14051
14052  return Collapse;
14053
14054}));
14055//# sourceMappingURL=collapse.js.map
14056
14057
14058/*!
14059  * Bootstrap modal.js v4.3.1 (https://getbootstrap.com/)
14060  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
14061  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
14062  */
14063(function (global, factory) {
14064  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
14065  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
14066  (global = global || self, global.Modal = factory(global.jQuery, global.Util));
14067}(this, function ($, Util) { 'use strict';
14068
14069  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
14070  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;
14071
14072  function _defineProperties(target, props) {
14073    for (var i = 0; i < props.length; i++) {
14074      var descriptor = props[i];
14075      descriptor.enumerable = descriptor.enumerable || false;
14076      descriptor.configurable = true;
14077      if ("value" in descriptor) descriptor.writable = true;
14078      Object.defineProperty(target, descriptor.key, descriptor);
14079    }
14080  }
14081
14082  function _createClass(Constructor, protoProps, staticProps) {
14083    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
14084    if (staticProps) _defineProperties(Constructor, staticProps);
14085    return Constructor;
14086  }
14087
14088  function _defineProperty(obj, key, value) {
14089    if (key in obj) {
14090      Object.defineProperty(obj, key, {
14091        value: value,
14092        enumerable: true,
14093        configurable: true,
14094        writable: true
14095      });
14096    } else {
14097      obj[key] = value;
14098    }
14099
14100    return obj;
14101  }
14102
14103  function _objectSpread(target) {
14104    for (var i = 1; i < arguments.length; i++) {
14105      var source = arguments[i] != null ? arguments[i] : {};
14106      var ownKeys = Object.keys(source);
14107
14108      if (typeof Object.getOwnPropertySymbols === 'function') {
14109        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
14110          return Object.getOwnPropertyDescriptor(source, sym).enumerable;
14111        }));
14112      }
14113
14114      ownKeys.forEach(function (key) {
14115        _defineProperty(target, key, source[key]);
14116      });
14117    }
14118
14119    return target;
14120  }
14121
14122  /**
14123   * ------------------------------------------------------------------------
14124   * Constants
14125   * ------------------------------------------------------------------------
14126   */
14127
14128  var NAME = 'modal';
14129  var VERSION = '4.3.1';
14130  var DATA_KEY = 'bs.modal';
14131  var EVENT_KEY = "." + DATA_KEY;
14132  var DATA_API_KEY = '.data-api';
14133  var JQUERY_NO_CONFLICT = $.fn[NAME];
14134  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
14135
14136  var Default = {
14137    backdrop: true,
14138    keyboard: true,
14139    focus: true,
14140    show: true
14141  };
14142  var DefaultType = {
14143    backdrop: '(boolean|string)',
14144    keyboard: 'boolean',
14145    focus: 'boolean',
14146    show: 'boolean'
14147  };
14148  var Event = {
14149    HIDE: "hide" + EVENT_KEY,
14150    HIDDEN: "hidden" + EVENT_KEY,
14151    SHOW: "show" + EVENT_KEY,
14152    SHOWN: "shown" + EVENT_KEY,
14153    FOCUSIN: "focusin" + EVENT_KEY,
14154    RESIZE: "resize" + EVENT_KEY,
14155    CLICK_DISMISS: "click.dismiss" + EVENT_KEY,
14156    KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY,
14157    MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY,
14158    MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY,
14159    CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
14160  };
14161  var ClassName = {
14162    SCROLLABLE: 'modal-dialog-scrollable',
14163    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
14164    BACKDROP: 'modal-backdrop',
14165    OPEN: 'modal-open',
14166    FADE: 'fade',
14167    SHOW: 'show'
14168  };
14169  var Selector = {
14170    DIALOG: '.modal-dialog',
14171    MODAL_BODY: '.modal-body',
14172    DATA_TOGGLE: '[data-toggle="modal"]',
14173    DATA_DISMISS: '[data-dismiss="modal"]',
14174    FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
14175    STICKY_CONTENT: '.sticky-top'
14176    /**
14177     * ------------------------------------------------------------------------
14178     * Class Definition
14179     * ------------------------------------------------------------------------
14180     */
14181
14182  };
14183
14184  var Modal =
14185  /*#__PURE__*/
14186  function () {
14187    function Modal(element, config) {
14188      this._config = this._getConfig(config);
14189      this._element = element;
14190      this._dialog = element.querySelector(Selector.DIALOG);
14191      this._backdrop = null;
14192      this._isShown = false;
14193      this._isBodyOverflowing = false;
14194      this._ignoreBackdropClick = false;
14195      this._isTransitioning = false;
14196      this._scrollbarWidth = 0;
14197    } // Getters
14198
14199
14200    var _proto = Modal.prototype;
14201
14202    // Public
14203    _proto.toggle = function toggle(relatedTarget) {
14204      return this._isShown ? this.hide() : this.show(relatedTarget);
14205    };
14206
14207    _proto.show = function show(relatedTarget) {
14208      var _this = this;
14209
14210      if (this._isShown || this._isTransitioning) {
14211        return;
14212      }
14213
14214      if ($(this._element).hasClass(ClassName.FADE)) {
14215        this._isTransitioning = true;
14216      }
14217
14218      var showEvent = $.Event(Event.SHOW, {
14219        relatedTarget: relatedTarget
14220      });
14221      $(this._element).trigger(showEvent);
14222
14223      if (this._isShown || showEvent.isDefaultPrevented()) {
14224        return;
14225      }
14226
14227      this._isShown = true;
14228
14229      this._checkScrollbar();
14230
14231      this._setScrollbar();
14232
14233      this._adjustDialog();
14234
14235      this._setEscapeEvent();
14236
14237      this._setResizeEvent();
14238
14239      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) {
14240        return _this.hide(event);
14241      });
14242      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
14243        $(_this._element).one(Event.MOUSEUP_DISMISS, function (event) {
14244          if ($(event.target).is(_this._element)) {
14245            _this._ignoreBackdropClick = true;
14246          }
14247        });
14248      });
14249
14250      this._showBackdrop(function () {
14251        return _this._showElement(relatedTarget);
14252      });
14253    };
14254
14255    _proto.hide = function hide(event) {
14256      var _this2 = this;
14257
14258      if (event) {
14259        event.preventDefault();
14260      }
14261
14262      if (!this._isShown || this._isTransitioning) {
14263        return;
14264      }
14265
14266      var hideEvent = $.Event(Event.HIDE);
14267      $(this._element).trigger(hideEvent);
14268
14269      if (!this._isShown || hideEvent.isDefaultPrevented()) {
14270        return;
14271      }
14272
14273      this._isShown = false;
14274      var transition = $(this._element).hasClass(ClassName.FADE);
14275
14276      if (transition) {
14277        this._isTransitioning = true;
14278      }
14279
14280      this._setEscapeEvent();
14281
14282      this._setResizeEvent();
14283
14284      $(document).off(Event.FOCUSIN);
14285      $(this._element).removeClass(ClassName.SHOW);
14286      $(this._element).off(Event.CLICK_DISMISS);
14287      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);
14288
14289      if (transition) {
14290        var transitionDuration = Util.getTransitionDurationFromElement(this._element);
14291        $(this._element).one(Util.TRANSITION_END, function (event) {
14292          return _this2._hideModal(event);
14293        }).emulateTransitionEnd(transitionDuration);
14294      } else {
14295        this._hideModal();
14296      }
14297    };
14298
14299    _proto.dispose = function dispose() {
14300      [window, this._element, this._dialog].forEach(function (htmlElement) {
14301        return $(htmlElement).off(EVENT_KEY);
14302      });
14303      /**
14304       * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API`
14305       * Do not move `document` in `htmlElements` array
14306       * It will remove `Event.CLICK_DATA_API` event that should remain
14307       */
14308
14309      $(document).off(Event.FOCUSIN);
14310      $.removeData(this._element, DATA_KEY);
14311      this._config = null;
14312      this._element = null;
14313      this._dialog = null;
14314      this._backdrop = null;
14315      this._isShown = null;
14316      this._isBodyOverflowing = null;
14317      this._ignoreBackdropClick = null;
14318      this._isTransitioning = null;
14319      this._scrollbarWidth = null;
14320    };
14321
14322    _proto.handleUpdate = function handleUpdate() {
14323      this._adjustDialog();
14324    } // Private
14325    ;
14326
14327    _proto._getConfig = function _getConfig(config) {
14328      config = _objectSpread({}, Default, config);
14329      Util.typeCheckConfig(NAME, config, DefaultType);
14330      return config;
14331    };
14332
14333    _proto._showElement = function _showElement(relatedTarget) {
14334      var _this3 = this;
14335
14336      var transition = $(this._element).hasClass(ClassName.FADE);
14337
14338      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
14339        // Don't move modal's DOM position
14340        document.body.appendChild(this._element);
14341      }
14342
14343      this._element.style.display = 'block';
14344
14345      this._element.removeAttribute('aria-hidden');
14346
14347      this._element.setAttribute('aria-modal', true);
14348
14349      if ($(this._dialog).hasClass(ClassName.SCROLLABLE)) {
14350        this._dialog.querySelector(Selector.MODAL_BODY).scrollTop = 0;
14351      } else {
14352        this._element.scrollTop = 0;
14353      }
14354
14355      if (transition) {
14356        Util.reflow(this._element);
14357      }
14358
14359      $(this._element).addClass(ClassName.SHOW);
14360
14361      if (this._config.focus) {
14362        this._enforceFocus();
14363      }
14364
14365      var shownEvent = $.Event(Event.SHOWN, {
14366        relatedTarget: relatedTarget
14367      });
14368
14369      var transitionComplete = function transitionComplete() {
14370        if (_this3._config.focus) {
14371          _this3._element.focus();
14372        }
14373
14374        _this3._isTransitioning = false;
14375        $(_this3._element).trigger(shownEvent);
14376      };
14377
14378      if (transition) {
14379        var transitionDuration = Util.getTransitionDurationFromElement(this._dialog);
14380        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration);
14381      } else {
14382        transitionComplete();
14383      }
14384    };
14385
14386    _proto._enforceFocus = function _enforceFocus() {
14387      var _this4 = this;
14388
14389      $(document).off(Event.FOCUSIN) // Guard against infinite focus loop
14390      .on(Event.FOCUSIN, function (event) {
14391        if (document !== event.target && _this4._element !== event.target && $(_this4._element).has(event.target).length === 0) {
14392          _this4._element.focus();
14393        }
14394      });
14395    };
14396
14397    _proto._setEscapeEvent = function _setEscapeEvent() {
14398      var _this5 = this;
14399
14400      if (this._isShown && this._config.keyboard) {
14401        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
14402          if (event.which === ESCAPE_KEYCODE) {
14403            event.preventDefault();
14404
14405            _this5.hide();
14406          }
14407        });
14408      } else if (!this._isShown) {
14409        $(this._element).off(Event.KEYDOWN_DISMISS);
14410      }
14411    };
14412
14413    _proto._setResizeEvent = function _setResizeEvent() {
14414      var _this6 = this;
14415
14416      if (this._isShown) {
14417        $(window).on(Event.RESIZE, function (event) {
14418          return _this6.handleUpdate(event);
14419        });
14420      } else {
14421        $(window).off(Event.RESIZE);
14422      }
14423    };
14424
14425    _proto._hideModal = function _hideModal() {
14426      var _this7 = this;
14427
14428      this._element.style.display = 'none';
14429
14430      this._element.setAttribute('aria-hidden', true);
14431
14432      this._element.removeAttribute('aria-modal');
14433
14434      this._isTransitioning = false;
14435
14436      this._showBackdrop(function () {
14437        $(document.body).removeClass(ClassName.OPEN);
14438
14439        _this7._resetAdjustments();
14440
14441        _this7._resetScrollbar();
14442
14443        $(_this7._element).trigger(Event.HIDDEN);
14444      });
14445    };
14446
14447    _proto._removeBackdrop = function _removeBackdrop() {
14448      if (this._backdrop) {
14449        $(this._backdrop).remove();
14450        this._backdrop = null;
14451      }
14452    };
14453
14454    _proto._showBackdrop = function _showBackdrop(callback) {
14455      var _this8 = this;
14456
14457      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
14458
14459      if (this._isShown && this._config.backdrop) {
14460        this._backdrop = document.createElement('div');
14461        this._backdrop.className = ClassName.BACKDROP;
14462
14463        if (animate) {
14464          this._backdrop.classList.add(animate);
14465        }
14466
14467        $(this._backdrop).appendTo(document.body);
14468        $(this._element).on(Event.CLICK_DISMISS, function (event) {
14469          if (_this8._ignoreBackdropClick) {
14470            _this8._ignoreBackdropClick = false;
14471            return;
14472          }
14473
14474          if (event.target !== event.currentTarget) {
14475            return;
14476          }
14477
14478          if (_this8._config.backdrop === 'static') {
14479            _this8._element.focus();
14480          } else {
14481            _this8.hide();
14482          }
14483        });
14484
14485        if (animate) {
14486          Util.reflow(this._backdrop);
14487        }
14488
14489        $(this._backdrop).addClass(ClassName.SHOW);
14490
14491        if (!callback) {
14492          return;
14493        }
14494
14495        if (!animate) {
14496          callback();
14497          return;
14498        }
14499
14500        var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);
14501        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration);
14502      } else if (!this._isShown && this._backdrop) {
14503        $(this._backdrop).removeClass(ClassName.SHOW);
14504
14505        var callbackRemove = function callbackRemove() {
14506          _this8._removeBackdrop();
14507
14508          if (callback) {
14509            callback();
14510          }
14511        };
14512
14513        if ($(this._element).hasClass(ClassName.FADE)) {
14514          var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop);
14515
14516          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration);
14517        } else {
14518          callbackRemove();
14519        }
14520      } else if (callback) {
14521        callback();
14522      }
14523    } // ----------------------------------------------------------------------
14524    // the following methods are used to handle overflowing modals
14525    // todo (fat): these should probably be refactored out of modal.js
14526    // ----------------------------------------------------------------------
14527    ;
14528
14529    _proto._adjustDialog = function _adjustDialog() {
14530      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
14531
14532      if (!this._isBodyOverflowing && isModalOverflowing) {
14533        this._element.style.paddingLeft = this._scrollbarWidth + "px";
14534      }
14535
14536      if (this._isBodyOverflowing && !isModalOverflowing) {
14537        this._element.style.paddingRight = this._scrollbarWidth + "px";
14538      }
14539    };
14540
14541    _proto._resetAdjustments = function _resetAdjustments() {
14542      this._element.style.paddingLeft = '';
14543      this._element.style.paddingRight = '';
14544    };
14545
14546    _proto._checkScrollbar = function _checkScrollbar() {
14547      var rect = document.body.getBoundingClientRect();
14548      this._isBodyOverflowing = rect.left + rect.right < window.innerWidth;
14549      this._scrollbarWidth = this._getScrollbarWidth();
14550    };
14551
14552    _proto._setScrollbar = function _setScrollbar() {
14553      var _this9 = this;
14554
14555      if (this._isBodyOverflowing) {
14556        // Note: DOMNode.style.paddingRight returns the actual value or '' if not set
14557        //   while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
14558        var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT));
14559        var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding
14560
14561        $(fixedContent).each(function (index, element) {
14562          var actualPadding = element.style.paddingRight;
14563          var calculatedPadding = $(element).css('padding-right');
14564          $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px");
14565        }); // Adjust sticky content margin
14566
14567        $(stickyContent).each(function (index, element) {
14568          var actualMargin = element.style.marginRight;
14569          var calculatedMargin = $(element).css('margin-right');
14570          $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px");
14571        }); // Adjust body padding
14572
14573        var actualPadding = document.body.style.paddingRight;
14574        var calculatedPadding = $(document.body).css('padding-right');
14575        $(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
14576      }
14577
14578      $(document.body).addClass(ClassName.OPEN);
14579    };
14580
14581    _proto._resetScrollbar = function _resetScrollbar() {
14582      // Restore fixed content padding
14583      var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT));
14584      $(fixedContent).each(function (index, element) {
14585        var padding = $(element).data('padding-right');
14586        $(element).removeData('padding-right');
14587        element.style.paddingRight = padding ? padding : '';
14588      }); // Restore sticky content
14589
14590      var elements = [].slice.call(document.querySelectorAll("" + Selector.STICKY_CONTENT));
14591      $(elements).each(function (index, element) {
14592        var margin = $(element).data('margin-right');
14593
14594        if (typeof margin !== 'undefined') {
14595          $(element).css('margin-right', margin).removeData('margin-right');
14596        }
14597      }); // Restore body padding
14598
14599      var padding = $(document.body).data('padding-right');
14600      $(document.body).removeData('padding-right');
14601      document.body.style.paddingRight = padding ? padding : '';
14602    };
14603
14604    _proto._getScrollbarWidth = function _getScrollbarWidth() {
14605      // thx d.walsh
14606      var scrollDiv = document.createElement('div');
14607      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
14608      document.body.appendChild(scrollDiv);
14609      var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;
14610      document.body.removeChild(scrollDiv);
14611      return scrollbarWidth;
14612    } // Static
14613    ;
14614
14615    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
14616      return this.each(function () {
14617        var data = $(this).data(DATA_KEY);
14618
14619        var _config = _objectSpread({}, Default, $(this).data(), typeof config === 'object' && config ? config : {});
14620
14621        if (!data) {
14622          data = new Modal(this, _config);
14623          $(this).data(DATA_KEY, data);
14624        }
14625
14626        if (typeof config === 'string') {
14627          if (typeof data[config] === 'undefined') {
14628            throw new TypeError("No method named \"" + config + "\"");
14629          }
14630
14631          data[config](relatedTarget);
14632        } else if (_config.show) {
14633          data.show(relatedTarget);
14634        }
14635      });
14636    };
14637
14638    _createClass(Modal, null, [{
14639      key: "VERSION",
14640      get: function get() {
14641        return VERSION;
14642      }
14643    }, {
14644      key: "Default",
14645      get: function get() {
14646        return Default;
14647      }
14648    }]);
14649
14650    return Modal;
14651  }();
14652  /**
14653   * ------------------------------------------------------------------------
14654   * Data Api implementation
14655   * ------------------------------------------------------------------------
14656   */
14657
14658
14659  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
14660    var _this10 = this;
14661
14662    var target;
14663    var selector = Util.getSelectorFromElement(this);
14664
14665    if (selector) {
14666      target = document.querySelector(selector);
14667    }
14668
14669    var config = $(target).data(DATA_KEY) ? 'toggle' : _objectSpread({}, $(target).data(), $(this).data());
14670
14671    if (this.tagName === 'A' || this.tagName === 'AREA') {
14672      event.preventDefault();
14673    }
14674
14675    var $target = $(target).one(Event.SHOW, function (showEvent) {
14676      if (showEvent.isDefaultPrevented()) {
14677        // Only register focus restorer if modal will actually get shown
14678        return;
14679      }
14680
14681      $target.one(Event.HIDDEN, function () {
14682        if ($(_this10).is(':visible')) {
14683          _this10.focus();
14684        }
14685      });
14686    });
14687
14688    Modal._jQueryInterface.call($(target), config, this);
14689  });
14690  /**
14691   * ------------------------------------------------------------------------
14692   * jQuery
14693   * ------------------------------------------------------------------------
14694   */
14695
14696  $.fn[NAME] = Modal._jQueryInterface;
14697  $.fn[NAME].Constructor = Modal;
14698
14699  $.fn[NAME].noConflict = function () {
14700    $.fn[NAME] = JQUERY_NO_CONFLICT;
14701    return Modal._jQueryInterface;
14702  };
14703
14704  return Modal;
14705
14706}));
14707//# sourceMappingURL=modal.js.map
14708
14709
14710/*!
14711  * Bootstrap toast.js v4.3.1 (https://getbootstrap.com/)
14712  * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
14713  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
14714  */
14715(function (global, factory) {
14716  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery'), require('./util.js')) :
14717  typeof define === 'function' && define.amd ? define(['jquery', './util.js'], factory) :
14718  (global = global || self, global.Toast = factory(global.jQuery, global.Util));
14719}(this, function ($, Util) { 'use strict';
14720
14721  $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
14722  Util = Util && Util.hasOwnProperty('default') ? Util['default'] : Util;
14723
14724  function _defineProperties(target, props) {
14725    for (var i = 0; i < props.length; i++) {
14726      var descriptor = props[i];
14727      descriptor.enumerable = descriptor.enumerable || false;
14728      descriptor.configurable = true;
14729      if ("value" in descriptor) descriptor.writable = true;
14730      Object.defineProperty(target, descriptor.key, descriptor);
14731    }
14732  }
14733
14734  function _createClass(Constructor, protoProps, staticProps) {
14735    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
14736    if (staticProps) _defineProperties(Constructor, staticProps);
14737    return Constructor;
14738  }
14739
14740  function _defineProperty(obj, key, value) {
14741    if (key in obj) {
14742      Object.defineProperty(obj, key, {
14743        value: value,
14744        enumerable: true,
14745        configurable: true,
14746        writable: true
14747      });
14748    } else {
14749      obj[key] = value;
14750    }
14751
14752    return obj;
14753  }
14754
14755  function _objectSpread(target) {
14756    for (var i = 1; i < arguments.length; i++) {
14757      var source = arguments[i] != null ? arguments[i] : {};
14758      var ownKeys = Object.keys(source);
14759
14760      if (typeof Object.getOwnPropertySymbols === 'function') {
14761        ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
14762          return Object.getOwnPropertyDescriptor(source, sym).enumerable;
14763        }));
14764      }
14765
14766      ownKeys.forEach(function (key) {
14767        _defineProperty(target, key, source[key]);
14768      });
14769    }
14770
14771    return target;
14772  }
14773
14774  /**
14775   * ------------------------------------------------------------------------
14776   * Constants
14777   * ------------------------------------------------------------------------
14778   */
14779
14780  var NAME = 'toast';
14781  var VERSION = '4.3.1';
14782  var DATA_KEY = 'bs.toast';
14783  var EVENT_KEY = "." + DATA_KEY;
14784  var JQUERY_NO_CONFLICT = $.fn[NAME];
14785  var Event = {
14786    CLICK_DISMISS: "click.dismiss" + EVENT_KEY,
14787    HIDE: "hide" + EVENT_KEY,
14788    HIDDEN: "hidden" + EVENT_KEY,
14789    SHOW: "show" + EVENT_KEY,
14790    SHOWN: "shown" + EVENT_KEY
14791  };
14792  var ClassName = {
14793    FADE: 'fade',
14794    HIDE: 'hide',
14795    SHOW: 'show',
14796    SHOWING: 'showing'
14797  };
14798  var DefaultType = {
14799    animation: 'boolean',
14800    autohide: 'boolean',
14801    delay: 'number'
14802  };
14803  var Default = {
14804    animation: true,
14805    autohide: true,
14806    delay: 500
14807  };
14808  var Selector = {
14809    DATA_DISMISS: '[data-dismiss="toast"]'
14810    /**
14811     * ------------------------------------------------------------------------
14812     * Class Definition
14813     * ------------------------------------------------------------------------
14814     */
14815
14816  };
14817
14818  var Toast =
14819  /*#__PURE__*/
14820  function () {
14821    function Toast(element, config) {
14822      this._element = element;
14823      this._config = this._getConfig(config);
14824      this._timeout = null;
14825
14826      this._setListeners();
14827    } // Getters
14828
14829
14830    var _proto = Toast.prototype;
14831
14832    // Public
14833    _proto.show = function show() {
14834      var _this = this;
14835
14836      $(this._element).trigger(Event.SHOW);
14837
14838      if (this._config.animation) {
14839        this._element.classList.add(ClassName.FADE);
14840      }
14841
14842      var complete = function complete() {
14843        _this._element.classList.remove(ClassName.SHOWING);
14844
14845        _this._element.classList.add(ClassName.SHOW);
14846
14847        $(_this._element).trigger(Event.SHOWN);
14848
14849        if (_this._config.autohide) {
14850          _this.hide();
14851        }
14852      };
14853
14854      this._element.classList.remove(ClassName.HIDE);
14855
14856      this._element.classList.add(ClassName.SHOWING);
14857
14858      if (this._config.animation) {
14859        var transitionDuration = Util.getTransitionDurationFromElement(this._element);
14860        $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
14861      } else {
14862        complete();
14863      }
14864    };
14865
14866    _proto.hide = function hide(withoutTimeout) {
14867      var _this2 = this;
14868
14869      if (!this._element.classList.contains(ClassName.SHOW)) {
14870        return;
14871      }
14872
14873      $(this._element).trigger(Event.HIDE);
14874
14875      if (withoutTimeout) {
14876        this._close();
14877      } else {
14878        this._timeout = setTimeout(function () {
14879          _this2._close();
14880        }, this._config.delay);
14881      }
14882    };
14883
14884    _proto.dispose = function dispose() {
14885      clearTimeout(this._timeout);
14886      this._timeout = null;
14887
14888      if (this._element.classList.contains(ClassName.SHOW)) {
14889        this._element.classList.remove(ClassName.SHOW);
14890      }
14891
14892      $(this._element).off(Event.CLICK_DISMISS);
14893      $.removeData(this._element, DATA_KEY);
14894      this._element = null;
14895      this._config = null;
14896    } // Private
14897    ;
14898
14899    _proto._getConfig = function _getConfig(config) {
14900      config = _objectSpread({}, Default, $(this._element).data(), typeof config === 'object' && config ? config : {});
14901      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
14902      return config;
14903    };
14904
14905    _proto._setListeners = function _setListeners() {
14906      var _this3 = this;
14907
14908      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function () {
14909        return _this3.hide(true);
14910      });
14911    };
14912
14913    _proto._close = function _close() {
14914      var _this4 = this;
14915
14916      var complete = function complete() {
14917        _this4._element.classList.add(ClassName.HIDE);
14918
14919        $(_this4._element).trigger(Event.HIDDEN);
14920      };
14921
14922      this._element.classList.remove(ClassName.SHOW);
14923
14924      if (this._config.animation) {
14925        var transitionDuration = Util.getTransitionDurationFromElement(this._element);
14926        $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration);
14927      } else {
14928        complete();
14929      }
14930    } // Static
14931    ;
14932
14933    Toast._jQueryInterface = function _jQueryInterface(config) {
14934      return this.each(function () {
14935        var $element = $(this);
14936        var data = $element.data(DATA_KEY);
14937
14938        var _config = typeof config === 'object' && config;
14939
14940        if (!data) {
14941          data = new Toast(this, _config);
14942          $element.data(DATA_KEY, data);
14943        }
14944
14945        if (typeof config === 'string') {
14946          if (typeof data[config] === 'undefined') {
14947            throw new TypeError("No method named \"" + config + "\"");
14948          }
14949
14950          data[config](this);
14951        }
14952      });
14953    };
14954
14955    _createClass(Toast, null, [{
14956      key: "VERSION",
14957      get: function get() {
14958        return VERSION;
14959      }
14960    }, {
14961      key: "DefaultType",
14962      get: function get() {
14963        return DefaultType;
14964      }
14965    }, {
14966      key: "Default",
14967      get: function get() {
14968        return Default;
14969      }
14970    }]);
14971
14972    return Toast;
14973  }();
14974  /**
14975   * ------------------------------------------------------------------------
14976   * jQuery
14977   * ------------------------------------------------------------------------
14978   */
14979
14980
14981  $.fn[NAME] = Toast._jQueryInterface;
14982  $.fn[NAME].Constructor = Toast;
14983
14984  $.fn[NAME].noConflict = function () {
14985    $.fn[NAME] = JQUERY_NO_CONFLICT;
14986    return Toast._jQueryInterface;
14987  };
14988
14989  return Toast;
14990
14991}));
14992//# sourceMappingURL=toast.js.map
14993
14994
14995/*! PhotoSwipe Default UI - 4.1.3 - 2019-01-08
14996* http://photoswipe.com
14997* Copyright (c) 2019 Dmitry Semenov; */
14998/**
14999*
15000* UI on top of main sliding area (caption, arrows, close button, etc.).
15001* Built just using public methods/properties of PhotoSwipe.
15002* 
15003*/
15004(function (root, factory) { 
15005	if (typeof define === 'function' && define.amd) {
15006		define(factory);
15007	} else if (typeof exports === 'object') {
15008		module.exports = factory();
15009	} else {
15010		root.PhotoSwipeUI_Default = factory();
15011	}
15012})(this, function () {
15013
15014	'use strict';
15015
15016
15017
15018var PhotoSwipeUI_Default =
15019 function(pswp, framework) {
15020
15021	var ui = this;
15022	var _overlayUIUpdated = false,
15023		_controlsVisible = true,
15024		_fullscrenAPI,
15025		_controls,
15026		_captionContainer,
15027		_fakeCaptionContainer,
15028		_indexIndicator,
15029		_shareButton,
15030		_shareModal,
15031		_shareModalHidden = true,
15032		_initalCloseOnScrollValue,
15033		_isIdle,
15034		_listen,
15035
15036		_loadingIndicator,
15037		_loadingIndicatorHidden,
15038		_loadingIndicatorTimeout,
15039
15040		_galleryHasOneSlide,
15041
15042		_options,
15043		_defaultUIOptions = {
15044			barsSize: {top:44, bottom:'auto'},
15045			closeElClasses: ['item', 'caption', 'zoom-wrap', 'ui', 'top-bar'], 
15046			timeToIdle: 4000, 
15047			timeToIdleOutside: 1000,
15048			loadingIndicatorDelay: 1000, // 2s
15049			
15050			addCaptionHTMLFn: function(item, captionEl /*, isFake */) {
15051				if(!item.title) {
15052					captionEl.children[0].innerHTML = '';
15053					return false;
15054				}
15055				captionEl.children[0].innerHTML = item.title;
15056				return true;
15057			},
15058
15059			closeEl:true,
15060			captionEl: true,
15061			fullscreenEl: true,
15062			zoomEl: true,
15063			shareEl: true,
15064			counterEl: true,
15065			arrowEl: true,
15066			preloaderEl: true,
15067
15068			tapToClose: false,
15069			tapToToggleControls: true,
15070
15071			clickToCloseNonZoomable: true,
15072
15073			shareButtons: [
15074				{id:'facebook', label:'Share on Facebook', url:'https://www.facebook.com/sharer/sharer.php?u={{url}}'},
15075				{id:'twitter', label:'Tweet', url:'https://twitter.com/intent/tweet?text={{text}}&url={{url}}'},
15076				{id:'pinterest', label:'Pin it', url:'http://www.pinterest.com/pin/create/button/'+
15077													'?url={{url}}&media={{image_url}}&description={{text}}'},
15078				{id:'download', label:'Download image', url:'{{raw_image_url}}', download:true}
15079			],
15080			getImageURLForShare: function( /* shareButtonData */ ) {
15081				return pswp.currItem.src || '';
15082			},
15083			getPageURLForShare: function( /* shareButtonData */ ) {
15084				return window.location.href;
15085			},
15086			getTextForShare: function( /* shareButtonData */ ) {
15087				return pswp.currItem.title || '';
15088			},
15089				
15090			indexIndicatorSep: ' / ',
15091			fitControlsWidth: 1200
15092
15093		},
15094		_blockControlsTap,
15095		_blockControlsTapTimeout;
15096
15097
15098
15099	var _onControlsTap = function(e) {
15100			if(_blockControlsTap) {
15101				return true;
15102			}
15103
15104
15105			e = e || window.event;
15106
15107			if(_options.timeToIdle && _options.mouseUsed && !_isIdle) {
15108				// reset idle timer
15109				_onIdleMouseMove();
15110			}
15111
15112
15113			var target = e.target || e.srcElement,
15114				uiElement,
15115				clickedClass = target.getAttribute('class') || '',
15116				found;
15117
15118			for(var i = 0; i < _uiElements.length; i++) {
15119				uiElement = _uiElements[i];
15120				if(uiElement.onTap && clickedClass.indexOf('pswp__' + uiElement.name ) > -1 ) {
15121					uiElement.onTap();
15122					found = true;
15123
15124				}
15125			}
15126
15127			if(found) {
15128				if(e.stopPropagation) {
15129					e.stopPropagation();
15130				}
15131				_blockControlsTap = true;
15132
15133				// Some versions of Android don't prevent ghost click event 
15134				// when preventDefault() was called on touchstart and/or touchend.
15135				// 
15136				// This happens on v4.3, 4.2, 4.1, 
15137				// older versions strangely work correctly, 
15138				// but just in case we add delay on all of them)	
15139				var tapDelay = framework.features.isOldAndroid ? 600 : 30;
15140				_blockControlsTapTimeout = setTimeout(function() {
15141					_blockControlsTap = false;
15142				}, tapDelay);
15143			}
15144
15145		},
15146		_fitControlsInViewport = function() {
15147			return !pswp.likelyTouchDevice || _options.mouseUsed || screen.width > _options.fitControlsWidth;
15148		},
15149		_togglePswpClass = function(el, cName, add) {
15150			framework[ (add ? 'add' : 'remove') + 'Class' ](el, 'pswp__' + cName);
15151		},
15152
15153		// add class when there is just one item in the gallery
15154		// (by default it hides left/right arrows and 1ofX counter)
15155		_countNumItems = function() {
15156			var hasOneSlide = (_options.getNumItemsFn() === 1);
15157
15158			if(hasOneSlide !== _galleryHasOneSlide) {
15159				_togglePswpClass(_controls, 'ui--one-slide', hasOneSlide);
15160				_galleryHasOneSlide = hasOneSlide;
15161			}
15162		},
15163		_toggleShareModalClass = function() {
15164			_togglePswpClass(_shareModal, 'share-modal--hidden', _shareModalHidden);
15165		},
15166		_toggleShareModal = function() {
15167
15168			_shareModalHidden = !_shareModalHidden;
15169			
15170			
15171			if(!_shareModalHidden) {
15172				_toggleShareModalClass();
15173				setTimeout(function() {
15174					if(!_shareModalHidden) {
15175						framework.addClass(_shareModal, 'pswp__share-modal--fade-in');
15176					}
15177				}, 30);
15178			} else {
15179				framework.removeClass(_shareModal, 'pswp__share-modal--fade-in');
15180				setTimeout(function() {
15181					if(_shareModalHidden) {
15182						_toggleShareModalClass();
15183					}
15184				}, 300);
15185			}
15186			
15187			if(!_shareModalHidden) {
15188				_updateShareURLs();
15189			}
15190			return false;
15191		},
15192
15193		_openWindowPopup = function(e) {
15194			e = e || window.event;
15195			var target = e.target || e.srcElement;
15196
15197			pswp.shout('shareLinkClick', e, target);
15198
15199			if(!target.href) {
15200				return false;
15201			}
15202
15203			if( target.hasAttribute('download') ) {
15204				return true;
15205			}
15206
15207			window.open(target.href, 'pswp_share', 'scrollbars=yes,resizable=yes,toolbar=no,'+
15208										'location=yes,width=550,height=420,top=100,left=' + 
15209										(window.screen ? Math.round(screen.width / 2 - 275) : 100)  );
15210
15211			if(!_shareModalHidden) {
15212				_toggleShareModal();
15213			}
15214			
15215			return false;
15216		},
15217		_updateShareURLs = function() {
15218			var shareButtonOut = '',
15219				shareButtonData,
15220				shareURL,
15221				image_url,
15222				page_url,
15223				share_text;
15224
15225			for(var i = 0; i < _options.shareButtons.length; i++) {
15226				shareButtonData = _options.shareButtons[i];
15227
15228				image_url = _options.getImageURLForShare(shareButtonData);
15229				page_url = _options.getPageURLForShare(shareButtonData);
15230				share_text = _options.getTextForShare(shareButtonData);
15231
15232				shareURL = shareButtonData.url.replace('{{url}}', encodeURIComponent(page_url) )
15233									.replace('{{image_url}}', encodeURIComponent(image_url) )
15234									.replace('{{raw_image_url}}', image_url )
15235									.replace('{{text}}', encodeURIComponent(share_text) );
15236
15237				shareButtonOut += '<a href="' + shareURL + '" target="_blank" '+
15238									'class="pswp__share--' + shareButtonData.id + '"' +
15239									(shareButtonData.download ? 'download' : '') + '>' + 
15240									shareButtonData.label + '</a>';
15241
15242				if(_options.parseShareButtonOut) {
15243					shareButtonOut = _options.parseShareButtonOut(shareButtonData, shareButtonOut);
15244				}
15245			}
15246			_shareModal.children[0].innerHTML = shareButtonOut;
15247			_shareModal.children[0].onclick = _openWindowPopup;
15248
15249		},
15250		_hasCloseClass = function(target) {
15251			for(var  i = 0; i < _options.closeElClasses.length; i++) {
15252				if( framework.hasClass(target, 'pswp__' + _options.closeElClasses[i]) ) {
15253					return true;
15254				}
15255			}
15256		},
15257		_idleInterval,
15258		_idleTimer,
15259		_idleIncrement = 0,
15260		_onIdleMouseMove = function() {
15261			clearTimeout(_idleTimer);
15262			_idleIncrement = 0;
15263			if(_isIdle) {
15264				ui.setIdle(false);
15265			}
15266		},
15267		_onMouseLeaveWindow = function(e) {
15268			e = e ? e : window.event;
15269			var from = e.relatedTarget || e.toElement;
15270			if (!from || from.nodeName === 'HTML') {
15271				clearTimeout(_idleTimer);
15272				_idleTimer = setTimeout(function() {
15273					ui.setIdle(true);
15274				}, _options.timeToIdleOutside);
15275			}
15276		},
15277		_setupFullscreenAPI = function() {
15278			if(_options.fullscreenEl && !framework.features.isOldAndroid) {
15279				if(!_fullscrenAPI) {
15280					_fullscrenAPI = ui.getFullscreenAPI();
15281				}
15282				if(_fullscrenAPI) {
15283					framework.bind(document, _fullscrenAPI.eventK, ui.updateFullscreen);
15284					ui.updateFullscreen();
15285					framework.addClass(pswp.template, 'pswp--supports-fs');
15286				} else {
15287					framework.removeClass(pswp.template, 'pswp--supports-fs');
15288				}
15289			}
15290		},
15291		_setupLoadingIndicator = function() {
15292			// Setup loading indicator
15293			if(_options.preloaderEl) {
15294			
15295				_toggleLoadingIndicator(true);
15296
15297				_listen('beforeChange', function() {
15298
15299					clearTimeout(_loadingIndicatorTimeout);
15300
15301					// display loading indicator with delay
15302					_loadingIndicatorTimeout = setTimeout(function() {
15303
15304						if(pswp.currItem && pswp.currItem.loading) {
15305
15306							if( !pswp.allowProgressiveImg() || (pswp.currItem.img && !pswp.currItem.img.naturalWidth)  ) {
15307								// show preloader if progressive loading is not enabled, 
15308								// or image width is not defined yet (because of slow connection)
15309								_toggleLoadingIndicator(false); 
15310								// items-controller.js function allowProgressiveImg
15311							}
15312							
15313						} else {
15314							_toggleLoadingIndicator(true); // hide preloader
15315						}
15316
15317					}, _options.loadingIndicatorDelay);
15318					
15319				});
15320				_listen('imageLoadComplete', function(index, item) {
15321					if(pswp.currItem === item) {
15322						_toggleLoadingIndicator(true);
15323					}
15324				});
15325
15326			}
15327		},
15328		_toggleLoadingIndicator = function(hide) {
15329			if( _loadingIndicatorHidden !== hide ) {
15330				_togglePswpClass(_loadingIndicator, 'preloader--active', !hide);
15331				_loadingIndicatorHidden = hide;
15332			}
15333		},
15334		_applyNavBarGaps = function(item) {
15335			var gap = item.vGap;
15336
15337			if( _fitControlsInViewport() ) {
15338				
15339				var bars = _options.barsSize; 
15340				if(_options.captionEl && bars.bottom === 'auto') {
15341					if(!_fakeCaptionContainer) {
15342						_fakeCaptionContainer = framework.createEl('pswp__caption pswp__caption--fake');
15343						_fakeCaptionContainer.appendChild( framework.createEl('pswp__caption__center') );
15344						_controls.insertBefore(_fakeCaptionContainer, _captionContainer);
15345						framework.addClass(_controls, 'pswp__ui--fit');
15346					}
15347					if( _options.addCaptionHTMLFn(item, _fakeCaptionContainer, true) ) {
15348
15349						var captionSize = _fakeCaptionContainer.clientHeight;
15350						gap.bottom = parseInt(captionSize,10) || 44;
15351					} else {
15352						gap.bottom = bars.top; // if no caption, set size of bottom gap to size of top
15353					}
15354				} else {
15355					gap.bottom = bars.bottom === 'auto' ? 0 : bars.bottom;
15356				}
15357				
15358				// height of top bar is static, no need to calculate it
15359				gap.top = bars.top;
15360			} else {
15361				gap.top = gap.bottom = 0;
15362			}
15363		},
15364		_setupIdle = function() {
15365			// Hide controls when mouse is used
15366			if(_options.timeToIdle) {
15367				_listen('mouseUsed', function() {
15368					
15369					framework.bind(document, 'mousemove', _onIdleMouseMove);
15370					framework.bind(document, 'mouseout', _onMouseLeaveWindow);
15371
15372					_idleInterval = setInterval(function() {
15373						_idleIncrement++;
15374						if(_idleIncrement === 2) {
15375							ui.setIdle(true);
15376						}
15377					}, _options.timeToIdle / 2);
15378				});
15379			}
15380		},
15381		_setupHidingControlsDuringGestures = function() {
15382
15383			// Hide controls on vertical drag
15384			_listen('onVerticalDrag', function(now) {
15385				if(_controlsVisible && now < 0.95) {
15386					ui.hideControls();
15387				} else if(!_controlsVisible && now >= 0.95) {
15388					ui.showControls();
15389				}
15390			});
15391
15392			// Hide controls when pinching to close
15393			var pinchControlsHidden;
15394			_listen('onPinchClose' , function(now) {
15395				if(_controlsVisible && now < 0.9) {
15396					ui.hideControls();
15397					pinchControlsHidden = true;
15398				} else if(pinchControlsHidden && !_controlsVisible && now > 0.9) {
15399					ui.showControls();
15400				}
15401			});
15402
15403			_listen('zoomGestureEnded', function() {
15404				pinchControlsHidden = false;
15405				if(pinchControlsHidden && !_controlsVisible) {
15406					ui.showControls();
15407				}
15408			});
15409
15410		};
15411
15412
15413
15414	var _uiElements = [
15415		{ 
15416			name: 'caption', 
15417			option: 'captionEl',
15418			onInit: function(el) {  
15419				_captionContainer = el; 
15420			} 
15421		},
15422		{ 
15423			name: 'share-modal', 
15424			option: 'shareEl',
15425			onInit: function(el) {  
15426				_shareModal = el;
15427			},
15428			onTap: function() {
15429				_toggleShareModal();
15430			} 
15431		},
15432		{ 
15433			name: 'button--share', 
15434			option: 'shareEl',
15435			onInit: function(el) { 
15436				_shareButton = el;
15437			},
15438			onTap: function() {
15439				_toggleShareModal();
15440			} 
15441		},
15442		{ 
15443			name: 'button--zoom', 
15444			option: 'zoomEl',
15445			onTap: pswp.toggleDesktopZoom
15446		},
15447		{ 
15448			name: 'counter', 
15449			option: 'counterEl',
15450			onInit: function(el) {  
15451				_indexIndicator = el;
15452			} 
15453		},
15454		{ 
15455			name: 'button--close', 
15456			option: 'closeEl',
15457			onTap: pswp.close
15458		},
15459		{ 
15460			name: 'button--arrow--left', 
15461			option: 'arrowEl',
15462			onTap: pswp.prev
15463		},
15464		{ 
15465			name: 'button--arrow--right', 
15466			option: 'arrowEl',
15467			onTap: pswp.next
15468		},
15469		{ 
15470			name: 'button--fs', 
15471			option: 'fullscreenEl',
15472			onTap: function() {  
15473				if(_fullscrenAPI.isFullscreen()) {
15474					_fullscrenAPI.exit();
15475				} else {
15476					_fullscrenAPI.enter();
15477				}
15478			} 
15479		},
15480		{ 
15481			name: 'preloader', 
15482			option: 'preloaderEl',
15483			onInit: function(el) {  
15484				_loadingIndicator = el;
15485			} 
15486		}
15487
15488	];
15489
15490	var _setupUIElements = function() {
15491		var item,
15492			classAttr,
15493			uiElement;
15494
15495		var loopThroughChildElements = function(sChildren) {
15496			if(!sChildren) {
15497				return;
15498			}
15499
15500			var l = sChildren.length;
15501			for(var i = 0; i < l; i++) {
15502				item = sChildren[i];
15503				classAttr = item.className;
15504
15505				for(var a = 0; a < _uiElements.length; a++) {
15506					uiElement = _uiElements[a];
15507
15508					if(classAttr.indexOf('pswp__' + uiElement.name) > -1  ) {
15509
15510						if( _options[uiElement.option] ) { // if element is not disabled from options
15511							
15512							framework.removeClass(item, 'pswp__element--disabled');
15513							if(uiElement.onInit) {
15514								uiElement.onInit(item);
15515							}
15516							
15517							//item.style.display = 'block';
15518						} else {
15519							framework.addClass(item, 'pswp__element--disabled');
15520							//item.style.display = 'none';
15521						}
15522					}
15523				}
15524			}
15525		};
15526		loopThroughChildElements(_controls.children);
15527
15528		var topBar =  framework.getChildByClass(_controls, 'pswp__top-bar');
15529		if(topBar) {
15530			loopThroughChildElements( topBar.children );
15531		}
15532	};
15533
15534
15535	
15536
15537	ui.init = function() {
15538
15539		// extend options
15540		framework.extend(pswp.options, _defaultUIOptions, true);
15541
15542		// create local link for fast access
15543		_options = pswp.options;
15544
15545		// find pswp__ui element
15546		_controls = framework.getChildByClass(pswp.scrollWrap, 'pswp__ui');
15547
15548		// create local link
15549		_listen = pswp.listen;
15550
15551
15552		_setupHidingControlsDuringGestures();
15553
15554		// update controls when slides change
15555		_listen('beforeChange', ui.update);
15556
15557		// toggle zoom on double-tap
15558		_listen('doubleTap', function(point) {
15559			var initialZoomLevel = pswp.currItem.initialZoomLevel;
15560			if(pswp.getZoomLevel() !== initialZoomLevel) {
15561				pswp.zoomTo(initialZoomLevel, point, 333);
15562			} else {
15563				pswp.zoomTo(_options.getDoubleTapZoom(false, pswp.currItem), point, 333);
15564			}
15565		});
15566
15567		// Allow text selection in caption
15568		_listen('preventDragEvent', function(e, isDown, preventObj) {
15569			var t = e.target || e.srcElement;
15570			if(
15571				t && 
15572				t.getAttribute('class') && e.type.indexOf('mouse') > -1 && 
15573				( t.getAttribute('class').indexOf('__caption') > 0 || (/(SMALL|STRONG|EM)/i).test(t.tagName) ) 
15574			) {
15575				preventObj.prevent = false;
15576			}
15577		});
15578
15579		// bind events for UI
15580		_listen('bindEvents', function() {
15581			framework.bind(_controls, 'pswpTap click', _onControlsTap);
15582			framework.bind(pswp.scrollWrap, 'pswpTap', ui.onGlobalTap);
15583
15584			if(!pswp.likelyTouchDevice) {
15585				framework.bind(pswp.scrollWrap, 'mouseover', ui.onMouseOver);
15586			}
15587		});
15588
15589		// unbind events for UI
15590		_listen('unbindEvents', function() {
15591			if(!_shareModalHidden) {
15592				_toggleShareModal();
15593			}
15594
15595			if(_idleInterval) {
15596				clearInterval(_idleInterval);
15597			}
15598			framework.unbind(document, 'mouseout', _onMouseLeaveWindow);
15599			framework.unbind(document, 'mousemove', _onIdleMouseMove);
15600			framework.unbind(_controls, 'pswpTap click', _onControlsTap);
15601			framework.unbind(pswp.scrollWrap, 'pswpTap', ui.onGlobalTap);
15602			framework.unbind(pswp.scrollWrap, 'mouseover', ui.onMouseOver);
15603
15604			if(_fullscrenAPI) {
15605				framework.unbind(document, _fullscrenAPI.eventK, ui.updateFullscreen);
15606				if(_fullscrenAPI.isFullscreen()) {
15607					_options.hideAnimationDuration = 0;
15608					_fullscrenAPI.exit();
15609				}
15610				_fullscrenAPI = null;
15611			}
15612		});
15613
15614
15615		// clean up things when gallery is destroyed
15616		_listen('destroy', function() {
15617			if(_options.captionEl) {
15618				if(_fakeCaptionContainer) {
15619					_controls.removeChild(_fakeCaptionContainer);
15620				}
15621				framework.removeClass(_captionContainer, 'pswp__caption--empty');
15622			}
15623
15624			if(_shareModal) {
15625				_shareModal.children[0].onclick = null;
15626			}
15627			framework.removeClass(_controls, 'pswp__ui--over-close');
15628			framework.addClass( _controls, 'pswp__ui--hidden');
15629			ui.setIdle(false);
15630		});
15631		
15632
15633		if(!_options.showAnimationDuration) {
15634			framework.removeClass( _controls, 'pswp__ui--hidden');
15635		}
15636		_listen('initialZoomIn', function() {
15637			if(_options.showAnimationDuration) {
15638				framework.removeClass( _controls, 'pswp__ui--hidden');
15639			}
15640		});
15641		_listen('initialZoomOut', function() {
15642			framework.addClass( _controls, 'pswp__ui--hidden');
15643		});
15644
15645		_listen('parseVerticalMargin', _applyNavBarGaps);
15646		
15647		_setupUIElements();
15648
15649		if(_options.shareEl && _shareButton && _shareModal) {
15650			_shareModalHidden = true;
15651		}
15652
15653		_countNumItems();
15654
15655		_setupIdle();
15656
15657		_setupFullscreenAPI();
15658
15659		_setupLoadingIndicator();
15660	};
15661
15662	ui.setIdle = function(isIdle) {
15663		_isIdle = isIdle;
15664		_togglePswpClass(_controls, 'ui--idle', isIdle);
15665	};
15666
15667	ui.update = function() {
15668		// Don't update UI if it's hidden
15669		if(_controlsVisible && pswp.currItem) {
15670			
15671			ui.updateIndexIndicator();
15672
15673			if(_options.captionEl) {
15674				_options.addCaptionHTMLFn(pswp.currItem, _captionContainer);
15675
15676				_togglePswpClass(_captionContainer, 'caption--empty', !pswp.currItem.title);
15677			}
15678
15679			_overlayUIUpdated = true;
15680
15681		} else {
15682			_overlayUIUpdated = false;
15683		}
15684
15685		if(!_shareModalHidden) {
15686			_toggleShareModal();
15687		}
15688
15689		_countNumItems();
15690	};
15691
15692	ui.updateFullscreen = function(e) {
15693
15694		if(e) {
15695			// some browsers change window scroll position during the fullscreen
15696			// so PhotoSwipe updates it just in case
15697			setTimeout(function() {
15698				pswp.setScrollOffset( 0, framework.getScrollY() );
15699			}, 50);
15700		}
15701		
15702		// toogle pswp--fs class on root element
15703		framework[ (_fullscrenAPI.isFullscreen() ? 'add' : 'remove') + 'Class' ](pswp.template, 'pswp--fs');
15704	};
15705
15706	ui.updateIndexIndicator = function() {
15707		if(_options.counterEl) {
15708			_indexIndicator.innerHTML = (pswp.getCurrentIndex()+1) + 
15709										_options.indexIndicatorSep + 
15710										_options.getNumItemsFn();
15711		}
15712	};
15713	
15714	ui.onGlobalTap = function(e) {
15715		e = e || window.event;
15716		var target = e.target || e.srcElement;
15717
15718		if(_blockControlsTap) {
15719			return;
15720		}
15721
15722		if(e.detail && e.detail.pointerType === 'mouse') {
15723
15724			// close gallery if clicked outside of the image
15725			if(_hasCloseClass(target)) {
15726				pswp.close();
15727				return;
15728			}
15729
15730			if(framework.hasClass(target, 'pswp__img')) {
15731				if(pswp.getZoomLevel() === 1 && pswp.getZoomLevel() <= pswp.currItem.fitRatio) {
15732					if(_options.clickToCloseNonZoomable) {
15733						pswp.close();
15734					}
15735				} else {
15736					pswp.toggleDesktopZoom(e.detail.releasePoint);
15737				}
15738			}
15739			
15740		} else {
15741
15742			// tap anywhere (except buttons) to toggle visibility of controls
15743			if(_options.tapToToggleControls) {
15744				if(_controlsVisible) {
15745					ui.hideControls();
15746				} else {
15747					ui.showControls();
15748				}
15749			}
15750
15751			// tap to close gallery
15752			if(_options.tapToClose && (framework.hasClass(target, 'pswp__img') || _hasCloseClass(target)) ) {
15753				pswp.close();
15754				return;
15755			}
15756			
15757		}
15758	};
15759	ui.onMouseOver = function(e) {
15760		e = e || window.event;
15761		var target = e.target || e.srcElement;
15762
15763		// add class when mouse is over an element that should close the gallery
15764		_togglePswpClass(_controls, 'ui--over-close', _hasCloseClass(target));
15765	};
15766
15767	ui.hideControls = function() {
15768		framework.addClass(_controls,'pswp__ui--hidden');
15769		_controlsVisible = false;
15770	};
15771
15772	ui.showControls = function() {
15773		_controlsVisible = true;
15774		if(!_overlayUIUpdated) {
15775			ui.update();
15776		}
15777		framework.removeClass(_controls,'pswp__ui--hidden');
15778	};
15779
15780	ui.supportsFullscreen = function() {
15781		var d = document;
15782		return !!(d.exitFullscreen || d.mozCancelFullScreen || d.webkitExitFullscreen || d.msExitFullscreen);
15783	};
15784
15785	ui.getFullscreenAPI = function() {
15786		var dE = document.documentElement,
15787			api,
15788			tF = 'fullscreenchange';
15789
15790		if (dE.requestFullscreen) {
15791			api = {
15792				enterK: 'requestFullscreen',
15793				exitK: 'exitFullscreen',
15794				elementK: 'fullscreenElement',
15795				eventK: tF
15796			};
15797
15798		} else if(dE.mozRequestFullScreen ) {
15799			api = {
15800				enterK: 'mozRequestFullScreen',
15801				exitK: 'mozCancelFullScreen',
15802				elementK: 'mozFullScreenElement',
15803				eventK: 'moz' + tF
15804			};
15805
15806			
15807
15808		} else if(dE.webkitRequestFullscreen) {
15809			api = {
15810				enterK: 'webkitRequestFullscreen',
15811				exitK: 'webkitExitFullscreen',
15812				elementK: 'webkitFullscreenElement',
15813				eventK: 'webkit' + tF
15814			};
15815
15816		} else if(dE.msRequestFullscreen) {
15817			api = {
15818				enterK: 'msRequestFullscreen',
15819				exitK: 'msExitFullscreen',
15820				elementK: 'msFullscreenElement',
15821				eventK: 'MSFullscreenChange'
15822			};
15823		}
15824
15825		if(api) {
15826			api.enter = function() { 
15827				// disable close-on-scroll in fullscreen
15828				_initalCloseOnScrollValue = _options.closeOnScroll; 
15829				_options.closeOnScroll = false; 
15830
15831				if(this.enterK === 'webkitRequestFullscreen') {
15832					pswp.template[this.enterK]( Element.ALLOW_KEYBOARD_INPUT );
15833				} else {
15834					return pswp.template[this.enterK](); 
15835				}
15836			};
15837			api.exit = function() { 
15838				_options.closeOnScroll = _initalCloseOnScrollValue;
15839
15840				return document[this.exitK](); 
15841
15842			};
15843			api.isFullscreen = function() { return document[this.elementK]; };
15844		}
15845
15846		return api;
15847	};
15848
15849
15850
15851};
15852return PhotoSwipeUI_Default;
15853
15854
15855});
15856
15857
15858/*! PhotoSwipe - v4.1.3 - 2019-01-08
15859* http://photoswipe.com
15860* Copyright (c) 2019 Dmitry Semenov; */
15861(function (root, factory) { 
15862	if (typeof define === 'function' && define.amd) {
15863		define(factory);
15864	} else if (typeof exports === 'object') {
15865		module.exports = factory();
15866	} else {
15867		root.PhotoSwipe = factory();
15868	}
15869})(this, function () {
15870
15871	'use strict';
15872	var PhotoSwipe = function(template, UiClass, items, options){
15873
15874/*>>framework-bridge*/
15875/**
15876 *
15877 * Set of generic functions used by gallery.
15878 * 
15879 * You're free to modify anything here as long as functionality is kept.
15880 * 
15881 */
15882var framework = {
15883	features: null,
15884	bind: function(target, type, listener, unbind) {
15885		var methodName = (unbind ? 'remove' : 'add') + 'EventListener';
15886		type = type.split(' ');
15887		for(var i = 0; i < type.length; i++) {
15888			if(type[i]) {
15889				target[methodName]( type[i], listener, false);
15890			}
15891		}
15892	},
15893	isArray: function(obj) {
15894		return (obj instanceof Array);
15895	},
15896	createEl: function(classes, tag) {
15897		var el = document.createElement(tag || 'div');
15898		if(classes) {
15899			el.className = classes;
15900		}
15901		return el;
15902	},
15903	getScrollY: function() {
15904		var yOffset = window.pageYOffset;
15905		return yOffset !== undefined ? yOffset : document.documentElement.scrollTop;
15906	},
15907	unbind: function(target, type, listener) {
15908		framework.bind(target,type,listener,true);
15909	},
15910	removeClass: function(el, className) {
15911		var reg = new RegExp('(\\s|^)' + className + '(\\s|$)');
15912		el.className = el.className.replace(reg, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 
15913	},
15914	addClass: function(el, className) {
15915		if( !framework.hasClass(el,className) ) {
15916			el.className += (el.className ? ' ' : '') + className;
15917		}
15918	},
15919	hasClass: function(el, className) {
15920		return el.className && new RegExp('(^|\\s)' + className + '(\\s|$)').test(el.className);
15921	},
15922	getChildByClass: function(parentEl, childClassName) {
15923		var node = parentEl.firstChild;
15924		while(node) {
15925			if( framework.hasClass(node, childClassName) ) {
15926				return node;
15927			}
15928			node = node.nextSibling;
15929		}
15930	},
15931	arraySearch: function(array, value, key) {
15932		var i = array.length;
15933		while(i--) {
15934			if(array[i][key] === value) {
15935				return i;
15936			} 
15937		}
15938		return -1;
15939	},
15940	extend: function(o1, o2, preventOverwrite) {
15941		for (var prop in o2) {
15942			if (o2.hasOwnProperty(prop)) {
15943				if(preventOverwrite && o1.hasOwnProperty(prop)) {
15944					continue;
15945				}
15946				o1[prop] = o2[prop];
15947			}
15948		}
15949	},
15950	easing: {
15951		sine: {
15952			out: function(k) {
15953				return Math.sin(k * (Math.PI / 2));
15954			},
15955			inOut: function(k) {
15956				return - (Math.cos(Math.PI * k) - 1) / 2;
15957			}
15958		},
15959		cubic: {
15960			out: function(k) {
15961				return --k * k * k + 1;
15962			}
15963		}
15964		/*
15965			elastic: {
15966				out: function ( k ) {
15967
15968					var s, a = 0.1, p = 0.4;
15969					if ( k === 0 ) return 0;
15970					if ( k === 1 ) return 1;
15971					if ( !a || a < 1 ) { a = 1; s = p / 4; }
15972					else s = p * Math.asin( 1 / a ) / ( 2 * Math.PI );
15973					return ( a * Math.pow( 2, - 10 * k) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) + 1 );
15974
15975				},
15976			},
15977			back: {
15978				out: function ( k ) {
15979					var s = 1.70158;
15980					return --k * k * ( ( s + 1 ) * k + s ) + 1;
15981				}
15982			}
15983		*/
15984	},
15985
15986	/**
15987	 * 
15988	 * @return {object}
15989	 * 
15990	 * {
15991	 *  raf : request animation frame function
15992	 *  caf : cancel animation frame function
15993	 *  transfrom : transform property key (with vendor), or null if not supported
15994	 *  oldIE : IE8 or below
15995	 * }
15996	 * 
15997	 */
15998	detectFeatures: function() {
15999		if(framework.features) {
16000			return framework.features;
16001		}
16002		var helperEl = framework.createEl(),
16003			helperStyle = helperEl.style,
16004			vendor = '',
16005			features = {};
16006
16007		// IE8 and below
16008		features.oldIE = document.all && !document.addEventListener;
16009
16010		features.touch = 'ontouchstart' in window;
16011
16012		if(window.requestAnimationFrame) {
16013			features.raf = window.requestAnimationFrame;
16014			features.caf = window.cancelAnimationFrame;
16015		}
16016
16017		features.pointerEvent = !!(window.PointerEvent) || navigator.msPointerEnabled;
16018
16019		// fix false-positive detection of old Android in new IE
16020		// (IE11 ua string contains "Android 4.0")
16021		
16022		if(!features.pointerEvent) { 
16023
16024			var ua = navigator.userAgent;
16025
16026			// Detect if device is iPhone or iPod and if it's older than iOS 8
16027			// http://stackoverflow.com/a/14223920
16028			// 
16029			// This detection is made because of buggy top/bottom toolbars
16030			// that don't trigger window.resize event.
16031			// For more info refer to _isFixedPosition variable in core.js
16032
16033			if (/iP(hone|od)/.test(navigator.platform)) {
16034				var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
16035				if(v && v.length > 0) {
16036					v = parseInt(v[1], 10);
16037					if(v >= 1 && v < 8 ) {
16038						features.isOldIOSPhone = true;
16039					}
16040				}
16041			}
16042
16043			// Detect old Android (before KitKat)
16044			// due to bugs related to position:fixed
16045			// http://stackoverflow.com/questions/7184573/pick-up-the-android-version-in-the-browser-by-javascript
16046			
16047			var match = ua.match(/Android\s([0-9\.]*)/);
16048			var androidversion =  match ? match[1] : 0;
16049			androidversion = parseFloat(androidversion);
16050			if(androidversion >= 1 ) {
16051				if(androidversion < 4.4) {
16052					features.isOldAndroid = true; // for fixed position bug & performance
16053				}
16054				features.androidVersion = androidversion; // for touchend bug
16055			}	
16056			features.isMobileOpera = /opera mini|opera mobi/i.test(ua);
16057
16058			// p.s. yes, yes, UA sniffing is bad, propose your solution for above bugs.
16059		}
16060		
16061		var styleChecks = ['transform', 'perspective', 'animationName'],
16062			vendors = ['', 'webkit','Moz','ms','O'],
16063			styleCheckItem,
16064			styleName;
16065
16066		for(var i = 0; i < 4; i++) {
16067			vendor = vendors[i];
16068
16069			for(var a = 0; a < 3; a++) {
16070				styleCheckItem = styleChecks[a];
16071
16072				// uppercase first letter of property name, if vendor is present
16073				styleName = vendor + (vendor ? 
16074										styleCheckItem.charAt(0).toUpperCase() + styleCheckItem.slice(1) : 
16075										styleCheckItem);
16076			
16077				if(!features[styleCheckItem] && styleName in helperStyle ) {
16078					features[styleCheckItem] = styleName;
16079				}
16080			}
16081
16082			if(vendor && !features.raf) {
16083				vendor = vendor.toLowerCase();
16084				features.raf = window[vendor+'RequestAnimationFrame'];
16085				if(features.raf) {
16086					features.caf = window[vendor+'CancelAnimationFrame'] || 
16087									window[vendor+'CancelRequestAnimationFrame'];
16088				}
16089			}
16090		}
16091			
16092		if(!features.raf) {
16093			var lastTime = 0;
16094			features.raf = function(fn) {
16095				var currTime = new Date().getTime();
16096				var timeToCall = Math.max(0, 16 - (currTime - lastTime));
16097				var id = window.setTimeout(function() { fn(currTime + timeToCall); }, timeToCall);
16098				lastTime = currTime + timeToCall;
16099				return id;
16100			};
16101			features.caf = function(id) { clearTimeout(id); };
16102		}
16103
16104		// Detect SVG support
16105		features.svg = !!document.createElementNS && 
16106						!!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect;
16107
16108		framework.features = features;
16109
16110		return features;
16111	}
16112};
16113
16114framework.detectFeatures();
16115
16116// Override addEventListener for old versions of IE
16117if(framework.features.oldIE) {
16118
16119	framework.bind = function(target, type, listener, unbind) {
16120		
16121		type = type.split(' ');
16122
16123		var methodName = (unbind ? 'detach' : 'attach') + 'Event',
16124			evName,
16125			_handleEv = function() {
16126				listener.handleEvent.call(listener);
16127			};
16128
16129		for(var i = 0; i < type.length; i++) {
16130			evName = type[i];
16131			if(evName) {
16132
16133				if(typeof listener === 'object' && listener.handleEvent) {
16134					if(!unbind) {
16135						listener['oldIE' + evName] = _handleEv;
16136					} else {
16137						if(!listener['oldIE' + evName]) {
16138							return false;
16139						}
16140					}
16141
16142					target[methodName]( 'on' + evName, listener['oldIE' + evName]);
16143				} else {
16144					target[methodName]( 'on' + evName, listener);
16145				}
16146
16147			}
16148		}
16149	};
16150	
16151}
16152
16153/*>>framework-bridge*/
16154
16155/*>>core*/
16156//function(template, UiClass, items, options)
16157
16158var self = this;
16159
16160/**
16161 * Static vars, don't change unless you know what you're doing.
16162 */
16163var DOUBLE_TAP_RADIUS = 25, 
16164	NUM_HOLDERS = 3;
16165
16166/**
16167 * Options
16168 */
16169var _options = {
16170	allowPanToNext:true,
16171	spacing: 0.12,
16172	bgOpacity: 1,
16173	mouseUsed: false,
16174	loop: true,
16175	pinchToClose: true,
16176	closeOnScroll: true,
16177	closeOnVerticalDrag: true,
16178	verticalDragRange: 0.75,
16179	hideAnimationDuration: 333,
16180	showAnimationDuration: 333,
16181	showHideOpacity: false,
16182	focus: true,
16183	escKey: true,
16184	arrowKeys: true,
16185	mainScrollEndFriction: 0.35,
16186	panEndFriction: 0.35,
16187	isClickableElement: function(el) {
16188        return el.tagName === 'A';
16189    },
16190    getDoubleTapZoom: function(isMouseClick, item) {
16191    	if(isMouseClick) {
16192    		return 1;
16193    	} else {
16194    		return item.initialZoomLevel < 0.7 ? 1 : 1.33;
16195    	}
16196    },
16197    maxSpreadZoom: 1.33,
16198	modal: true,
16199
16200	// not fully implemented yet
16201	scaleMode: 'fit' // TODO
16202};
16203framework.extend(_options, options);
16204
16205
16206/**
16207 * Private helper variables & functions
16208 */
16209
16210var _getEmptyPoint = function() { 
16211		return {x:0,y:0}; 
16212	};
16213
16214var _isOpen,
16215	_isDestroying,
16216	_closedByScroll,
16217	_currentItemIndex,
16218	_containerStyle,
16219	_containerShiftIndex,
16220	_currPanDist = _getEmptyPoint(),
16221	_startPanOffset = _getEmptyPoint(),
16222	_panOffset = _getEmptyPoint(),
16223	_upMoveEvents, // drag move, drag end & drag cancel events array
16224	_downEvents, // drag start events array
16225	_globalEventHandlers,
16226	_viewportSize = {},
16227	_currZoomLevel,
16228	_startZoomLevel,
16229	_translatePrefix,
16230	_translateSufix,
16231	_updateSizeInterval,
16232	_itemsNeedUpdate,
16233	_currPositionIndex = 0,
16234	_offset = {},
16235	_slideSize = _getEmptyPoint(), // size of slide area, including spacing
16236	_itemHolders,
16237	_prevItemIndex,
16238	_indexDiff = 0, // difference of indexes since last content update
16239	_dragStartEvent,
16240	_dragMoveEvent,
16241	_dragEndEvent,
16242	_dragCancelEvent,
16243	_transformKey,
16244	_pointerEventEnabled,
16245	_isFixedPosition = true,
16246	_likelyTouchDevice,
16247	_modules = [],
16248	_requestAF,
16249	_cancelAF,
16250	_initalClassName,
16251	_initalWindowScrollY,
16252	_oldIE,
16253	_currentWindowScrollY,
16254	_features,
16255	_windowVisibleSize = {},
16256	_renderMaxResolution = false,
16257	_orientationChangeTimeout,
16258
16259
16260	// Registers PhotoSWipe module (History, Controller ...)
16261	_registerModule = function(name, module) {
16262		framework.extend(self, module.publicMethods);
16263		_modules.push(name);
16264	},
16265
16266	_getLoopedId = function(index) {
16267		var numSlides = _getNumItems();
16268		if(index > numSlides - 1) {
16269			return index - numSlides;
16270		} else  if(index < 0) {
16271			return numSlides + index;
16272		}
16273		return index;
16274	},
16275	
16276	// Micro bind/trigger
16277	_listeners = {},
16278	_listen = function(name, fn) {
16279		if(!_listeners[name]) {
16280			_listeners[name] = [];
16281		}
16282		return _listeners[name].push(fn);
16283	},
16284	_shout = function(name) {
16285		var listeners = _listeners[name];
16286
16287		if(listeners) {
16288			var args = Array.prototype.slice.call(arguments);
16289			args.shift();
16290
16291			for(var i = 0; i < listeners.length; i++) {
16292				listeners[i].apply(self, args);
16293			}
16294		}
16295	},
16296
16297	_getCurrentTime = function() {
16298		return new Date().getTime();
16299	},
16300	_applyBgOpacity = function(opacity) {
16301		_bgOpacity = opacity;
16302		self.bg.style.opacity = opacity * _options.bgOpacity;
16303	},
16304
16305	_applyZoomTransform = function(styleObj,x,y,zoom,item) {
16306		if(!_renderMaxResolution || (item && item !== self.currItem) ) {
16307			zoom = zoom / (item ? item.fitRatio : self.currItem.fitRatio);	
16308		}
16309			
16310		styleObj[_transformKey] = _translatePrefix + x + 'px, ' + y + 'px' + _translateSufix + ' scale(' + zoom + ')';
16311	},
16312	_applyCurrentZoomPan = function( allowRenderResolution ) {
16313		if(_currZoomElementStyle) {
16314
16315			if(allowRenderResolution) {
16316				if(_currZoomLevel > self.currItem.fitRatio) {
16317					if(!_renderMaxResolution) {
16318						_setImageSize(self.currItem, false, true);
16319						_renderMaxResolution = true;
16320					}
16321				} else {
16322					if(_renderMaxResolution) {
16323						_setImageSize(self.currItem);
16324						_renderMaxResolution = false;
16325					}
16326				}
16327			}
16328			
16329
16330			_applyZoomTransform(_currZoomElementStyle, _panOffset.x, _panOffset.y, _currZoomLevel);
16331		}
16332	},
16333	_applyZoomPanToItem = function(item) {
16334		if(item.container) {
16335
16336			_applyZoomTransform(item.container.style, 
16337								item.initialPosition.x, 
16338								item.initialPosition.y, 
16339								item.initialZoomLevel,
16340								item);
16341		}
16342	},
16343	_setTranslateX = function(x, elStyle) {
16344		elStyle[_transformKey] = _translatePrefix + x + 'px, 0px' + _translateSufix;
16345	},
16346	_moveMainScroll = function(x, dragging) {
16347
16348		if(!_options.loop && dragging) {
16349			var newSlideIndexOffset = _currentItemIndex + (_slideSize.x * _currPositionIndex - x) / _slideSize.x,
16350				delta = Math.round(x - _mainScrollPos.x);
16351
16352			if( (newSlideIndexOffset < 0 && delta > 0) || 
16353				(newSlideIndexOffset >= _getNumItems() - 1 && delta < 0) ) {
16354				x = _mainScrollPos.x + delta * _options.mainScrollEndFriction;
16355			} 
16356		}
16357		
16358		_mainScrollPos.x = x;
16359		_setTranslateX(x, _containerStyle);
16360	},
16361	_calculatePanOffset = function(axis, zoomLevel) {
16362		var m = _midZoomPoint[axis] - _offset[axis];
16363		return _startPanOffset[axis] + _currPanDist[axis] + m - m * ( zoomLevel / _startZoomLevel );
16364	},
16365	
16366	_equalizePoints = function(p1, p2) {
16367		p1.x = p2.x;
16368		p1.y = p2.y;
16369		if(p2.id) {
16370			p1.id = p2.id;
16371		}
16372	},
16373	_roundPoint = function(p) {
16374		p.x = Math.round(p.x);
16375		p.y = Math.round(p.y);
16376	},
16377
16378	_mouseMoveTimeout = null,
16379	_onFirstMouseMove = function() {
16380		// Wait until mouse move event is fired at least twice during 100ms
16381		// We do this, because some mobile browsers trigger it on touchstart
16382		if(_mouseMoveTimeout ) { 
16383			framework.unbind(document, 'mousemove', _onFirstMouseMove);
16384			framework.addClass(template, 'pswp--has_mouse');
16385			_options.mouseUsed = true;
16386			_shout('mouseUsed');
16387		}
16388		_mouseMoveTimeout = setTimeout(function() {
16389			_mouseMoveTimeout = null;
16390		}, 100);
16391	},
16392
16393	_bindEvents = function() {
16394		framework.bind(document, 'keydown', self);
16395
16396		if(_features.transform) {
16397			// don't bind click event in browsers that don't support transform (mostly IE8)
16398			framework.bind(self.scrollWrap, 'click', self);
16399		}
16400		
16401
16402		if(!_options.mouseUsed) {
16403			framework.bind(document, 'mousemove', _onFirstMouseMove);
16404		}
16405
16406		framework.bind(window, 'resize scroll orientationchange', self);
16407
16408		_shout('bindEvents');
16409	},
16410
16411	_unbindEvents = function() {
16412		framework.unbind(window, 'resize scroll orientationchange', self);
16413		framework.unbind(window, 'scroll', _globalEventHandlers.scroll);
16414		framework.unbind(document, 'keydown', self);
16415		framework.unbind(document, 'mousemove', _onFirstMouseMove);
16416
16417		if(_features.transform) {
16418			framework.unbind(self.scrollWrap, 'click', self);
16419		}
16420
16421		if(_isDragging) {
16422			framework.unbind(window, _upMoveEvents, self);
16423		}
16424
16425		clearTimeout(_orientationChangeTimeout);
16426
16427		_shout('unbindEvents');
16428	},
16429	
16430	_calculatePanBounds = function(zoomLevel, update) {
16431		var bounds = _calculateItemSize( self.currItem, _viewportSize, zoomLevel );
16432		if(update) {
16433			_currPanBounds = bounds;
16434		}
16435		return bounds;
16436	},
16437	
16438	_getMinZoomLevel = function(item) {
16439		if(!item) {
16440			item = self.currItem;
16441		}
16442		return item.initialZoomLevel;
16443	},
16444	_getMaxZoomLevel = function(item) {
16445		if(!item) {
16446			item = self.currItem;
16447		}
16448		return item.w > 0 ? _options.maxSpreadZoom : 1;
16449	},
16450
16451	// Return true if offset is out of the bounds
16452	_modifyDestPanOffset = function(axis, destPanBounds, destPanOffset, destZoomLevel) {
16453		if(destZoomLevel === self.currItem.initialZoomLevel) {
16454			destPanOffset[axis] = self.currItem.initialPosition[axis];
16455			return true;
16456		} else {
16457			destPanOffset[axis] = _calculatePanOffset(axis, destZoomLevel); 
16458
16459			if(destPanOffset[axis] > destPanBounds.min[axis]) {
16460				destPanOffset[axis] = destPanBounds.min[axis];
16461				return true;
16462			} else if(destPanOffset[axis] < destPanBounds.max[axis] ) {
16463				destPanOffset[axis] = destPanBounds.max[axis];
16464				return true;
16465			}
16466		}
16467		return false;
16468	},
16469
16470	_setupTransforms = function() {
16471
16472		if(_transformKey) {
16473			// setup 3d transforms
16474			var allow3dTransform = _features.perspective && !_likelyTouchDevice;
16475			_translatePrefix = 'translate' + (allow3dTransform ? '3d(' : '(');
16476			_translateSufix = _features.perspective ? ', 0px)' : ')';	
16477			return;
16478		}
16479
16480		// Override zoom/pan/move functions in case old browser is used (most likely IE)
16481		// (so they use left/top/width/height, instead of CSS transform)
16482	
16483		_transformKey = 'left';
16484		framework.addClass(template, 'pswp--ie');
16485
16486		_setTranslateX = function(x, elStyle) {
16487			elStyle.left = x + 'px';
16488		};
16489		_applyZoomPanToItem = function(item) {
16490
16491			var zoomRatio = item.fitRatio > 1 ? 1 : item.fitRatio,
16492				s = item.container.style,
16493				w = zoomRatio * item.w,
16494				h = zoomRatio * item.h;
16495
16496			s.width = w + 'px';
16497			s.height = h + 'px';
16498			s.left = item.initialPosition.x + 'px';
16499			s.top = item.initialPosition.y + 'px';
16500
16501		};
16502		_applyCurrentZoomPan = function() {
16503			if(_currZoomElementStyle) {
16504
16505				var s = _currZoomElementStyle,
16506					item = self.currItem,
16507					zoomRatio = item.fitRatio > 1 ? 1 : item.fitRatio,
16508					w = zoomRatio * item.w,
16509					h = zoomRatio * item.h;
16510
16511				s.width = w + 'px';
16512				s.height = h + 'px';
16513
16514
16515				s.left = _panOffset.x + 'px';
16516				s.top = _panOffset.y + 'px';
16517			}
16518			
16519		};
16520	},
16521
16522	_onKeyDown = function(e) {
16523		var keydownAction = '';
16524		if(_options.escKey && e.keyCode === 27) { 
16525			keydownAction = 'close';
16526		} else if(_options.arrowKeys) {
16527			if(e.keyCode === 37) {
16528				keydownAction = 'prev';
16529			} else if(e.keyCode === 39) { 
16530				keydownAction = 'next';
16531			}
16532		}
16533
16534		if(keydownAction) {
16535			// don't do anything if special key pressed to prevent from overriding default browser actions
16536			// e.g. in Chrome on Mac cmd+arrow-left returns to previous page
16537			if( !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey ) {
16538				if(e.preventDefault) {
16539					e.preventDefault();
16540				} else {
16541					e.returnValue = false;
16542				} 
16543				self[keydownAction]();
16544			}
16545		}
16546	},
16547
16548	_onGlobalClick = function(e) {
16549		if(!e) {
16550			return;
16551		}
16552
16553		// don't allow click event to pass through when triggering after drag or some other gesture
16554		if(_moved || _zoomStarted || _mainScrollAnimating || _verticalDragInitiated) {
16555			e.preventDefault();
16556			e.stopPropagation();
16557		}
16558	},
16559
16560	_updatePageScrollOffset = function() {
16561		self.setScrollOffset(0, framework.getScrollY());		
16562	};
16563	
16564
16565
16566	
16567
16568
16569
16570// Micro animation engine
16571var _animations = {},
16572	_numAnimations = 0,
16573	_stopAnimation = function(name) {
16574		if(_animations[name]) {
16575			if(_animations[name].raf) {
16576				_cancelAF( _animations[name].raf );
16577			}
16578			_numAnimations--;
16579			delete _animations[name];
16580		}
16581	},
16582	_registerStartAnimation = function(name) {
16583		if(_animations[name]) {
16584			_stopAnimation(name);
16585		}
16586		if(!_animations[name]) {
16587			_numAnimations++;
16588			_animations[name] = {};
16589		}
16590	},
16591	_stopAllAnimations = function() {
16592		for (var prop in _animations) {
16593
16594			if( _animations.hasOwnProperty( prop ) ) {
16595				_stopAnimation(prop);
16596			} 
16597			
16598		}
16599	},
16600	_animateProp = function(name, b, endProp, d, easingFn, onUpdate, onComplete) {
16601		var startAnimTime = _getCurrentTime(), t;
16602		_registerStartAnimation(name);
16603
16604		var animloop = function(){
16605			if ( _animations[name] ) {
16606				
16607				t = _getCurrentTime() - startAnimTime; // time diff
16608				//b - beginning (start prop)
16609				//d - anim duration
16610
16611				if ( t >= d ) {
16612					_stopAnimation(name);
16613					onUpdate(endProp);
16614					if(onComplete) {
16615						onComplete();
16616					}
16617					return;
16618				}
16619				onUpdate( (endProp - b) * easingFn(t/d) + b );
16620
16621				_animations[name].raf = _requestAF(animloop);
16622			}
16623		};
16624		animloop();
16625	};
16626	
16627
16628
16629var publicMethods = {
16630
16631	// make a few local variables and functions public
16632	shout: _shout,
16633	listen: _listen,
16634	viewportSize: _viewportSize,
16635	options: _options,
16636
16637	isMainScrollAnimating: function() {
16638		return _mainScrollAnimating;
16639	},
16640	getZoomLevel: function() {
16641		return _currZoomLevel;
16642	},
16643	getCurrentIndex: function() {
16644		return _currentItemIndex;
16645	},
16646	isDragging: function() {
16647		return _isDragging;
16648	},	
16649	isZooming: function() {
16650		return _isZooming;
16651	},
16652	setScrollOffset: function(x,y) {
16653		_offset.x = x;
16654		_currentWindowScrollY = _offset.y = y;
16655		_shout('updateScrollOffset', _offset);
16656	},
16657	applyZoomPan: function(zoomLevel,panX,panY,allowRenderResolution) {
16658		_panOffset.x = panX;
16659		_panOffset.y = panY;
16660		_currZoomLevel = zoomLevel;
16661		_applyCurrentZoomPan( allowRenderResolution );
16662	},
16663
16664	init: function() {
16665
16666		if(_isOpen || _isDestroying) {
16667			return;
16668		}
16669
16670		var i;
16671
16672		self.framework = framework; // basic functionality
16673		self.template = template; // root DOM element of PhotoSwipe
16674		self.bg = framework.getChildByClass(template, 'pswp__bg');
16675
16676		_initalClassName = template.className;
16677		_isOpen = true;
16678				
16679		_features = framework.detectFeatures();
16680		_requestAF = _features.raf;
16681		_cancelAF = _features.caf;
16682		_transformKey = _features.transform;
16683		_oldIE = _features.oldIE;
16684		
16685		self.scrollWrap = framework.getChildByClass(template, 'pswp__scroll-wrap');
16686		self.container = framework.getChildByClass(self.scrollWrap, 'pswp__container');
16687
16688		_containerStyle = self.container.style; // for fast access
16689
16690		// Objects that hold slides (there are only 3 in DOM)
16691		self.itemHolders = _itemHolders = [
16692			{el:self.container.children[0] , wrap:0, index: -1},
16693			{el:self.container.children[1] , wrap:0, index: -1},
16694			{el:self.container.children[2] , wrap:0, index: -1}
16695		];
16696
16697		// hide nearby item holders until initial zoom animation finishes (to avoid extra Paints)
16698		_itemHolders[0].el.style.display = _itemHolders[2].el.style.display = 'none';
16699
16700		_setupTransforms();
16701
16702		// Setup global events
16703		_globalEventHandlers = {
16704			resize: self.updateSize,
16705
16706			// Fixes: iOS 10.3 resize event
16707			// does not update scrollWrap.clientWidth instantly after resize
16708			// https://github.com/dimsemenov/PhotoSwipe/issues/1315
16709			orientationchange: function() {
16710				clearTimeout(_orientationChangeTimeout);
16711				_orientationChangeTimeout = setTimeout(function() {
16712					if(_viewportSize.x !== self.scrollWrap.clientWidth) {
16713						self.updateSize();
16714					}
16715				}, 500);
16716			},
16717			scroll: _updatePageScrollOffset,
16718			keydown: _onKeyDown,
16719			click: _onGlobalClick
16720		};
16721
16722		// disable show/hide effects on old browsers that don't support CSS animations or transforms, 
16723		// old IOS, Android and Opera mobile. Blackberry seems to work fine, even older models.
16724		var oldPhone = _features.isOldIOSPhone || _features.isOldAndroid || _features.isMobileOpera;
16725		if(!_features.animationName || !_features.transform || oldPhone) {
16726			_options.showAnimationDuration = _options.hideAnimationDuration = 0;
16727		}
16728
16729		// init modules
16730		for(i = 0; i < _modules.length; i++) {
16731			self['init' + _modules[i]]();
16732		}
16733		
16734		// init
16735		if(UiClass) {
16736			var ui = self.ui = new UiClass(self, framework);
16737			ui.init();
16738		}
16739
16740		_shout('firstUpdate');
16741		_currentItemIndex = _currentItemIndex || _options.index || 0;
16742		// validate index
16743		if( isNaN(_currentItemIndex) || _currentItemIndex < 0 || _currentItemIndex >= _getNumItems() ) {
16744			_currentItemIndex = 0;
16745		}
16746		self.currItem = _getItemAt( _currentItemIndex );
16747
16748		
16749		if(_features.isOldIOSPhone || _features.isOldAndroid) {
16750			_isFixedPosition = false;
16751		}
16752		
16753		template.setAttribute('aria-hidden', 'false');
16754		if(_options.modal) {
16755			if(!_isFixedPosition) {
16756				template.style.position = 'absolute';
16757				template.style.top = framework.getScrollY() + 'px';
16758			} else {
16759				template.style.position = 'fixed';
16760			}
16761		}
16762
16763		if(_currentWindowScrollY === undefined) {
16764			_shout('initialLayout');
16765			_currentWindowScrollY = _initalWindowScrollY = framework.getScrollY();
16766		}
16767		
16768		// add classes to root element of PhotoSwipe
16769		var rootClasses = 'pswp--open ';
16770		if(_options.mainClass) {
16771			rootClasses += _options.mainClass + ' ';
16772		}
16773		if(_options.showHideOpacity) {
16774			rootClasses += 'pswp--animate_opacity ';
16775		}
16776		rootClasses += _likelyTouchDevice ? 'pswp--touch' : 'pswp--notouch';
16777		rootClasses += _features.animationName ? ' pswp--css_animation' : '';
16778		rootClasses += _features.svg ? ' pswp--svg' : '';
16779		framework.addClass(template, rootClasses);
16780
16781		self.updateSize();
16782
16783		// initial update
16784		_containerShiftIndex = -1;
16785		_indexDiff = null;
16786		for(i = 0; i < NUM_HOLDERS; i++) {
16787			_setTranslateX( (i+_containerShiftIndex) * _slideSize.x, _itemHolders[i].el.style);
16788		}
16789
16790		if(!_oldIE) {
16791			framework.bind(self.scrollWrap, _downEvents, self); // no dragging for old IE
16792		}	
16793
16794		_listen('initialZoomInEnd', function() {
16795			self.setContent(_itemHolders[0], _currentItemIndex-1);
16796			self.setContent(_itemHolders[2], _currentItemIndex+1);
16797
16798			_itemHolders[0].el.style.display = _itemHolders[2].el.style.display = 'block';
16799
16800			if(_options.focus) {
16801				// focus causes layout, 
16802				// which causes lag during the animation, 
16803				// that's why we delay it untill the initial zoom transition ends
16804				template.focus();
16805			}
16806			 
16807
16808			_bindEvents();
16809		});
16810
16811		// set content for center slide (first time)
16812		self.setContent(_itemHolders[1], _currentItemIndex);
16813		
16814		self.updateCurrItem();
16815
16816		_shout('afterInit');
16817
16818		if(!_isFixedPosition) {
16819
16820			// On all versions of iOS lower than 8.0, we check size of viewport every second.
16821			// 
16822			// This is done to detect when Safari top & bottom bars appear, 
16823			// as this action doesn't trigger any events (like resize). 
16824			// 
16825			// On iOS8 they fixed this.
16826			// 
16827			// 10 Nov 2014: iOS 7 usage ~40%. iOS 8 usage 56%.
16828			
16829			_updateSizeInterval = setInterval(function() {
16830				if(!_numAnimations && !_isDragging && !_isZooming && (_currZoomLevel === self.currItem.initialZoomLevel)  ) {
16831					self.updateSize();
16832				}
16833			}, 1000);
16834		}
16835
16836		framework.addClass(template, 'pswp--visible');
16837	},
16838
16839	// Close the gallery, then destroy it
16840	close: function() {
16841		if(!_isOpen) {
16842			return;
16843		}
16844
16845		_isOpen = false;
16846		_isDestroying = true;
16847		_shout('close');
16848		_unbindEvents();
16849
16850		_showOrHide(self.currItem, null, true, self.destroy);
16851	},
16852
16853	// destroys the gallery (unbinds events, cleans up intervals and timeouts to avoid memory leaks)
16854	destroy: function() {
16855		_shout('destroy');
16856
16857		if(_showOrHideTimeout) {
16858			clearTimeout(_showOrHideTimeout);
16859		}
16860		
16861		template.setAttribute('aria-hidden', 'true');
16862		template.className = _initalClassName;
16863
16864		if(_updateSizeInterval) {
16865			clearInterval(_updateSizeInterval);
16866		}
16867
16868		framework.unbind(self.scrollWrap, _downEvents, self);
16869
16870		// we unbind scroll event at the end, as closing animation may depend on it
16871		framework.unbind(window, 'scroll', self);
16872
16873		_stopDragUpdateLoop();
16874
16875		_stopAllAnimations();
16876
16877		_listeners = null;
16878	},
16879
16880	/**
16881	 * Pan image to position
16882	 * @param {Number} x     
16883	 * @param {Number} y     
16884	 * @param {Boolean} force Will ignore bounds if set to true.
16885	 */
16886	panTo: function(x,y,force) {
16887		if(!force) {
16888			if(x > _currPanBounds.min.x) {
16889				x = _currPanBounds.min.x;
16890			} else if(x < _currPanBounds.max.x) {
16891				x = _currPanBounds.max.x;
16892			}
16893
16894			if(y > _currPanBounds.min.y) {
16895				y = _currPanBounds.min.y;
16896			} else if(y < _currPanBounds.max.y) {
16897				y = _currPanBounds.max.y;
16898			}
16899		}
16900		
16901		_panOffset.x = x;
16902		_panOffset.y = y;
16903		_applyCurrentZoomPan();
16904	},
16905	
16906	handleEvent: function (e) {
16907		e = e || window.event;
16908		if(_globalEventHandlers[e.type]) {
16909			_globalEventHandlers[e.type](e);
16910		}
16911	},
16912
16913
16914	goTo: function(index) {
16915
16916		index = _getLoopedId(index);
16917
16918		var diff = index - _currentItemIndex;
16919		_indexDiff = diff;
16920
16921		_currentItemIndex = index;
16922		self.currItem = _getItemAt( _currentItemIndex );
16923		_currPositionIndex -= diff;
16924		
16925		_moveMainScroll(_slideSize.x * _currPositionIndex);
16926		
16927
16928		_stopAllAnimations();
16929		_mainScrollAnimating = false;
16930
16931		self.updateCurrItem();
16932	},
16933	next: function() {
16934		self.goTo( _currentItemIndex + 1);
16935	},
16936	prev: function() {
16937		self.goTo( _currentItemIndex - 1);
16938	},
16939
16940	// update current zoom/pan objects
16941	updateCurrZoomItem: function(emulateSetContent) {
16942		if(emulateSetContent) {
16943			_shout('beforeChange', 0);
16944		}
16945
16946		// itemHolder[1] is middle (current) item
16947		if(_itemHolders[1].el.children.length) {
16948			var zoomElement = _itemHolders[1].el.children[0];
16949			if( framework.hasClass(zoomElement, 'pswp__zoom-wrap') ) {
16950				_currZoomElementStyle = zoomElement.style;
16951			} else {
16952				_currZoomElementStyle = null;
16953			}
16954		} else {
16955			_currZoomElementStyle = null;
16956		}
16957		
16958		_currPanBounds = self.currItem.bounds;	
16959		_startZoomLevel = _currZoomLevel = self.currItem.initialZoomLevel;
16960
16961		_panOffset.x = _currPanBounds.center.x;
16962		_panOffset.y = _currPanBounds.center.y;
16963
16964		if(emulateSetContent) {
16965			_shout('afterChange');
16966		}
16967	},
16968
16969
16970	invalidateCurrItems: function() {
16971		_itemsNeedUpdate = true;
16972		for(var i = 0; i < NUM_HOLDERS; i++) {
16973			if( _itemHolders[i].item ) {
16974				_itemHolders[i].item.needsUpdate = true;
16975			}
16976		}
16977	},
16978
16979	updateCurrItem: function(beforeAnimation) {
16980
16981		if(_indexDiff === 0) {
16982			return;
16983		}
16984
16985		var diffAbs = Math.abs(_indexDiff),
16986			tempHolder;
16987
16988		if(beforeAnimation && diffAbs < 2) {
16989			return;
16990		}
16991
16992
16993		self.currItem = _getItemAt( _currentItemIndex );
16994		_renderMaxResolution = false;
16995		
16996		_shout('beforeChange', _indexDiff);
16997
16998		if(diffAbs >= NUM_HOLDERS) {
16999			_containerShiftIndex += _indexDiff + (_indexDiff > 0 ? -NUM_HOLDERS : NUM_HOLDERS);
17000			diffAbs = NUM_HOLDERS;
17001		}
17002		for(var i = 0; i < diffAbs; i++) {
17003			if(_indexDiff > 0) {
17004				tempHolder = _itemHolders.shift();
17005				_itemHolders[NUM_HOLDERS-1] = tempHolder; // move first to last
17006
17007				_containerShiftIndex++;
17008				_setTranslateX( (_containerShiftIndex+2) * _slideSize.x, tempHolder.el.style);
17009				self.setContent(tempHolder, _currentItemIndex - diffAbs + i + 1 + 1);
17010			} else {
17011				tempHolder = _itemHolders.pop();
17012				_itemHolders.unshift( tempHolder ); // move last to first
17013
17014				_containerShiftIndex--;
17015				_setTranslateX( _containerShiftIndex * _slideSize.x, tempHolder.el.style);
17016				self.setContent(tempHolder, _currentItemIndex + diffAbs - i - 1 - 1);
17017			}
17018			
17019		}
17020
17021		// reset zoom/pan on previous item
17022		if(_currZoomElementStyle && Math.abs(_indexDiff) === 1) {
17023
17024			var prevItem = _getItemAt(_prevItemIndex);
17025			if(prevItem.initialZoomLevel !== _currZoomLevel) {
17026				_calculateItemSize(prevItem , _viewportSize );
17027				_setImageSize(prevItem);
17028				_applyZoomPanToItem( prevItem ); 				
17029			}
17030
17031		}
17032
17033		// reset diff after update
17034		_indexDiff = 0;
17035
17036		self.updateCurrZoomItem();
17037
17038		_prevItemIndex = _currentItemIndex;
17039
17040		_shout('afterChange');
17041		
17042	},
17043
17044
17045
17046	updateSize: function(force) {
17047		
17048		if(!_isFixedPosition && _options.modal) {
17049			var windowScrollY = framework.getScrollY();
17050			if(_currentWindowScrollY !== windowScrollY) {
17051				template.style.top = windowScrollY + 'px';
17052				_currentWindowScrollY = windowScrollY;
17053			}
17054			if(!force && _windowVisibleSize.x === window.innerWidth && _windowVisibleSize.y === window.innerHeight) {
17055				return;
17056			}
17057			_windowVisibleSize.x = window.innerWidth;
17058			_windowVisibleSize.y = window.innerHeight;
17059
17060			//template.style.width = _windowVisibleSize.x + 'px';
17061			template.style.height = _windowVisibleSize.y + 'px';
17062		}
17063
17064
17065
17066		_viewportSize.x = self.scrollWrap.clientWidth;
17067		_viewportSize.y = self.scrollWrap.clientHeight;
17068
17069		_updatePageScrollOffset();
17070
17071		_slideSize.x = _viewportSize.x + Math.round(_viewportSize.x * _options.spacing);
17072		_slideSize.y = _viewportSize.y;
17073
17074		_moveMainScroll(_slideSize.x * _currPositionIndex);
17075
17076		_shout('beforeResize'); // even may be used for example to switch image sources
17077
17078
17079		// don't re-calculate size on inital size update
17080		if(_containerShiftIndex !== undefined) {
17081
17082			var holder,
17083				item,
17084				hIndex;
17085
17086			for(var i = 0; i < NUM_HOLDERS; i++) {
17087				holder = _itemHolders[i];
17088				_setTranslateX( (i+_containerShiftIndex) * _slideSize.x, holder.el.style);
17089
17090				hIndex = _currentItemIndex+i-1;
17091
17092				if(_options.loop && _getNumItems() > 2) {
17093					hIndex = _getLoopedId(hIndex);
17094				}
17095
17096				// update zoom level on items and refresh source (if needsUpdate)
17097				item = _getItemAt( hIndex );
17098
17099				// re-render gallery item if `needsUpdate`,
17100				// or doesn't have `bounds` (entirely new slide object)
17101				if( item && (_itemsNeedUpdate || item.needsUpdate || !item.bounds) ) {
17102
17103					self.cleanSlide( item );
17104					
17105					self.setContent( holder, hIndex );
17106
17107					// if "center" slide
17108					if(i === 1) {
17109						self.currItem = item;
17110						self.updateCurrZoomItem(true);
17111					}
17112
17113					item.needsUpdate = false;
17114
17115				} else if(holder.index === -1 && hIndex >= 0) {
17116					// add content first time
17117					self.setContent( holder, hIndex );
17118				}
17119				if(item && item.container) {
17120					_calculateItemSize(item, _viewportSize);
17121					_setImageSize(item);
17122					_applyZoomPanToItem( item );
17123				}
17124				
17125			}
17126			_itemsNeedUpdate = false;
17127		}	
17128
17129		_startZoomLevel = _currZoomLevel = self.currItem.initialZoomLevel;
17130		_currPanBounds = self.currItem.bounds;
17131
17132		if(_currPanBounds) {
17133			_panOffset.x = _currPanBounds.center.x;
17134			_panOffset.y = _currPanBounds.center.y;
17135			_applyCurrentZoomPan( true );
17136		}
17137		
17138		_shout('resize');
17139	},
17140	
17141	// Zoom current item to
17142	zoomTo: function(destZoomLevel, centerPoint, speed, easingFn, updateFn) {
17143		/*
17144			if(destZoomLevel === 'fit') {
17145				destZoomLevel = self.currItem.fitRatio;
17146			} else if(destZoomLevel === 'fill') {
17147				destZoomLevel = self.currItem.fillRatio;
17148			}
17149		*/
17150
17151		if(centerPoint) {
17152			_startZoomLevel = _currZoomLevel;
17153			_midZoomPoint.x = Math.abs(centerPoint.x) - _panOffset.x ;
17154			_midZoomPoint.y = Math.abs(centerPoint.y) - _panOffset.y ;
17155			_equalizePoints(_startPanOffset, _panOffset);
17156		}
17157
17158		var destPanBounds = _calculatePanBounds(destZoomLevel, false),
17159			destPanOffset = {};
17160
17161		_modifyDestPanOffset('x', destPanBounds, destPanOffset, destZoomLevel);
17162		_modifyDestPanOffset('y', destPanBounds, destPanOffset, destZoomLevel);
17163
17164		var initialZoomLevel = _currZoomLevel;
17165		var initialPanOffset = {
17166			x: _panOffset.x,
17167			y: _panOffset.y
17168		};
17169
17170		_roundPoint(destPanOffset);
17171
17172		var onUpdate = function(now) {
17173			if(now === 1) {
17174				_currZoomLevel = destZoomLevel;
17175				_panOffset.x = destPanOffset.x;
17176				_panOffset.y = destPanOffset.y;
17177			} else {
17178				_currZoomLevel = (destZoomLevel - initialZoomLevel) * now + initialZoomLevel;
17179				_panOffset.x = (destPanOffset.x - initialPanOffset.x) * now + initialPanOffset.x;
17180				_panOffset.y = (destPanOffset.y - initialPanOffset.y) * now + initialPanOffset.y;
17181			}
17182
17183			if(updateFn) {
17184				updateFn(now);
17185			}
17186
17187			_applyCurrentZoomPan( now === 1 );
17188		};
17189
17190		if(speed) {
17191			_animateProp('customZoomTo', 0, 1, speed, easingFn || framework.easing.sine.inOut, onUpdate);
17192		} else {
17193			onUpdate(1);
17194		}
17195	}
17196
17197
17198};
17199
17200
17201/*>>core*/
17202
17203/*>>gestures*/
17204/**
17205 * Mouse/touch/pointer event handlers.
17206 * 
17207 * separated from @core.js for readability
17208 */
17209
17210var MIN_SWIPE_DISTANCE = 30,
17211	DIRECTION_CHECK_OFFSET = 10; // amount of pixels to drag to determine direction of swipe
17212
17213var _gestureStartTime,
17214	_gestureCheckSpeedTime,
17215
17216	// pool of objects that are used during dragging of zooming
17217	p = {}, // first point
17218	p2 = {}, // second point (for zoom gesture)
17219	delta = {},
17220	_currPoint = {},
17221	_startPoint = {},
17222	_currPointers = [],
17223	_startMainScrollPos = {},
17224	_releaseAnimData,
17225	_posPoints = [], // array of points during dragging, used to determine type of gesture
17226	_tempPoint = {},
17227
17228	_isZoomingIn,
17229	_verticalDragInitiated,
17230	_oldAndroidTouchEndTimeout,
17231	_currZoomedItemIndex = 0,
17232	_centerPoint = _getEmptyPoint(),
17233	_lastReleaseTime = 0,
17234	_isDragging, // at least one pointer is down
17235	_isMultitouch, // at least two _pointers are down
17236	_zoomStarted, // zoom level changed during zoom gesture
17237	_moved,
17238	_dragAnimFrame,
17239	_mainScrollShifted,
17240	_currentPoints, // array of current touch points
17241	_isZooming,
17242	_currPointsDistance,
17243	_startPointsDistance,
17244	_currPanBounds,
17245	_mainScrollPos = _getEmptyPoint(),
17246	_currZoomElementStyle,
17247	_mainScrollAnimating, // true, if animation after swipe gesture is running
17248	_midZoomPoint = _getEmptyPoint(),
17249	_currCenterPoint = _getEmptyPoint(),
17250	_direction,
17251	_isFirstMove,
17252	_opacityChanged,
17253	_bgOpacity,
17254	_wasOverInitialZoom,
17255
17256	_isEqualPoints = function(p1, p2) {
17257		return p1.x === p2.x && p1.y === p2.y;
17258	},
17259	_isNearbyPoints = function(touch0, touch1) {
17260		return Math.abs(touch0.x - touch1.x) < DOUBLE_TAP_RADIUS && Math.abs(touch0.y - touch1.y) < DOUBLE_TAP_RADIUS;
17261	},
17262	_calculatePointsDistance = function(p1, p2) {
17263		_tempPoint.x = Math.abs( p1.x - p2.x );
17264		_tempPoint.y = Math.abs( p1.y - p2.y );
17265		return Math.sqrt(_tempPoint.x * _tempPoint.x + _tempPoint.y * _tempPoint.y);
17266	},
17267	_stopDragUpdateLoop = function() {
17268		if(_dragAnimFrame) {
17269			_cancelAF(_dragAnimFrame);
17270			_dragAnimFrame = null;
17271		}
17272	},
17273	_dragUpdateLoop = function() {
17274		if(_isDragging) {
17275			_dragAnimFrame = _requestAF(_dragUpdateLoop);
17276			_renderMovement();
17277		}
17278	},
17279	_canPan = function() {
17280		return !(_options.scaleMode === 'fit' && _currZoomLevel ===  self.currItem.initialZoomLevel);
17281	},
17282	
17283	// find the closest parent DOM element
17284	_closestElement = function(el, fn) {
17285	  	if(!el || el === document) {
17286	  		return false;
17287	  	}
17288
17289	  	// don't search elements above pswp__scroll-wrap
17290	  	if(el.getAttribute('class') && el.getAttribute('class').indexOf('pswp__scroll-wrap') > -1 ) {
17291	  		return false;
17292	  	}
17293
17294	  	if( fn(el) ) {
17295	  		return el;
17296	  	}
17297
17298	  	return _closestElement(el.parentNode, fn);
17299	},
17300
17301	_preventObj = {},
17302	_preventDefaultEventBehaviour = function(e, isDown) {
17303	    _preventObj.prevent = !_closestElement(e.target, _options.isClickableElement);
17304
17305		_shout('preventDragEvent', e, isDown, _preventObj);
17306		return _preventObj.prevent;
17307
17308	},
17309	_convertTouchToPoint = function(touch, p) {
17310		p.x = touch.pageX;
17311		p.y = touch.pageY;
17312		p.id = touch.identifier;
17313		return p;
17314	},
17315	_findCenterOfPoints = function(p1, p2, pCenter) {
17316		pCenter.x = (p1.x + p2.x) * 0.5;
17317		pCenter.y = (p1.y + p2.y) * 0.5;
17318	},
17319	_pushPosPoint = function(time, x, y) {
17320		if(time - _gestureCheckSpeedTime > 50) {
17321			var o = _posPoints.length > 2 ? _posPoints.shift() : {};
17322			o.x = x;
17323			o.y = y; 
17324			_posPoints.push(o);
17325			_gestureCheckSpeedTime = time;
17326		}
17327	},
17328
17329	_calculateVerticalDragOpacityRatio = function() {
17330		var yOffset = _panOffset.y - self.currItem.initialPosition.y; // difference between initial and current position
17331		return 1 -  Math.abs( yOffset / (_viewportSize.y / 2)  );
17332	},
17333
17334	
17335	// points pool, reused during touch events
17336	_ePoint1 = {},
17337	_ePoint2 = {},
17338	_tempPointsArr = [],
17339	_tempCounter,
17340	_getTouchPoints = function(e) {
17341		// clean up previous points, without recreating array
17342		while(_tempPointsArr.length > 0) {
17343			_tempPointsArr.pop();
17344		}
17345
17346		if(!_pointerEventEnabled) {
17347			if(e.type.indexOf('touch') > -1) {
17348
17349				if(e.touches && e.touches.length > 0) {
17350					_tempPointsArr[0] = _convertTouchToPoint(e.touches[0], _ePoint1);
17351					if(e.touches.length > 1) {
17352						_tempPointsArr[1] = _convertTouchToPoint(e.touches[1], _ePoint2);
17353					}
17354				}
17355				
17356			} else {
17357				_ePoint1.x = e.pageX;
17358				_ePoint1.y = e.pageY;
17359				_ePoint1.id = '';
17360				_tempPointsArr[0] = _ePoint1;//_ePoint1;
17361			}
17362		} else {
17363			_tempCounter = 0;
17364			// we can use forEach, as pointer events are supported only in modern browsers
17365			_currPointers.forEach(function(p) {
17366				if(_tempCounter === 0) {
17367					_tempPointsArr[0] = p;
17368				} else if(_tempCounter === 1) {
17369					_tempPointsArr[1] = p;
17370				}
17371				_tempCounter++;
17372
17373			});
17374		}
17375		return _tempPointsArr;
17376	},
17377
17378	_panOrMoveMainScroll = function(axis, delta) {
17379
17380		var panFriction,
17381			overDiff = 0,
17382			newOffset = _panOffset[axis] + delta[axis],
17383			startOverDiff,
17384			dir = delta[axis] > 0,
17385			newMainScrollPosition = _mainScrollPos.x + delta.x,
17386			mainScrollDiff = _mainScrollPos.x - _startMainScrollPos.x,
17387			newPanPos,
17388			newMainScrollPos;
17389
17390		// calculate fdistance over the bounds and friction
17391		if(newOffset > _currPanBounds.min[axis] || newOffset < _currPanBounds.max[axis]) {
17392			panFriction = _options.panEndFriction;
17393			// Linear increasing of friction, so at 1/4 of viewport it's at max value. 
17394			// Looks not as nice as was expected. Left for history.
17395			// panFriction = (1 - (_panOffset[axis] + delta[axis] + panBounds.min[axis]) / (_viewportSize[axis] / 4) );
17396		} else {
17397			panFriction = 1;
17398		}
17399		
17400		newOffset = _panOffset[axis] + delta[axis] * panFriction;
17401
17402		// move main scroll or start panning
17403		if(_options.allowPanToNext || _currZoomLevel === self.currItem.initialZoomLevel) {
17404
17405
17406			if(!_currZoomElementStyle) {
17407				
17408				newMainScrollPos = newMainScrollPosition;
17409
17410			} else if(_direction === 'h' && axis === 'x' && !_zoomStarted ) {
17411				
17412				if(dir) {
17413					if(newOffset > _currPanBounds.min[axis]) {
17414						panFriction = _options.panEndFriction;
17415						overDiff = _currPanBounds.min[axis] - newOffset;
17416						startOverDiff = _currPanBounds.min[axis] - _startPanOffset[axis];
17417					}
17418					
17419					// drag right
17420					if( (startOverDiff <= 0 || mainScrollDiff < 0) && _getNumItems() > 1 ) {
17421						newMainScrollPos = newMainScrollPosition;
17422						if(mainScrollDiff < 0 && newMainScrollPosition > _startMainScrollPos.x) {
17423							newMainScrollPos = _startMainScrollPos.x;
17424						}
17425					} else {
17426						if(_currPanBounds.min.x !== _currPanBounds.max.x) {
17427							newPanPos = newOffset;
17428						}
17429						
17430					}
17431
17432				} else {
17433
17434					if(newOffset < _currPanBounds.max[axis] ) {
17435						panFriction =_options.panEndFriction;
17436						overDiff = newOffset - _currPanBounds.max[axis];
17437						startOverDiff = _startPanOffset[axis] - _currPanBounds.max[axis];
17438					}
17439
17440					if( (startOverDiff <= 0 || mainScrollDiff > 0) && _getNumItems() > 1 ) {
17441						newMainScrollPos = newMainScrollPosition;
17442
17443						if(mainScrollDiff > 0 && newMainScrollPosition < _startMainScrollPos.x) {
17444							newMainScrollPos = _startMainScrollPos.x;
17445						}
17446
17447					} else {
17448						if(_currPanBounds.min.x !== _currPanBounds.max.x) {
17449							newPanPos = newOffset;
17450						}
17451					}
17452
17453				}
17454
17455
17456				//
17457			}
17458
17459			if(axis === 'x') {
17460
17461				if(newMainScrollPos !== undefined) {
17462					_moveMainScroll(newMainScrollPos, true);
17463					if(newMainScrollPos === _startMainScrollPos.x) {
17464						_mainScrollShifted = false;
17465					} else {
17466						_mainScrollShifted = true;
17467					}
17468				}
17469
17470				if(_currPanBounds.min.x !== _currPanBounds.max.x) {
17471					if(newPanPos !== undefined) {
17472						_panOffset.x = newPanPos;
17473					} else if(!_mainScrollShifted) {
17474						_panOffset.x += delta.x * panFriction;
17475					}
17476				}
17477
17478				return newMainScrollPos !== undefined;
17479			}
17480
17481		}
17482
17483		if(!_mainScrollAnimating) {
17484			
17485			if(!_mainScrollShifted) {
17486				if(_currZoomLevel > self.currItem.fitRatio) {
17487					_panOffset[axis] += delta[axis] * panFriction;
17488				
17489				}
17490			}
17491
17492			
17493		}
17494		
17495	},
17496
17497	// Pointerdown/touchstart/mousedown handler
17498	_onDragStart = function(e) {
17499
17500		// Allow dragging only via left mouse button.
17501		// As this handler is not added in IE8 - we ignore e.which
17502		// 
17503		// http://www.quirksmode.org/js/events_properties.html
17504		// https://developer.mozilla.org/en-US/docs/Web/API/event.button
17505		if(e.type === 'mousedown' && e.button > 0  ) {
17506			return;
17507		}
17508
17509		if(_initialZoomRunning) {
17510			e.preventDefault();
17511			return;
17512		}
17513
17514		if(_oldAndroidTouchEndTimeout && e.type === 'mousedown') {
17515			return;
17516		}
17517
17518		if(_preventDefaultEventBehaviour(e, true)) {
17519			e.preventDefault();
17520		}
17521
17522
17523
17524		_shout('pointerDown');
17525
17526		if(_pointerEventEnabled) {
17527			var pointerIndex = framework.arraySearch(_currPointers, e.pointerId, 'id');
17528			if(pointerIndex < 0) {
17529				pointerIndex = _currPointers.length;
17530			}
17531			_currPointers[pointerIndex] = {x:e.pageX, y:e.pageY, id: e.pointerId};
17532		}
17533		
17534
17535
17536		var startPointsList = _getTouchPoints(e),
17537			numPoints = startPointsList.length;
17538
17539		_currentPoints = null;
17540
17541		_stopAllAnimations();
17542
17543		// init drag
17544		if(!_isDragging || numPoints === 1) {
17545
17546			
17547
17548			_isDragging = _isFirstMove = true;
17549			framework.bind(window, _upMoveEvents, self);
17550
17551			_isZoomingIn = 
17552				_wasOverInitialZoom = 
17553				_opacityChanged = 
17554				_verticalDragInitiated = 
17555				_mainScrollShifted = 
17556				_moved = 
17557				_isMultitouch = 
17558				_zoomStarted = false;
17559
17560			_direction = null;
17561
17562			_shout('firstTouchStart', startPointsList);
17563
17564			_equalizePoints(_startPanOffset, _panOffset);
17565
17566			_currPanDist.x = _currPanDist.y = 0;
17567			_equalizePoints(_currPoint, startPointsList[0]);
17568			_equalizePoints(_startPoint, _currPoint);
17569
17570			//_equalizePoints(_startMainScrollPos, _mainScrollPos);
17571			_startMainScrollPos.x = _slideSize.x * _currPositionIndex;
17572
17573			_posPoints = [{
17574				x: _currPoint.x,
17575				y: _currPoint.y
17576			}];
17577
17578			_gestureCheckSpeedTime = _gestureStartTime = _getCurrentTime();
17579
17580			//_mainScrollAnimationEnd(true);
17581			_calculatePanBounds( _currZoomLevel, true );
17582			
17583			// Start rendering
17584			_stopDragUpdateLoop();
17585			_dragUpdateLoop();
17586			
17587		}
17588
17589		// init zoom
17590		if(!_isZooming && numPoints > 1 && !_mainScrollAnimating && !_mainScrollShifted) {
17591			_startZoomLevel = _currZoomLevel;
17592			_zoomStarted = false; // true if zoom changed at least once
17593
17594			_isZooming = _isMultitouch = true;
17595			_currPanDist.y = _currPanDist.x = 0;
17596
17597			_equalizePoints(_startPanOffset, _panOffset);
17598
17599			_equalizePoints(p, startPointsList[0]);
17600			_equalizePoints(p2, startPointsList[1]);
17601
17602			_findCenterOfPoints(p, p2, _currCenterPoint);
17603
17604			_midZoomPoint.x = Math.abs(_currCenterPoint.x) - _panOffset.x;
17605			_midZoomPoint.y = Math.abs(_currCenterPoint.y) - _panOffset.y;
17606			_currPointsDistance = _startPointsDistance = _calculatePointsDistance(p, p2);
17607		}
17608
17609
17610	},
17611
17612	// Pointermove/touchmove/mousemove handler
17613	_onDragMove = function(e) {
17614
17615		e.preventDefault();
17616
17617		if(_pointerEventEnabled) {
17618			var pointerIndex = framework.arraySearch(_currPointers, e.pointerId, 'id');
17619			if(pointerIndex > -1) {
17620				var p = _currPointers[pointerIndex];
17621				p.x = e.pageX;
17622				p.y = e.pageY; 
17623			}
17624		}
17625
17626		if(_isDragging) {
17627			var touchesList = _getTouchPoints(e);
17628			if(!_direction && !_moved && !_isZooming) {
17629
17630				if(_mainScrollPos.x !== _slideSize.x * _currPositionIndex) {
17631					// if main scroll position is shifted – direction is always horizontal
17632					_direction = 'h';
17633				} else {
17634					var diff = Math.abs(touchesList[0].x - _currPoint.x) - Math.abs(touchesList[0].y - _currPoint.y);
17635					// check the direction of movement
17636					if(Math.abs(diff) >= DIRECTION_CHECK_OFFSET) {
17637						_direction = diff > 0 ? 'h' : 'v';
17638						_currentPoints = touchesList;
17639					}
17640				}
17641				
17642			} else {
17643				_currentPoints = touchesList;
17644			}
17645		}	
17646	},
17647	// 
17648	_renderMovement =  function() {
17649
17650		if(!_currentPoints) {
17651			return;
17652		}
17653
17654		var numPoints = _currentPoints.length;
17655
17656		if(numPoints === 0) {
17657			return;
17658		}
17659
17660		_equalizePoints(p, _currentPoints[0]);
17661
17662		delta.x = p.x - _currPoint.x;
17663		delta.y = p.y - _currPoint.y;
17664
17665		if(_isZooming && numPoints > 1) {
17666			// Handle behaviour for more than 1 point
17667
17668			_currPoint.x = p.x;
17669			_currPoint.y = p.y;
17670		
17671			// check if one of two points changed
17672			if( !delta.x && !delta.y && _isEqualPoints(_currentPoints[1], p2) ) {
17673				return;
17674			}
17675
17676			_equalizePoints(p2, _currentPoints[1]);
17677
17678
17679			if(!_zoomStarted) {
17680				_zoomStarted = true;
17681				_shout('zoomGestureStarted');
17682			}
17683			
17684			// Distance between two points
17685			var pointsDistance = _calculatePointsDistance(p,p2);
17686
17687			var zoomLevel = _calculateZoomLevel(pointsDistance);
17688
17689			// slightly over the of initial zoom level
17690			if(zoomLevel > self.currItem.initialZoomLevel + self.currItem.initialZoomLevel / 15) {
17691				_wasOverInitialZoom = true;
17692			}
17693
17694			// Apply the friction if zoom level is out of the bounds
17695			var zoomFriction = 1,
17696				minZoomLevel = _getMinZoomLevel(),
17697				maxZoomLevel = _getMaxZoomLevel();
17698
17699			if ( zoomLevel < minZoomLevel ) {
17700				
17701				if(_options.pinchToClose && !_wasOverInitialZoom && _startZoomLevel <= self.currItem.initialZoomLevel) {
17702					// fade out background if zooming out
17703					var minusDiff = minZoomLevel - zoomLevel;
17704					var percent = 1 - minusDiff / (minZoomLevel / 1.2);
17705
17706					_applyBgOpacity(percent);
17707					_shout('onPinchClose', percent);
17708					_opacityChanged = true;
17709				} else {
17710					zoomFriction = (minZoomLevel - zoomLevel) / minZoomLevel;
17711					if(zoomFriction > 1) {
17712						zoomFriction = 1;
17713					}
17714					zoomLevel = minZoomLevel - zoomFriction * (minZoomLevel / 3);
17715				}
17716				
17717			} else if ( zoomLevel > maxZoomLevel ) {
17718				// 1.5 - extra zoom level above the max. E.g. if max is x6, real max 6 + 1.5 = 7.5
17719				zoomFriction = (zoomLevel - maxZoomLevel) / ( minZoomLevel * 6 );
17720				if(zoomFriction > 1) {
17721					zoomFriction = 1;
17722				}
17723				zoomLevel = maxZoomLevel + zoomFriction * minZoomLevel;
17724			}
17725
17726			if(zoomFriction < 0) {
17727				zoomFriction = 0;
17728			}
17729
17730			// distance between touch points after friction is applied
17731			_currPointsDistance = pointsDistance;
17732
17733			// _centerPoint - The point in the middle of two pointers
17734			_findCenterOfPoints(p, p2, _centerPoint);
17735		
17736			// paning with two pointers pressed
17737			_currPanDist.x += _centerPoint.x - _currCenterPoint.x;
17738			_currPanDist.y += _centerPoint.y - _currCenterPoint.y;
17739			_equalizePoints(_currCenterPoint, _centerPoint);
17740
17741			_panOffset.x = _calculatePanOffset('x', zoomLevel);
17742			_panOffset.y = _calculatePanOffset('y', zoomLevel);
17743
17744			_isZoomingIn = zoomLevel > _currZoomLevel;
17745			_currZoomLevel = zoomLevel;
17746			_applyCurrentZoomPan();
17747
17748		} else {
17749
17750			// handle behaviour for one point (dragging or panning)
17751
17752			if(!_direction) {
17753				return;
17754			}
17755
17756			if(_isFirstMove) {
17757				_isFirstMove = false;
17758
17759				// subtract drag distance that was used during the detection direction  
17760
17761				if( Math.abs(delta.x) >= DIRECTION_CHECK_OFFSET) {
17762					delta.x -= _currentPoints[0].x - _startPoint.x;
17763				}
17764				
17765				if( Math.abs(delta.y) >= DIRECTION_CHECK_OFFSET) {
17766					delta.y -= _currentPoints[0].y - _startPoint.y;
17767				}
17768			}
17769
17770			_currPoint.x = p.x;
17771			_currPoint.y = p.y;
17772
17773			// do nothing if pointers position hasn't changed
17774			if(delta.x === 0 && delta.y === 0) {
17775				return;
17776			}
17777
17778			if(_direction === 'v' && _options.closeOnVerticalDrag) {
17779				if(!_canPan()) {
17780					_currPanDist.y += delta.y;
17781					_panOffset.y += delta.y;
17782
17783					var opacityRatio = _calculateVerticalDragOpacityRatio();
17784
17785					_verticalDragInitiated = true;
17786					_shout('onVerticalDrag', opacityRatio);
17787
17788					_applyBgOpacity(opacityRatio);
17789					_applyCurrentZoomPan();
17790					return ;
17791				}
17792			}
17793
17794			_pushPosPoint(_getCurrentTime(), p.x, p.y);
17795
17796			_moved = true;
17797			_currPanBounds = self.currItem.bounds;
17798			
17799			var mainScrollChanged = _panOrMoveMainScroll('x', delta);
17800			if(!mainScrollChanged) {
17801				_panOrMoveMainScroll('y', delta);
17802
17803				_roundPoint(_panOffset);
17804				_applyCurrentZoomPan();
17805			}
17806
17807		}
17808
17809	},
17810	
17811	// Pointerup/pointercancel/touchend/touchcancel/mouseup event handler
17812	_onDragRelease = function(e) {
17813
17814		if(_features.isOldAndroid ) {
17815
17816			if(_oldAndroidTouchEndTimeout && e.type === 'mouseup') {
17817				return;
17818			}
17819
17820			// on Android (v4.1, 4.2, 4.3 & possibly older) 
17821			// ghost mousedown/up event isn't preventable via e.preventDefault,
17822			// which causes fake mousedown event
17823			// so we block mousedown/up for 600ms
17824			if( e.type.indexOf('touch') > -1 ) {
17825				clearTimeout(_oldAndroidTouchEndTimeout);
17826				_oldAndroidTouchEndTimeout = setTimeout(function() {
17827					_oldAndroidTouchEndTimeout = 0;
17828				}, 600);
17829			}
17830			
17831		}
17832
17833		_shout('pointerUp');
17834
17835		if(_preventDefaultEventBehaviour(e, false)) {
17836			e.preventDefault();
17837		}
17838
17839		var releasePoint;
17840
17841		if(_pointerEventEnabled) {
17842			var pointerIndex = framework.arraySearch(_currPointers, e.pointerId, 'id');
17843			
17844			if(pointerIndex > -1) {
17845				releasePoint = _currPointers.splice(pointerIndex, 1)[0];
17846
17847				if(navigator.msPointerEnabled) {
17848					var MSPOINTER_TYPES = {
17849						4: 'mouse', // event.MSPOINTER_TYPE_MOUSE
17850						2: 'touch', // event.MSPOINTER_TYPE_TOUCH 
17851						3: 'pen' // event.MSPOINTER_TYPE_PEN
17852					};
17853					releasePoint.type = MSPOINTER_TYPES[e.pointerType];
17854
17855					if(!releasePoint.type) {
17856						releasePoint.type = e.pointerType || 'mouse';
17857					}
17858				} else {
17859					releasePoint.type = e.pointerType || 'mouse';
17860				}
17861
17862			}
17863		}
17864
17865		var touchList = _getTouchPoints(e),
17866			gestureType,
17867			numPoints = touchList.length;
17868
17869		if(e.type === 'mouseup') {
17870			numPoints = 0;
17871		}
17872
17873		// Do nothing if there were 3 touch points or more
17874		if(numPoints === 2) {
17875			_currentPoints = null;
17876			return true;
17877		}
17878
17879		// if second pointer released
17880		if(numPoints === 1) {
17881			_equalizePoints(_startPoint, touchList[0]);
17882		}				
17883
17884
17885		// pointer hasn't moved, send "tap release" point
17886		if(numPoints === 0 && !_direction && !_mainScrollAnimating) {
17887			if(!releasePoint) {
17888				if(e.type === 'mouseup') {
17889					releasePoint = {x: e.pageX, y: e.pageY, type:'mouse'};
17890				} else if(e.changedTouches && e.changedTouches[0]) {
17891					releasePoint = {x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY, type:'touch'};
17892				}		
17893			}
17894
17895			_shout('touchRelease', e, releasePoint);
17896		}
17897
17898		// Difference in time between releasing of two last touch points (zoom gesture)
17899		var releaseTimeDiff = -1;
17900
17901		// Gesture completed, no pointers left
17902		if(numPoints === 0) {
17903			_isDragging = false;
17904			framework.unbind(window, _upMoveEvents, self);
17905
17906			_stopDragUpdateLoop();
17907
17908			if(_isZooming) {
17909				// Two points released at the same time
17910				releaseTimeDiff = 0;
17911			} else if(_lastReleaseTime !== -1) {
17912				releaseTimeDiff = _getCurrentTime() - _lastReleaseTime;
17913			}
17914		}
17915		_lastReleaseTime = numPoints === 1 ? _getCurrentTime() : -1;
17916		
17917		if(releaseTimeDiff !== -1 && releaseTimeDiff < 150) {
17918			gestureType = 'zoom';
17919		} else {
17920			gestureType = 'swipe';
17921		}
17922
17923		if(_isZooming && numPoints < 2) {
17924			_isZooming = false;
17925
17926			// Only second point released
17927			if(numPoints === 1) {
17928				gestureType = 'zoomPointerUp';
17929			}
17930			_shout('zoomGestureEnded');
17931		}
17932
17933		_currentPoints = null;
17934		if(!_moved && !_zoomStarted && !_mainScrollAnimating && !_verticalDragInitiated) {
17935			// nothing to animate
17936			return;
17937		}
17938	
17939		_stopAllAnimations();
17940
17941		
17942		if(!_releaseAnimData) {
17943			_releaseAnimData = _initDragReleaseAnimationData();
17944		}
17945		
17946		_releaseAnimData.calculateSwipeSpeed('x');
17947
17948
17949		if(_verticalDragInitiated) {
17950
17951			var opacityRatio = _calculateVerticalDragOpacityRatio();
17952
17953			if(opacityRatio < _options.verticalDragRange) {
17954				self.close();
17955			} else {
17956				var initalPanY = _panOffset.y,
17957					initialBgOpacity = _bgOpacity;
17958
17959				_animateProp('verticalDrag', 0, 1, 300, framework.easing.cubic.out, function(now) {
17960					
17961					_panOffset.y = (self.currItem.initialPosition.y - initalPanY) * now + initalPanY;
17962
17963					_applyBgOpacity(  (1 - initialBgOpacity) * now + initialBgOpacity );
17964					_applyCurrentZoomPan();
17965				});
17966
17967				_shout('onVerticalDrag', 1);
17968			}
17969
17970			return;
17971		}
17972
17973
17974		// main scroll 
17975		if(  (_mainScrollShifted || _mainScrollAnimating) && numPoints === 0) {
17976			var itemChanged = _finishSwipeMainScrollGesture(gestureType, _releaseAnimData);
17977			if(itemChanged) {
17978				return;
17979			}
17980			gestureType = 'zoomPointerUp';
17981		}
17982
17983		// prevent zoom/pan animation when main scroll animation runs
17984		if(_mainScrollAnimating) {
17985			return;
17986		}
17987		
17988		// Complete simple zoom gesture (reset zoom level if it's out of the bounds)  
17989		if(gestureType !== 'swipe') {
17990			_completeZoomGesture();
17991			return;
17992		}
17993	
17994		// Complete pan gesture if main scroll is not shifted, and it's possible to pan current image
17995		if(!_mainScrollShifted && _currZoomLevel > self.currItem.fitRatio) {
17996			_completePanGesture(_releaseAnimData);
17997		}
17998	},
17999
18000
18001	// Returns object with data about gesture
18002	// It's created only once and then reused
18003	_initDragReleaseAnimationData  = function() {
18004		// temp local vars
18005		var lastFlickDuration,
18006			tempReleasePos;
18007
18008		// s = this
18009		var s = {
18010			lastFlickOffset: {},
18011			lastFlickDist: {},
18012			lastFlickSpeed: {},
18013			slowDownRatio:  {},
18014			slowDownRatioReverse:  {},
18015			speedDecelerationRatio:  {},
18016			speedDecelerationRatioAbs:  {},
18017			distanceOffset:  {},
18018			backAnimDestination: {},
18019			backAnimStarted: {},
18020			calculateSwipeSpeed: function(axis) {
18021				
18022
18023				if( _posPoints.length > 1) {
18024					lastFlickDuration = _getCurrentTime() - _gestureCheckSpeedTime + 50;
18025					tempReleasePos = _posPoints[_posPoints.length-2][axis];
18026				} else {
18027					lastFlickDuration = _getCurrentTime() - _gestureStartTime; // total gesture duration
18028					tempReleasePos = _startPoint[axis];
18029				}
18030				s.lastFlickOffset[axis] = _currPoint[axis] - tempReleasePos;
18031				s.lastFlickDist[axis] = Math.abs(s.lastFlickOffset[axis]);
18032				if(s.lastFlickDist[axis] > 20) {
18033					s.lastFlickSpeed[axis] = s.lastFlickOffset[axis] / lastFlickDuration;
18034				} else {
18035					s.lastFlickSpeed[axis] = 0;
18036				}
18037				if( Math.abs(s.lastFlickSpeed[axis]) < 0.1 ) {
18038					s.lastFlickSpeed[axis] = 0;
18039				}
18040				
18041				s.slowDownRatio[axis] = 0.95;
18042				s.slowDownRatioReverse[axis] = 1 - s.slowDownRatio[axis];
18043				s.speedDecelerationRatio[axis] = 1;
18044			},
18045
18046			calculateOverBoundsAnimOffset: function(axis, speed) {
18047				if(!s.backAnimStarted[axis]) {
18048
18049					if(_panOffset[axis] > _currPanBounds.min[axis]) {
18050						s.backAnimDestination[axis] = _currPanBounds.min[axis];
18051						
18052					} else if(_panOffset[axis] < _currPanBounds.max[axis]) {
18053						s.backAnimDestination[axis] = _currPanBounds.max[axis];
18054					}
18055
18056					if(s.backAnimDestination[axis] !== undefined) {
18057						s.slowDownRatio[axis] = 0.7;
18058						s.slowDownRatioReverse[axis] = 1 - s.slowDownRatio[axis];
18059						if(s.speedDecelerationRatioAbs[axis] < 0.05) {
18060
18061							s.lastFlickSpeed[axis] = 0;
18062							s.backAnimStarted[axis] = true;
18063
18064							_animateProp('bounceZoomPan'+axis,_panOffset[axis], 
18065								s.backAnimDestination[axis], 
18066								speed || 300, 
18067								framework.easing.sine.out, 
18068								function(pos) {
18069									_panOffset[axis] = pos;
18070									_applyCurrentZoomPan();
18071								}
18072							);
18073
18074						}
18075					}
18076				}
18077			},
18078
18079			// Reduces the speed by slowDownRatio (per 10ms)
18080			calculateAnimOffset: function(axis) {
18081				if(!s.backAnimStarted[axis]) {
18082					s.speedDecelerationRatio[axis] = s.speedDecelerationRatio[axis] * (s.slowDownRatio[axis] + 
18083												s.slowDownRatioReverse[axis] - 
18084												s.slowDownRatioReverse[axis] * s.timeDiff / 10);
18085
18086					s.speedDecelerationRatioAbs[axis] = Math.abs(s.lastFlickSpeed[axis] * s.speedDecelerationRatio[axis]);
18087					s.distanceOffset[axis] = s.lastFlickSpeed[axis] * s.speedDecelerationRatio[axis] * s.timeDiff;
18088					_panOffset[axis] += s.distanceOffset[axis];
18089
18090				}
18091			},
18092
18093			panAnimLoop: function() {
18094				if ( _animations.zoomPan ) {
18095					_animations.zoomPan.raf = _requestAF(s.panAnimLoop);
18096
18097					s.now = _getCurrentTime();
18098					s.timeDiff = s.now - s.lastNow;
18099					s.lastNow = s.now;
18100					
18101					s.calculateAnimOffset('x');
18102					s.calculateAnimOffset('y');
18103
18104					_applyCurrentZoomPan();
18105					
18106					s.calculateOverBoundsAnimOffset('x');
18107					s.calculateOverBoundsAnimOffset('y');
18108
18109
18110					if (s.speedDecelerationRatioAbs.x < 0.05 && s.speedDecelerationRatioAbs.y < 0.05) {
18111
18112						// round pan position
18113						_panOffset.x = Math.round(_panOffset.x);
18114						_panOffset.y = Math.round(_panOffset.y);
18115						_applyCurrentZoomPan();
18116						
18117						_stopAnimation('zoomPan');
18118						return;
18119					}
18120				}
18121
18122			}
18123		};
18124		return s;
18125	},
18126
18127	_completePanGesture = function(animData) {
18128		// calculate swipe speed for Y axis (paanning)
18129		animData.calculateSwipeSpeed('y');
18130
18131		_currPanBounds = self.currItem.bounds;
18132		
18133		animData.backAnimDestination = {};
18134		animData.backAnimStarted = {};
18135
18136		// Avoid acceleration animation if speed is too low
18137		if(Math.abs(animData.lastFlickSpeed.x) <= 0.05 && Math.abs(animData.lastFlickSpeed.y) <= 0.05 ) {
18138			animData.speedDecelerationRatioAbs.x = animData.speedDecelerationRatioAbs.y = 0;
18139
18140			// Run pan drag release animation. E.g. if you drag image and release finger without momentum.
18141			animData.calculateOverBoundsAnimOffset('x');
18142			animData.calculateOverBoundsAnimOffset('y');
18143			return true;
18144		}
18145
18146		// Animation loop that controls the acceleration after pan gesture ends
18147		_registerStartAnimation('zoomPan');
18148		animData.lastNow = _getCurrentTime();
18149		animData.panAnimLoop();
18150	},
18151
18152
18153	_finishSwipeMainScrollGesture = function(gestureType, _releaseAnimData) {
18154		var itemChanged;
18155		if(!_mainScrollAnimating) {
18156			_currZoomedItemIndex = _currentItemIndex;
18157		}
18158
18159
18160		
18161		var itemsDiff;
18162
18163		if(gestureType === 'swipe') {
18164			var totalShiftDist = _currPoint.x - _startPoint.x,
18165				isFastLastFlick = _releaseAnimData.lastFlickDist.x < 10;
18166
18167			// if container is shifted for more than MIN_SWIPE_DISTANCE, 
18168			// and last flick gesture was in right direction
18169			if(totalShiftDist > MIN_SWIPE_DISTANCE && 
18170				(isFastLastFlick || _releaseAnimData.lastFlickOffset.x > 20) ) {
18171				// go to prev item
18172				itemsDiff = -1;
18173			} else if(totalShiftDist < -MIN_SWIPE_DISTANCE && 
18174				(isFastLastFlick || _releaseAnimData.lastFlickOffset.x < -20) ) {
18175				// go to next item
18176				itemsDiff = 1;
18177			}
18178		}
18179
18180		var nextCircle;
18181
18182		if(itemsDiff) {
18183			
18184			_currentItemIndex += itemsDiff;
18185
18186			if(_currentItemIndex < 0) {
18187				_currentItemIndex = _options.loop ? _getNumItems()-1 : 0;
18188				nextCircle = true;
18189			} else if(_currentItemIndex >= _getNumItems()) {
18190				_currentItemIndex = _options.loop ? 0 : _getNumItems()-1;
18191				nextCircle = true;
18192			}
18193
18194			if(!nextCircle || _options.loop) {
18195				_indexDiff += itemsDiff;
18196				_currPositionIndex -= itemsDiff;
18197				itemChanged = true;
18198			}
18199			
18200
18201			
18202		}
18203
18204		var animateToX = _slideSize.x * _currPositionIndex;
18205		var animateToDist = Math.abs( animateToX - _mainScrollPos.x );
18206		var finishAnimDuration;
18207
18208
18209		if(!itemChanged && animateToX > _mainScrollPos.x !== _releaseAnimData.lastFlickSpeed.x > 0) {
18210			// "return to current" duration, e.g. when dragging from slide 0 to -1
18211			finishAnimDuration = 333; 
18212		} else {
18213			finishAnimDuration = Math.abs(_releaseAnimData.lastFlickSpeed.x) > 0 ? 
18214									animateToDist / Math.abs(_releaseAnimData.lastFlickSpeed.x) : 
18215									333;
18216
18217			finishAnimDuration = Math.min(finishAnimDuration, 400);
18218			finishAnimDuration = Math.max(finishAnimDuration, 250);
18219		}
18220
18221		if(_currZoomedItemIndex === _currentItemIndex) {
18222			itemChanged = false;
18223		}
18224		
18225		_mainScrollAnimating = true;
18226		
18227		_shout('mainScrollAnimStart');
18228
18229		_animateProp('mainScroll', _mainScrollPos.x, animateToX, finishAnimDuration, framework.easing.cubic.out, 
18230			_moveMainScroll,
18231			function() {
18232				_stopAllAnimations();
18233				_mainScrollAnimating = false;
18234				_currZoomedItemIndex = -1;
18235				
18236				if(itemChanged || _currZoomedItemIndex !== _currentItemIndex) {
18237					self.updateCurrItem();
18238				}
18239				
18240				_shout('mainScrollAnimComplete');
18241			}
18242		);
18243
18244		if(itemChanged) {
18245			self.updateCurrItem(true);
18246		}
18247
18248		return itemChanged;
18249	},
18250
18251	_calculateZoomLevel = function(touchesDistance) {
18252		return  1 / _startPointsDistance * touchesDistance * _startZoomLevel;
18253	},
18254
18255	// Resets zoom if it's out of bounds
18256	_completeZoomGesture = function() {
18257		var destZoomLevel = _currZoomLevel,
18258			minZoomLevel = _getMinZoomLevel(),
18259			maxZoomLevel = _getMaxZoomLevel();
18260
18261		if ( _currZoomLevel < minZoomLevel ) {
18262			destZoomLevel = minZoomLevel;
18263		} else if ( _currZoomLevel > maxZoomLevel ) {
18264			destZoomLevel = maxZoomLevel;
18265		}
18266
18267		var destOpacity = 1,
18268			onUpdate,
18269			initialOpacity = _bgOpacity;
18270
18271		if(_opacityChanged && !_isZoomingIn && !_wasOverInitialZoom && _currZoomLevel < minZoomLevel) {
18272			//_closedByScroll = true;
18273			self.close();
18274			return true;
18275		}
18276
18277		if(_opacityChanged) {
18278			onUpdate = function(now) {
18279				_applyBgOpacity(  (destOpacity - initialOpacity) * now + initialOpacity );
18280			};
18281		}
18282
18283		self.zoomTo(destZoomLevel, 0, 200,  framework.easing.cubic.out, onUpdate);
18284		return true;
18285	};
18286
18287
18288_registerModule('Gestures', {
18289	publicMethods: {
18290
18291		initGestures: function() {
18292
18293			// helper function that builds touch/pointer/mouse events
18294			var addEventNames = function(pref, down, move, up, cancel) {
18295				_dragStartEvent = pref + down;
18296				_dragMoveEvent = pref + move;
18297				_dragEndEvent = pref + up;
18298				if(cancel) {
18299					_dragCancelEvent = pref + cancel;
18300				} else {
18301					_dragCancelEvent = '';
18302				}
18303			};
18304
18305			_pointerEventEnabled = _features.pointerEvent;
18306			if(_pointerEventEnabled && _features.touch) {
18307				// we don't need touch events, if browser supports pointer events
18308				_features.touch = false;
18309			}
18310
18311			if(_pointerEventEnabled) {
18312				if(navigator.msPointerEnabled) {
18313					// IE10 pointer events are case-sensitive
18314					addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel');
18315				} else {
18316					addEventNames('pointer', 'down', 'move', 'up', 'cancel');
18317				}
18318			} else if(_features.touch) {
18319				addEventNames('touch', 'start', 'move', 'end', 'cancel');
18320				_likelyTouchDevice = true;
18321			} else {
18322				addEventNames('mouse', 'down', 'move', 'up');	
18323			}
18324
18325			_upMoveEvents = _dragMoveEvent + ' ' + _dragEndEvent  + ' ' +  _dragCancelEvent;
18326			_downEvents = _dragStartEvent;
18327
18328			if(_pointerEventEnabled && !_likelyTouchDevice) {
18329				_likelyTouchDevice = (navigator.maxTouchPoints > 1) || (navigator.msMaxTouchPoints > 1);
18330			}
18331			// make variable public
18332			self.likelyTouchDevice = _likelyTouchDevice; 
18333			
18334			_globalEventHandlers[_dragStartEvent] = _onDragStart;
18335			_globalEventHandlers[_dragMoveEvent] = _onDragMove;
18336			_globalEventHandlers[_dragEndEvent] = _onDragRelease; // the Kraken
18337
18338			if(_dragCancelEvent) {
18339				_globalEventHandlers[_dragCancelEvent] = _globalEventHandlers[_dragEndEvent];
18340			}
18341
18342			// Bind mouse events on device with detected hardware touch support, in case it supports multiple types of input.
18343			if(_features.touch) {
18344				_downEvents += ' mousedown';
18345				_upMoveEvents += ' mousemove mouseup';
18346				_globalEventHandlers.mousedown = _globalEventHandlers[_dragStartEvent];
18347				_globalEventHandlers.mousemove = _globalEventHandlers[_dragMoveEvent];
18348				_globalEventHandlers.mouseup = _globalEventHandlers[_dragEndEvent];
18349			}
18350
18351			if(!_likelyTouchDevice) {
18352				// don't allow pan to next slide from zoomed state on Desktop
18353				_options.allowPanToNext = false;
18354			}
18355		}
18356
18357	}
18358});
18359
18360
18361/*>>gestures*/
18362
18363/*>>show-hide-transition*/
18364/**
18365 * show-hide-transition.js:
18366 *
18367 * Manages initial opening or closing transition.
18368 *
18369 * If you're not planning to use transition for gallery at all,
18370 * you may set options hideAnimationDuration and showAnimationDuration to 0,
18371 * and just delete startAnimation function.
18372 * 
18373 */
18374
18375
18376var _showOrHideTimeout,
18377	_showOrHide = function(item, img, out, completeFn) {
18378
18379		if(_showOrHideTimeout) {
18380			clearTimeout(_showOrHideTimeout);
18381		}
18382
18383		_initialZoomRunning = true;
18384		_initialContentSet = true;
18385		
18386		// dimensions of small thumbnail {x:,y:,w:}.
18387		// Height is optional, as calculated based on large image.
18388		var thumbBounds; 
18389		if(item.initialLayout) {
18390			thumbBounds = item.initialLayout;
18391			item.initialLayout = null;
18392		} else {
18393			thumbBounds = _options.getThumbBoundsFn && _options.getThumbBoundsFn(_currentItemIndex);
18394		}
18395
18396		var duration = out ? _options.hideAnimationDuration : _options.showAnimationDuration;
18397
18398		var onComplete = function() {
18399			_stopAnimation('initialZoom');
18400			if(!out) {
18401				_applyBgOpacity(1);
18402				if(img) {
18403					img.style.display = 'block';
18404				}
18405				framework.addClass(template, 'pswp--animated-in');
18406				_shout('initialZoom' + (out ? 'OutEnd' : 'InEnd'));
18407			} else {
18408				self.template.removeAttribute('style');
18409				self.bg.removeAttribute('style');
18410			}
18411
18412			if(completeFn) {
18413				completeFn();
18414			}
18415			_initialZoomRunning = false;
18416		};
18417
18418		// if bounds aren't provided, just open gallery without animation
18419		if(!duration || !thumbBounds || thumbBounds.x === undefined) {
18420
18421			_shout('initialZoom' + (out ? 'Out' : 'In') );
18422
18423			_currZoomLevel = item.initialZoomLevel;
18424			_equalizePoints(_panOffset,  item.initialPosition );
18425			_applyCurrentZoomPan();
18426
18427			template.style.opacity = out ? 0 : 1;
18428			_applyBgOpacity(1);
18429
18430			if(duration) {
18431				setTimeout(function() {
18432					onComplete();
18433				}, duration);
18434			} else {
18435				onComplete();
18436			}
18437
18438			return;
18439		}
18440
18441		var startAnimation = function() {
18442			var closeWithRaf = _closedByScroll,
18443				fadeEverything = !self.currItem.src || self.currItem.loadError || _options.showHideOpacity;
18444			
18445			// apply hw-acceleration to image
18446			if(item.miniImg) {
18447				item.miniImg.style.webkitBackfaceVisibility = 'hidden';
18448			}
18449
18450			if(!out) {
18451				_currZoomLevel = thumbBounds.w / item.w;
18452				_panOffset.x = thumbBounds.x;
18453				_panOffset.y = thumbBounds.y - _initalWindowScrollY;
18454
18455				self[fadeEverything ? 'template' : 'bg'].style.opacity = 0.001;
18456				_applyCurrentZoomPan();
18457			}
18458
18459			_registerStartAnimation('initialZoom');
18460			
18461			if(out && !closeWithRaf) {
18462				framework.removeClass(template, 'pswp--animated-in');
18463			}
18464
18465			if(fadeEverything) {
18466				if(out) {
18467					framework[ (closeWithRaf ? 'remove' : 'add') + 'Class' ](template, 'pswp--animate_opacity');
18468				} else {
18469					setTimeout(function() {
18470						framework.addClass(template, 'pswp--animate_opacity');
18471					}, 30);
18472				}
18473			}
18474
18475			_showOrHideTimeout = setTimeout(function() {
18476
18477				_shout('initialZoom' + (out ? 'Out' : 'In') );
18478				
18479
18480				if(!out) {
18481
18482					// "in" animation always uses CSS transitions (instead of rAF).
18483					// CSS transition work faster here, 
18484					// as developer may also want to animate other things, 
18485					// like ui on top of sliding area, which can be animated just via CSS
18486					
18487					_currZoomLevel = item.initialZoomLevel;
18488					_equalizePoints(_panOffset,  item.initialPosition );
18489					_applyCurrentZoomPan();
18490					_applyBgOpacity(1);
18491
18492					if(fadeEverything) {
18493						template.style.opacity = 1;
18494					} else {
18495						_applyBgOpacity(1);
18496					}
18497
18498					_showOrHideTimeout = setTimeout(onComplete, duration + 20);
18499				} else {
18500
18501					// "out" animation uses rAF only when PhotoSwipe is closed by browser scroll, to recalculate position
18502					var destZoomLevel = thumbBounds.w / item.w,
18503						initialPanOffset = {
18504							x: _panOffset.x,
18505							y: _panOffset.y
18506						},
18507						initialZoomLevel = _currZoomLevel,
18508						initalBgOpacity = _bgOpacity,
18509						onUpdate = function(now) {
18510							
18511							if(now === 1) {
18512								_currZoomLevel = destZoomLevel;
18513								_panOffset.x = thumbBounds.x;
18514								_panOffset.y = thumbBounds.y  - _currentWindowScrollY;
18515							} else {
18516								_currZoomLevel = (destZoomLevel - initialZoomLevel) * now + initialZoomLevel;
18517								_panOffset.x = (thumbBounds.x - initialPanOffset.x) * now + initialPanOffset.x;
18518								_panOffset.y = (thumbBounds.y - _currentWindowScrollY - initialPanOffset.y) * now + initialPanOffset.y;
18519							}
18520							
18521							_applyCurrentZoomPan();
18522							if(fadeEverything) {
18523								template.style.opacity = 1 - now;
18524							} else {
18525								_applyBgOpacity( initalBgOpacity - now * initalBgOpacity );
18526							}
18527						};
18528
18529					if(closeWithRaf) {
18530						_animateProp('initialZoom', 0, 1, duration, framework.easing.cubic.out, onUpdate, onComplete);
18531					} else {
18532						onUpdate(1);
18533						_showOrHideTimeout = setTimeout(onComplete, duration + 20);
18534					}
18535				}
18536			
18537			}, out ? 25 : 90); // Main purpose of this delay is to give browser time to paint and
18538					// create composite layers of PhotoSwipe UI parts (background, controls, caption, arrows).
18539					// Which avoids lag at the beginning of scale transition.
18540		};
18541		startAnimation();
18542
18543		
18544	};
18545
18546/*>>show-hide-transition*/
18547
18548/*>>items-controller*/
18549/**
18550*
18551* Controller manages gallery items, their dimensions, and their content.
18552* 
18553*/
18554
18555var _items,
18556	_tempPanAreaSize = {},
18557	_imagesToAppendPool = [],
18558	_initialContentSet,
18559	_initialZoomRunning,
18560	_controllerDefaultOptions = {
18561		index: 0,
18562		errorMsg: '<div class="pswp__error-msg"><a href="%url%" target="_blank">The image</a> could not be loaded.</div>',
18563		forceProgressiveLoading: false, // TODO
18564		preload: [1,1],
18565		getNumItemsFn: function() {
18566			return _items.length;
18567		}
18568	};
18569
18570
18571var _getItemAt,
18572	_getNumItems,
18573	_initialIsLoop,
18574	_getZeroBounds = function() {
18575		return {
18576			center:{x:0,y:0}, 
18577			max:{x:0,y:0}, 
18578			min:{x:0,y:0}
18579		};
18580	},
18581	_calculateSingleItemPanBounds = function(item, realPanElementW, realPanElementH ) {
18582		var bounds = item.bounds;
18583
18584		// position of element when it's centered
18585		bounds.center.x = Math.round((_tempPanAreaSize.x - realPanElementW) / 2);
18586		bounds.center.y = Math.round((_tempPanAreaSize.y - realPanElementH) / 2) + item.vGap.top;
18587
18588		// maximum pan position
18589		bounds.max.x = (realPanElementW > _tempPanAreaSize.x) ? 
18590							Math.round(_tempPanAreaSize.x - realPanElementW) : 
18591							bounds.center.x;
18592		
18593		bounds.max.y = (realPanElementH > _tempPanAreaSize.y) ? 
18594							Math.round(_tempPanAreaSize.y - realPanElementH) + item.vGap.top : 
18595							bounds.center.y;
18596		
18597		// minimum pan position
18598		bounds.min.x = (realPanElementW > _tempPanAreaSize.x) ? 0 : bounds.center.x;
18599		bounds.min.y = (realPanElementH > _tempPanAreaSize.y) ? item.vGap.top : bounds.center.y;
18600	},
18601	_calculateItemSize = function(item, viewportSize, zoomLevel) {
18602
18603		if (item.src && !item.loadError) {
18604			var isInitial = !zoomLevel;
18605			
18606			if(isInitial) {
18607				if(!item.vGap) {
18608					item.vGap = {top:0,bottom:0};
18609				}
18610				// allows overriding vertical margin for individual items
18611				_shout('parseVerticalMargin', item);
18612			}
18613
18614
18615			_tempPanAreaSize.x = viewportSize.x;
18616			_tempPanAreaSize.y = viewportSize.y - item.vGap.top - item.vGap.bottom;
18617
18618			if (isInitial) {
18619				var hRatio = _tempPanAreaSize.x / item.w;
18620				var vRatio = _tempPanAreaSize.y / item.h;
18621
18622				item.fitRatio = hRatio < vRatio ? hRatio : vRatio;
18623				//item.fillRatio = hRatio > vRatio ? hRatio : vRatio;
18624
18625				var scaleMode = _options.scaleMode;
18626
18627				if (scaleMode === 'orig') {
18628					zoomLevel = 1;
18629				} else if (scaleMode === 'fit') {
18630					zoomLevel = item.fitRatio;
18631				}
18632
18633				if (zoomLevel > 1) {
18634					zoomLevel = 1;
18635				}
18636
18637				item.initialZoomLevel = zoomLevel;
18638				
18639				if(!item.bounds) {
18640					// reuse bounds object
18641					item.bounds = _getZeroBounds(); 
18642				}
18643			}
18644
18645			if(!zoomLevel) {
18646				return;
18647			}
18648
18649			_calculateSingleItemPanBounds(item, item.w * zoomLevel, item.h * zoomLevel);
18650
18651			if (isInitial && zoomLevel === item.initialZoomLevel) {
18652				item.initialPosition = item.bounds.center;
18653			}
18654
18655			return item.bounds;
18656		} else {
18657			item.w = item.h = 0;
18658			item.initialZoomLevel = item.fitRatio = 1;
18659			item.bounds = _getZeroBounds();
18660			item.initialPosition = item.bounds.center;
18661
18662			// if it's not image, we return zero bounds (content is not zoomable)
18663			return item.bounds;
18664		}
18665		
18666	},
18667
18668	
18669
18670
18671	_appendImage = function(index, item, baseDiv, img, preventAnimation, keepPlaceholder) {
18672		
18673
18674		if(item.loadError) {
18675			return;
18676		}
18677
18678		if(img) {
18679
18680			item.imageAppended = true;
18681			_setImageSize(item, img, (item === self.currItem && _renderMaxResolution) );
18682			
18683			baseDiv.appendChild(img);
18684
18685			if(keepPlaceholder) {
18686				setTimeout(function() {
18687					if(item && item.loaded && item.placeholder) {
18688						item.placeholder.style.display = 'none';
18689						item.placeholder = null;
18690					}
18691				}, 500);
18692			}
18693		}
18694	},
18695	
18696
18697
18698	_preloadImage = function(item) {
18699		item.loading = true;
18700		item.loaded = false;
18701		var img = item.img = framework.createEl('pswp__img', 'img');
18702		var onComplete = function() {
18703			item.loading = false;
18704			item.loaded = true;
18705
18706			if(item.loadComplete) {
18707				item.loadComplete(item);
18708			} else {
18709				item.img = null; // no need to store image object
18710			}
18711			img.onload = img.onerror = null;
18712			img = null;
18713		};
18714		img.onload = onComplete;
18715		img.onerror = function() {
18716			item.loadError = true;
18717			onComplete();
18718		};		
18719
18720		img.src = item.src;// + '?a=' + Math.random();
18721
18722		return img;
18723	},
18724	_checkForError = function(item, cleanUp) {
18725		if(item.src && item.loadError && item.container) {
18726
18727			if(cleanUp) {
18728				item.container.innerHTML = '';
18729			}
18730
18731			item.container.innerHTML = _options.errorMsg.replace('%url%',  item.src );
18732			return true;
18733			
18734		}
18735	},
18736	_setImageSize = function(item, img, maxRes) {
18737		if(!item.src) {
18738			return;
18739		}
18740
18741		if(!img) {
18742			img = item.container.lastChild;
18743		}
18744
18745		var w = maxRes ? item.w : Math.round(item.w * item.fitRatio),
18746			h = maxRes ? item.h : Math.round(item.h * item.fitRatio);
18747		
18748		if(item.placeholder && !item.loaded) {
18749			item.placeholder.style.width = w + 'px';
18750			item.placeholder.style.height = h + 'px';
18751		}
18752
18753		img.style.width = w + 'px';
18754		img.style.height = h + 'px';
18755	},
18756	_appendImagesPool = function() {
18757
18758		if(_imagesToAppendPool.length) {
18759			var poolItem;
18760
18761			for(var i = 0; i < _imagesToAppendPool.length; i++) {
18762				poolItem = _imagesToAppendPool[i];
18763				if( poolItem.holder.index === poolItem.index ) {
18764					_appendImage(poolItem.index, poolItem.item, poolItem.baseDiv, poolItem.img, false, poolItem.clearPlaceholder);
18765				}
18766			}
18767			_imagesToAppendPool = [];
18768		}
18769	};
18770	
18771
18772
18773_registerModule('Controller', {
18774
18775	publicMethods: {
18776
18777		lazyLoadItem: function(index) {
18778			index = _getLoopedId(index);
18779			var item = _getItemAt(index);
18780
18781			if(!item || ((item.loaded || item.loading) && !_itemsNeedUpdate)) {
18782				return;
18783			}
18784
18785			_shout('gettingData', index, item);
18786
18787			if (!item.src) {
18788				return;
18789			}
18790
18791			_preloadImage(item);
18792		},
18793		initController: function() {
18794			framework.extend(_options, _controllerDefaultOptions, true);
18795			self.items = _items = items;
18796			_getItemAt = self.getItemAt;
18797			_getNumItems = _options.getNumItemsFn; //self.getNumItems;
18798
18799
18800
18801			_initialIsLoop = _options.loop;
18802			if(_getNumItems() < 3) {
18803				_options.loop = false; // disable loop if less then 3 items
18804			}
18805
18806			_listen('beforeChange', function(diff) {
18807
18808				var p = _options.preload,
18809					isNext = diff === null ? true : (diff >= 0),
18810					preloadBefore = Math.min(p[0], _getNumItems() ),
18811					preloadAfter = Math.min(p[1], _getNumItems() ),
18812					i;
18813
18814
18815				for(i = 1; i <= (isNext ? preloadAfter : preloadBefore); i++) {
18816					self.lazyLoadItem(_currentItemIndex+i);
18817				}
18818				for(i = 1; i <= (isNext ? preloadBefore : preloadAfter); i++) {
18819					self.lazyLoadItem(_currentItemIndex-i);
18820				}
18821			});
18822
18823			_listen('initialLayout', function() {
18824				self.currItem.initialLayout = _options.getThumbBoundsFn && _options.getThumbBoundsFn(_currentItemIndex);
18825			});
18826
18827			_listen('mainScrollAnimComplete', _appendImagesPool);
18828			_listen('initialZoomInEnd', _appendImagesPool);
18829
18830
18831
18832			_listen('destroy', function() {
18833				var item;
18834				for(var i = 0; i < _items.length; i++) {
18835					item = _items[i];
18836					// remove reference to DOM elements, for GC
18837					if(item.container) {
18838						item.container = null; 
18839					}
18840					if(item.placeholder) {
18841						item.placeholder = null;
18842					}
18843					if(item.img) {
18844						item.img = null;
18845					}
18846					if(item.preloader) {
18847						item.preloader = null;
18848					}
18849					if(item.loadError) {
18850						item.loaded = item.loadError = false;
18851					}
18852				}
18853				_imagesToAppendPool = null;
18854			});
18855		},
18856
18857
18858		getItemAt: function(index) {
18859			if (index >= 0) {
18860				return _items[index] !== undefined ? _items[index] : false;
18861			}
18862			return false;
18863		},
18864
18865		allowProgressiveImg: function() {
18866			// 1. Progressive image loading isn't working on webkit/blink 
18867			//    when hw-acceleration (e.g. translateZ) is applied to IMG element.
18868			//    That's why in PhotoSwipe parent element gets zoom transform, not image itself.
18869			//    
18870			// 2. Progressive image loading sometimes blinks in webkit/blink when applying animation to parent element.
18871			//    That's why it's disabled on touch devices (mainly because of swipe transition)
18872			//    
18873			// 3. Progressive image loading sometimes doesn't work in IE (up to 11).
18874
18875			// Don't allow progressive loading on non-large touch devices
18876			return _options.forceProgressiveLoading || !_likelyTouchDevice || _options.mouseUsed || screen.width > 1200; 
18877			// 1200 - to eliminate touch devices with large screen (like Chromebook Pixel)
18878		},
18879
18880		setContent: function(holder, index) {
18881
18882			if(_options.loop) {
18883				index = _getLoopedId(index);
18884			}
18885
18886			var prevItem = self.getItemAt(holder.index);
18887			if(prevItem) {
18888				prevItem.container = null;
18889			}
18890	
18891			var item = self.getItemAt(index),
18892				img;
18893			
18894			if(!item) {
18895				holder.el.innerHTML = '';
18896				return;
18897			}
18898
18899			// allow to override data
18900			_shout('gettingData', index, item);
18901
18902			holder.index = index;
18903			holder.item = item;
18904
18905			// base container DIV is created only once for each of 3 holders
18906			var baseDiv = item.container = framework.createEl('pswp__zoom-wrap'); 
18907
18908			
18909
18910			if(!item.src && item.html) {
18911				if(item.html.tagName) {
18912					baseDiv.appendChild(item.html);
18913				} else {
18914					baseDiv.innerHTML = item.html;
18915				}
18916			}
18917
18918			_checkForError(item);
18919
18920			_calculateItemSize(item, _viewportSize);
18921			
18922			if(item.src && !item.loadError && !item.loaded) {
18923
18924				item.loadComplete = function(item) {
18925
18926					// gallery closed before image finished loading
18927					if(!_isOpen) {
18928						return;
18929					}
18930
18931					// check if holder hasn't changed while image was loading
18932					if(holder && holder.index === index ) {
18933						if( _checkForError(item, true) ) {
18934							item.loadComplete = item.img = null;
18935							_calculateItemSize(item, _viewportSize);
18936							_applyZoomPanToItem(item);
18937
18938							if(holder.index === _currentItemIndex) {
18939								// recalculate dimensions
18940								self.updateCurrZoomItem();
18941							}
18942							return;
18943						}
18944						if( !item.imageAppended ) {
18945							if(_features.transform && (_mainScrollAnimating || _initialZoomRunning) ) {
18946								_imagesToAppendPool.push({
18947									item:item,
18948									baseDiv:baseDiv,
18949									img:item.img,
18950									index:index,
18951									holder:holder,
18952									clearPlaceholder:true
18953								});
18954							} else {
18955								_appendImage(index, item, baseDiv, item.img, _mainScrollAnimating || _initialZoomRunning, true);
18956							}
18957						} else {
18958							// remove preloader & mini-img
18959							if(!_initialZoomRunning && item.placeholder) {
18960								item.placeholder.style.display = 'none';
18961								item.placeholder = null;
18962							}
18963						}
18964					}
18965
18966					item.loadComplete = null;
18967					item.img = null; // no need to store image element after it's added
18968
18969					_shout('imageLoadComplete', index, item);
18970				};
18971
18972				if(framework.features.transform) {
18973					
18974					var placeholderClassName = 'pswp__img pswp__img--placeholder'; 
18975					placeholderClassName += (item.msrc ? '' : ' pswp__img--placeholder--blank');
18976
18977					var placeholder = framework.createEl(placeholderClassName, item.msrc ? 'img' : '');
18978					if(item.msrc) {
18979						placeholder.src = item.msrc;
18980					}
18981					
18982					_setImageSize(item, placeholder);
18983
18984					baseDiv.appendChild(placeholder);
18985					item.placeholder = placeholder;
18986
18987				}
18988				
18989
18990				
18991
18992				if(!item.loading) {
18993					_preloadImage(item);
18994				}
18995
18996
18997				if( self.allowProgressiveImg() ) {
18998					// just append image
18999					if(!_initialContentSet && _features.transform) {
19000						_imagesToAppendPool.push({
19001							item:item, 
19002							baseDiv:baseDiv, 
19003							img:item.img, 
19004							index:index, 
19005							holder:holder
19006						});
19007					} else {
19008						_appendImage(index, item, baseDiv, item.img, true, true);
19009					}
19010				}
19011				
19012			} else if(item.src && !item.loadError) {
19013				// image object is created every time, due to bugs of image loading & delay when switching images
19014				img = framework.createEl('pswp__img', 'img');
19015				img.style.opacity = 1;
19016				img.src = item.src;
19017				_setImageSize(item, img);
19018				_appendImage(index, item, baseDiv, img, true);
19019			}
19020			
19021
19022			if(!_initialContentSet && index === _currentItemIndex) {
19023				_currZoomElementStyle = baseDiv.style;
19024				_showOrHide(item, (img ||item.img) );
19025			} else {
19026				_applyZoomPanToItem(item);
19027			}
19028
19029			holder.el.innerHTML = '';
19030			holder.el.appendChild(baseDiv);
19031		},
19032
19033		cleanSlide: function( item ) {
19034			if(item.img ) {
19035				item.img.onload = item.img.onerror = null;
19036			}
19037			item.loaded = item.loading = item.img = item.imageAppended = false;
19038		}
19039
19040	}
19041});
19042
19043/*>>items-controller*/
19044
19045/*>>tap*/
19046/**
19047 * tap.js:
19048 *
19049 * Displatches tap and double-tap events.
19050 * 
19051 */
19052
19053var tapTimer,
19054	tapReleasePoint = {},
19055	_dispatchTapEvent = function(origEvent, releasePoint, pointerType) {		
19056		var e = document.createEvent( 'CustomEvent' ),
19057			eDetail = {
19058				origEvent:origEvent, 
19059				target:origEvent.target, 
19060				releasePoint: releasePoint, 
19061				pointerType:pointerType || 'touch'
19062			};
19063
19064		e.initCustomEvent( 'pswpTap', true, true, eDetail );
19065		origEvent.target.dispatchEvent(e);
19066	};
19067
19068_registerModule('Tap', {
19069	publicMethods: {
19070		initTap: function() {
19071			_listen('firstTouchStart', self.onTapStart);
19072			_listen('touchRelease', self.onTapRelease);
19073			_listen('destroy', function() {
19074				tapReleasePoint = {};
19075				tapTimer = null;
19076			});
19077		},
19078		onTapStart: function(touchList) {
19079			if(touchList.length > 1) {
19080				clearTimeout(tapTimer);
19081				tapTimer = null;
19082			}
19083		},
19084		onTapRelease: function(e, releasePoint) {
19085			if(!releasePoint) {
19086				return;
19087			}
19088
19089			if(!_moved && !_isMultitouch && !_numAnimations) {
19090				var p0 = releasePoint;
19091				if(tapTimer) {
19092					clearTimeout(tapTimer);
19093					tapTimer = null;
19094
19095					// Check if taped on the same place
19096					if ( _isNearbyPoints(p0, tapReleasePoint) ) {
19097						_shout('doubleTap', p0);
19098						return;
19099					}
19100				}
19101
19102				if(releasePoint.type === 'mouse') {
19103					_dispatchTapEvent(e, releasePoint, 'mouse');
19104					return;
19105				}
19106
19107				var clickedTagName = e.target.tagName.toUpperCase();
19108				// avoid double tap delay on buttons and elements that have class pswp__single-tap
19109				if(clickedTagName === 'BUTTON' || framework.hasClass(e.target, 'pswp__single-tap') ) {
19110					_dispatchTapEvent(e, releasePoint);
19111					return;
19112				}
19113
19114				_equalizePoints(tapReleasePoint, p0);
19115
19116				tapTimer = setTimeout(function() {
19117					_dispatchTapEvent(e, releasePoint);
19118					tapTimer = null;
19119				}, 300);
19120			}
19121		}
19122	}
19123});
19124
19125/*>>tap*/
19126
19127/*>>desktop-zoom*/
19128/**
19129 *
19130 * desktop-zoom.js:
19131 *
19132 * - Binds mousewheel event for paning zoomed image.
19133 * - Manages "dragging", "zoomed-in", "zoom-out" classes.
19134 *   (which are used for cursors and zoom icon)
19135 * - Adds toggleDesktopZoom function.
19136 * 
19137 */
19138
19139var _wheelDelta;
19140	
19141_registerModule('DesktopZoom', {
19142
19143	publicMethods: {
19144
19145		initDesktopZoom: function() {
19146
19147			if(_oldIE) {
19148				// no zoom for old IE (<=8)
19149				return;
19150			}
19151
19152			if(_likelyTouchDevice) {
19153				// if detected hardware touch support, we wait until mouse is used,
19154				// and only then apply desktop-zoom features
19155				_listen('mouseUsed', function() {
19156					self.setupDesktopZoom();
19157				});
19158			} else {
19159				self.setupDesktopZoom(true);
19160			}
19161
19162		},
19163
19164		setupDesktopZoom: function(onInit) {
19165
19166			_wheelDelta = {};
19167
19168			var events = 'wheel mousewheel DOMMouseScroll';
19169			
19170			_listen('bindEvents', function() {
19171				framework.bind(template, events,  self.handleMouseWheel);
19172			});
19173
19174			_listen('unbindEvents', function() {
19175				if(_wheelDelta) {
19176					framework.unbind(template, events, self.handleMouseWheel);
19177				}
19178			});
19179
19180			self.mouseZoomedIn = false;
19181
19182			var hasDraggingClass,
19183				updateZoomable = function() {
19184					if(self.mouseZoomedIn) {
19185						framework.removeClass(template, 'pswp--zoomed-in');
19186						self.mouseZoomedIn = false;
19187					}
19188					if(_currZoomLevel < 1) {
19189						framework.addClass(template, 'pswp--zoom-allowed');
19190					} else {
19191						framework.removeClass(template, 'pswp--zoom-allowed');
19192					}
19193					removeDraggingClass();
19194				},
19195				removeDraggingClass = function() {
19196					if(hasDraggingClass) {
19197						framework.removeClass(template, 'pswp--dragging');
19198						hasDraggingClass = false;
19199					}
19200				};
19201
19202			_listen('resize' , updateZoomable);
19203			_listen('afterChange' , updateZoomable);
19204			_listen('pointerDown', function() {
19205				if(self.mouseZoomedIn) {
19206					hasDraggingClass = true;
19207					framework.addClass(template, 'pswp--dragging');
19208				}
19209			});
19210			_listen('pointerUp', removeDraggingClass);
19211
19212			if(!onInit) {
19213				updateZoomable();
19214			}
19215			
19216		},
19217
19218		handleMouseWheel: function(e) {
19219
19220			if(_currZoomLevel <= self.currItem.fitRatio) {
19221				if( _options.modal ) {
19222
19223					if (!_options.closeOnScroll || _numAnimations || _isDragging) {
19224						e.preventDefault();
19225					} else if(_transformKey && Math.abs(e.deltaY) > 2) {
19226						// close PhotoSwipe
19227						// if browser supports transforms & scroll changed enough
19228						_closedByScroll = true;
19229						self.close();
19230					}
19231
19232				}
19233				return true;
19234			}
19235
19236			// allow just one event to fire
19237			e.stopPropagation();
19238
19239			// https://developer.mozilla.org/en-US/docs/Web/Events/wheel
19240			_wheelDelta.x = 0;
19241
19242			if('deltaX' in e) {
19243				if(e.deltaMode === 1 /* DOM_DELTA_LINE */) {
19244					// 18 - average line height
19245					_wheelDelta.x = e.deltaX * 18;
19246					_wheelDelta.y = e.deltaY * 18;
19247				} else {
19248					_wheelDelta.x = e.deltaX;
19249					_wheelDelta.y = e.deltaY;
19250				}
19251			} else if('wheelDelta' in e) {
19252				if(e.wheelDeltaX) {
19253					_wheelDelta.x = -0.16 * e.wheelDeltaX;
19254				}
19255				if(e.wheelDeltaY) {
19256					_wheelDelta.y = -0.16 * e.wheelDeltaY;
19257				} else {
19258					_wheelDelta.y = -0.16 * e.wheelDelta;
19259				}
19260			} else if('detail' in e) {
19261				_wheelDelta.y = e.detail;
19262			} else {
19263				return;
19264			}
19265
19266			_calculatePanBounds(_currZoomLevel, true);
19267
19268			var newPanX = _panOffset.x - _wheelDelta.x,
19269				newPanY = _panOffset.y - _wheelDelta.y;
19270
19271			// only prevent scrolling in nonmodal mode when not at edges
19272			if (_options.modal ||
19273				(
19274				newPanX <= _currPanBounds.min.x && newPanX >= _currPanBounds.max.x &&
19275				newPanY <= _currPanBounds.min.y && newPanY >= _currPanBounds.max.y
19276				) ) {
19277				e.preventDefault();
19278			}
19279
19280			// TODO: use rAF instead of mousewheel?
19281			self.panTo(newPanX, newPanY);
19282		},
19283
19284		toggleDesktopZoom: function(centerPoint) {
19285			centerPoint = centerPoint || {x:_viewportSize.x/2 + _offset.x, y:_viewportSize.y/2 + _offset.y };
19286
19287			var doubleTapZoomLevel = _options.getDoubleTapZoom(true, self.currItem);
19288			var zoomOut = _currZoomLevel === doubleTapZoomLevel;
19289			
19290			self.mouseZoomedIn = !zoomOut;
19291
19292			self.zoomTo(zoomOut ? self.currItem.initialZoomLevel : doubleTapZoomLevel, centerPoint, 333);
19293			framework[ (!zoomOut ? 'add' : 'remove') + 'Class'](template, 'pswp--zoomed-in');
19294		}
19295
19296	}
19297});
19298
19299
19300/*>>desktop-zoom*/
19301
19302/*>>history*/
19303/**
19304 *
19305 * history.js:
19306 *
19307 * - Back button to close gallery.
19308 * 
19309 * - Unique URL for each slide: example.com/&pid=1&gid=3
19310 *   (where PID is picture index, and GID and gallery index)
19311 *   
19312 * - Switch URL when slides change.
19313 * 
19314 */
19315
19316
19317var _historyDefaultOptions = {
19318	history: true,
19319	galleryUID: 1
19320};
19321
19322var _historyUpdateTimeout,
19323	_hashChangeTimeout,
19324	_hashAnimCheckTimeout,
19325	_hashChangedByScript,
19326	_hashChangedByHistory,
19327	_hashReseted,
19328	_initialHash,
19329	_historyChanged,
19330	_closedFromURL,
19331	_urlChangedOnce,
19332	_windowLoc,
19333
19334	_supportsPushState,
19335
19336	_getHash = function() {
19337		return _windowLoc.hash.substring(1);
19338	},
19339	_cleanHistoryTimeouts = function() {
19340
19341		if(_historyUpdateTimeout) {
19342			clearTimeout(_historyUpdateTimeout);
19343		}
19344
19345		if(_hashAnimCheckTimeout) {
19346			clearTimeout(_hashAnimCheckTimeout);
19347		}
19348	},
19349
19350	// pid - Picture index
19351	// gid - Gallery index
19352	_parseItemIndexFromURL = function() {
19353		var hash = _getHash(),
19354			params = {};
19355
19356		if(hash.length < 5) { // pid=1
19357			return params;
19358		}
19359
19360		var i, vars = hash.split('&');
19361		for (i = 0; i < vars.length; i++) {
19362			if(!vars[i]) {
19363				continue;
19364			}
19365			var pair = vars[i].split('=');	
19366			if(pair.length < 2) {
19367				continue;
19368			}
19369			params[pair[0]] = pair[1];
19370		}
19371		if(_options.galleryPIDs) {
19372			// detect custom pid in hash and search for it among the items collection
19373			var searchfor = params.pid;
19374			params.pid = 0; // if custom pid cannot be found, fallback to the first item
19375			for(i = 0; i < _items.length; i++) {
19376				if(_items[i].pid === searchfor) {
19377					params.pid = i;
19378					break;
19379				}
19380			}
19381		} else {
19382			params.pid = parseInt(params.pid,10)-1;
19383		}
19384		if( params.pid < 0 ) {
19385			params.pid = 0;
19386		}
19387		return params;
19388	},
19389	_updateHash = function() {
19390
19391		if(_hashAnimCheckTimeout) {
19392			clearTimeout(_hashAnimCheckTimeout);
19393		}
19394
19395
19396		if(_numAnimations || _isDragging) {
19397			// changing browser URL forces layout/paint in some browsers, which causes noticable lag during animation
19398			// that's why we update hash only when no animations running
19399			_hashAnimCheckTimeout = setTimeout(_updateHash, 500);
19400			return;
19401		}
19402		
19403		if(_hashChangedByScript) {
19404			clearTimeout(_hashChangeTimeout);
19405		} else {
19406			_hashChangedByScript = true;
19407		}
19408
19409
19410		var pid = (_currentItemIndex + 1);
19411		var item = _getItemAt( _currentItemIndex );
19412		if(item.hasOwnProperty('pid')) {
19413			// carry forward any custom pid assigned to the item
19414			pid = item.pid;
19415		}
19416		var newHash = _initialHash + '&'  +  'gid=' + _options.galleryUID + '&' + 'pid=' + pid;
19417
19418		if(!_historyChanged) {
19419			if(_windowLoc.hash.indexOf(newHash) === -1) {
19420				_urlChangedOnce = true;
19421			}
19422			// first time - add new hisory record, then just replace
19423		}
19424
19425		var newURL = _windowLoc.href.split('#')[0] + '#' +  newHash;
19426
19427		if( _supportsPushState ) {
19428
19429			if('#' + newHash !== window.location.hash) {
19430				history[_historyChanged ? 'replaceState' : 'pushState']('', document.title, newURL);
19431			}
19432
19433		} else {
19434			if(_historyChanged) {
19435				_windowLoc.replace( newURL );
19436			} else {
19437				_windowLoc.hash = newHash;
19438			}
19439		}
19440		
19441		
19442
19443		_historyChanged = true;
19444		_hashChangeTimeout = setTimeout(function() {
19445			_hashChangedByScript = false;
19446		}, 60);
19447	};
19448
19449
19450
19451	
19452
19453_registerModule('History', {
19454
19455	
19456
19457	publicMethods: {
19458		initHistory: function() {
19459
19460			framework.extend(_options, _historyDefaultOptions, true);
19461
19462			if( !_options.history ) {
19463				return;
19464			}
19465
19466
19467			_windowLoc = window.location;
19468			_urlChangedOnce = false;
19469			_closedFromURL = false;
19470			_historyChanged = false;
19471			_initialHash = _getHash();
19472			_supportsPushState = ('pushState' in history);
19473
19474
19475			if(_initialHash.indexOf('gid=') > -1) {
19476				_initialHash = _initialHash.split('&gid=')[0];
19477				_initialHash = _initialHash.split('?gid=')[0];
19478			}
19479			
19480
19481			_listen('afterChange', self.updateURL);
19482			_listen('unbindEvents', function() {
19483				framework.unbind(window, 'hashchange', self.onHashChange);
19484			});
19485
19486
19487			var returnToOriginal = function() {
19488				_hashReseted = true;
19489				if(!_closedFromURL) {
19490
19491					if(_urlChangedOnce) {
19492						history.back();
19493					} else {
19494
19495						if(_initialHash) {
19496							_windowLoc.hash = _initialHash;
19497						} else {
19498							if (_supportsPushState) {
19499
19500								// remove hash from url without refreshing it or scrolling to top
19501								history.pushState('', document.title,  _windowLoc.pathname + _windowLoc.search );
19502							} else {
19503								_windowLoc.hash = '';
19504							}
19505						}
19506					}
19507					
19508				}
19509
19510				_cleanHistoryTimeouts();
19511			};
19512
19513
19514			_listen('unbindEvents', function() {
19515				if(_closedByScroll) {
19516					// if PhotoSwipe is closed by scroll, we go "back" before the closing animation starts
19517					// this is done to keep the scroll position
19518					returnToOriginal();
19519				}
19520			});
19521			_listen('destroy', function() {
19522				if(!_hashReseted) {
19523					returnToOriginal();
19524				}
19525			});
19526			_listen('firstUpdate', function() {
19527				_currentItemIndex = _parseItemIndexFromURL().pid;
19528			});
19529
19530			
19531
19532			
19533			var index = _initialHash.indexOf('pid=');
19534			if(index > -1) {
19535				_initialHash = _initialHash.substring(0, index);
19536				if(_initialHash.slice(-1) === '&') {
19537					_initialHash = _initialHash.slice(0, -1);
19538				}
19539			}
19540			
19541
19542			setTimeout(function() {
19543				if(_isOpen) { // hasn't destroyed yet
19544					framework.bind(window, 'hashchange', self.onHashChange);
19545				}
19546			}, 40);
19547			
19548		},
19549		onHashChange: function() {
19550
19551			if(_getHash() === _initialHash) {
19552
19553				_closedFromURL = true;
19554				self.close();
19555				return;
19556			}
19557			if(!_hashChangedByScript) {
19558
19559				_hashChangedByHistory = true;
19560				self.goTo( _parseItemIndexFromURL().pid );
19561				_hashChangedByHistory = false;
19562			}
19563			
19564		},
19565		updateURL: function() {
19566
19567			// Delay the update of URL, to avoid lag during transition, 
19568			// and to not to trigger actions like "refresh page sound" or "blinking favicon" to often
19569			
19570			_cleanHistoryTimeouts();
19571			
19572
19573			if(_hashChangedByHistory) {
19574				return;
19575			}
19576
19577			if(!_historyChanged) {
19578				_updateHash(); // first time
19579			} else {
19580				_historyUpdateTimeout = setTimeout(_updateHash, 800);
19581			}
19582		}
19583	
19584	}
19585});
19586
19587
19588/*>>history*/
19589	framework.extend(self, publicMethods); };
19590	return PhotoSwipe;
19591});
19592
19593/**
19594 * Swiper 4.5.0
19595 * Most modern mobile touch slider and framework with hardware accelerated transitions
19596 * http://www.idangero.us/swiper/
19597 *
19598 * Copyright 2014-2019 Vladimir Kharlampidi
19599 *
19600 * Released under the MIT License
19601 *
19602 * Released on: February 22
vendor: 41,637 bytes, lines 19602-20915
19602, 2019
19603 */
19604
19605(function (global, factory) {
19606  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19607  typeof define === 'function' && define.amd ? define(factory) :
19608  (global = global || self, global.Swiper = factory());
19609}(this, function () { 'use strict';
19610
19611  /**
19612   * SSR Window 1.0.1
19613   * Better handling for window object in SSR environment
19614   * https://github.com/nolimits4web/ssr-window
19615   *
19616   * Copyright 2018, Vladimir Kharlampidi
19617   *
19618   * Licensed under MIT
19619   *
19620   * Released on: July 18, 2018
19621   */
19622  var doc = (typeof document === 'undefined') ? {
19623    body: {},
19624    addEventListener: function addEventListener() {},
19625    removeEventListener: function removeEventListener() {},
19626    activeElement: {
19627      blur: function blur() {},
19628      nodeName: '',
19629    },
19630    querySelector: function querySelector() {
19631      return null;
19632    },
19633    querySelectorAll: function querySelectorAll() {
19634      return [];
19635    },
19636    getElementById: function getElementById() {
19637      return null;
19638    },
19639    createEvent: function createEvent() {
19640      return {
19641        initEvent: function initEvent() {},
19642      };
19643    },
19644    createElement: function createElement() {
19645      return {
19646        children: [],
19647        childNodes: [],
19648        style: {},
19649        setAttribute: function setAttribute() {},
19650        getElementsByTagName: function getElementsByTagName() {
19651          return [];
19652        },
19653      };
19654    },
19655    location: { hash: '' },
19656  } : document; // eslint-disable-line
19657
19658  var win = (typeof window === 'undefined') ? {
19659    document: doc,
19660    navigator: {
19661      userAgent: '',
19662    },
19663    location: {},
19664    history: {},
19665    CustomEvent: function CustomEvent() {
19666      return this;
19667    },
19668    addEventListener: function addEventListener() {},
19669    removeEventListener: function removeEventListener() {},
19670    getComputedStyle: function getComputedStyle() {
19671      return {
19672        getPropertyValue: function getPropertyValue() {
19673          return '';
19674        },
19675      };
19676    },
19677    Image: function Image() {},
19678    Date: function Date() {},
19679    screen: {},
19680    setTimeout: function setTimeout() {},
19681    clearTimeout: function clearTimeout() {},
19682  } : window; // eslint-disable-line
19683
19684  /**
19685   * Dom7 2.1.3
19686   * Minimalistic JavaScript library for DOM manipulation, with a jQuery-compatible API
19687   * http://framework7.io/docs/dom.html
19688   *
19689   * Copyright 2019, Vladimir Kharlampidi
19690   * The iDangero.us
19691   * http://www.idangero.us/
19692   *
19693   * Licensed under MIT
19694   *
19695   * Released on: February 11, 2019
19696   */
19697
19698  var Dom7 = function Dom7(arr) {
19699    var self = this;
19700    // Create array-like object
19701    for (var i = 0; i < arr.length; i += 1) {
19702      self[i] = arr[i];
19703    }
19704    self.length = arr.length;
19705    // Return collection with methods
19706    return this;
19707  };
19708
19709  function $(selector, context) {
19710    var arr = [];
19711    var i = 0;
19712    if (selector && !context) {
19713      if (selector instanceof Dom7) {
19714        return selector;
19715      }
19716    }
19717    if (selector) {
19718        // String
19719      if (typeof selector === 'string') {
19720        var els;
19721        var tempParent;
19722        var html = selector.trim();
19723        if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {
19724          var toCreate = 'div';
19725          if (html.indexOf('<li') === 0) { toCreate = 'ul'; }
19726          if (html.indexOf('<tr') === 0) { toCreate = 'tbody'; }
19727          if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) { toCreate = 'tr'; }
19728          if (html.indexOf('<tbody') === 0) { toCreate = 'table'; }
19729          if (html.indexOf('<option') === 0) { toCreate = 'select'; }
19730          tempParent = doc.createElement(toCreate);
19731          tempParent.innerHTML = html;
19732          for (i = 0; i < tempParent.childNodes.length; i += 1) {
19733            arr.push(tempParent.childNodes[i]);
19734          }
19735        } else {
19736          if (!context && selector[0] === '#' && !selector.match(/[ .<>:~]/)) {
19737            // Pure ID selector
19738            els = [doc.getElementById(selector.trim().split('#')[1])];
19739          } else {
19740            // Other selectors
19741            els = (context || doc).querySelectorAll(selector.trim());
19742          }
19743          for (i = 0; i < els.length; i += 1) {
19744            if (els[i]) { arr.push(els[i]); }
19745          }
19746        }
19747      } else if (selector.nodeType || selector === win || selector === doc) {
19748        // Node/element
19749        arr.push(selector);
19750      } else if (selector.length > 0 && selector[0].nodeType) {
19751        // Array of elements or instance of Dom
19752        for (i = 0; i < selector.length; i += 1) {
19753          arr.push(selector[i]);
19754        }
19755      }
19756    }
19757    return new Dom7(arr);
19758  }
19759
19760  $.fn = Dom7.prototype;
19761  $.Class = Dom7;
19762  $.Dom7 = Dom7;
19763
19764  function unique(arr) {
19765    var uniqueArray = [];
19766    for (var i = 0; i < arr.length; i += 1) {
19767      if (uniqueArray.indexOf(arr[i]) === -1) { uniqueArray.push(arr[i]); }
19768    }
19769    return uniqueArray;
19770  }
19771
19772  // Classes and attributes
19773  function addClass(className) {
19774    if (typeof className === 'undefined') {
19775      return this;
19776    }
19777    var classes = className.split(' ');
19778    for (var i = 0; i < classes.length; i += 1) {
19779      for (var j = 0; j < this.length; j += 1) {
19780        if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') { this[j].classList.add(classes[i]); }
19781      }
19782    }
19783    return this;
19784  }
19785  function removeClass(className) {
19786    var classes = className.split(' ');
19787    for (var i = 0; i < classes.length; i += 1) {
19788      for (var j = 0; j < this.length; j += 1) {
19789        if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') { this[j].classList.remove(classes[i]); }
19790      }
19791    }
19792    return this;
19793  }
19794  function hasClass(className) {
19795    if (!this[0]) { return false; }
19796    return this[0].classList.contains(className);
19797  }
19798  function toggleClass(className) {
19799    var classes = className.split(' ');
19800    for (var i = 0; i < classes.length; i += 1) {
19801      for (var j = 0; j < this.length; j += 1) {
19802        if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') { this[j].classList.toggle(classes[i]); }
19803      }
19804    }
19805    return this;
19806  }
19807  function attr(attrs, value) {
19808    var arguments$1 = arguments;
19809
19810    if (arguments.length === 1 && typeof attrs === 'string') {
19811      // Get attr
19812      if (this[0]) { return this[0].getAttribute(attrs); }
19813      return undefined;
19814    }
19815
19816    // Set attrs
19817    for (var i = 0; i < this.length; i += 1) {
19818      if (arguments$1.length === 2) {
19819        // String
19820        this[i].setAttribute(attrs, value);
19821      } else {
19822        // Object
19823        // eslint-disable-next-line
19824        for (var attrName in attrs) {
19825          this[i][attrName] = attrs[attrName];
19826          this[i].setAttribute(attrName, attrs[attrName]);
19827        }
19828      }
19829    }
19830    return this;
19831  }
19832  // eslint-disable-next-line
19833  function removeAttr(attr) {
19834    for (var i = 0; i < this.length; i += 1) {
19835      this[i].removeAttribute(attr);
19836    }
19837    return this;
19838  }
19839  function data(key, value) {
19840    var el;
19841    if (typeof value === 'undefined') {
19842      el = this[0];
19843      // Get value
19844      if (el) {
19845        if (el.dom7ElementDataStorage && (key in el.dom7ElementDataStorage)) {
19846          return el.dom7ElementDataStorage[key];
19847        }
19848
19849        var dataKey = el.getAttribute(("data-" + key));
19850        if (dataKey) {
19851          return dataKey;
19852        }
19853        return undefined;
19854      }
19855      return undefined;
19856    }
19857
19858    // Set value
19859    for (var i = 0; i < this.length; i += 1) {
19860      el = this[i];
19861      if (!el.dom7ElementDataStorage) { el.dom7ElementDataStorage = {}; }
19862      el.dom7ElementDataStorage[key] = value;
19863    }
19864    return this;
19865  }
19866  // Transforms
19867  // eslint-disable-next-line
19868  function transform(transform) {
19869    for (var i = 0; i < this.length; i += 1) {
19870      var elStyle = this[i].style;
19871      elStyle.webkitTransform = transform;
19872      elStyle.transform = transform;
19873    }
19874    return this;
19875  }
19876  function transition(duration) {
19877    if (typeof duration !== 'string') {
19878      duration = duration + "ms"; // eslint-disable-line
19879    }
19880    for (var i = 0; i < this.length; i += 1) {
19881      var elStyle = this[i].style;
19882      elStyle.webkitTransitionDuration = duration;
19883      elStyle.transitionDuration = duration;
19884    }
19885    return this;
19886  }
19887  // Events
19888  function on() {
19889    var assign;
19890
19891    var args = [], len = arguments.length;
19892    while ( len-- ) args[ len ] = arguments[ len ];
19893    var eventType = args[0];
19894    var targetSelector = args[1];
19895    var listener = args[2];
19896    var capture = args[3];
19897    if (typeof args[1] === 'function') {
19898      (assign = args, eventType = assign[0], listener = assign[1], capture = assign[2]);
19899      targetSelector = undefined;
19900    }
19901    if (!capture) { capture = false; }
19902
19903    function handleLiveEvent(e) {
19904      var target = e.target;
19905      if (!target) { return; }
19906      var eventData = e.target.dom7EventData || [];
19907      if (eventData.indexOf(e) < 0) {
19908        eventData.unshift(e);
19909      }
19910      if ($(target).is(targetSelector)) { listener.apply(target, eventData); }
19911      else {
19912        var parents = $(target).parents(); // eslint-disable-line
19913        for (var k = 0; k < parents.length; k += 1) {
19914          if ($(parents[k]).is(targetSelector)) { listener.apply(parents[k], eventData); }
19915        }
19916      }
19917    }
19918    function handleEvent(e) {
19919      var eventData = e && e.target ? e.target.dom7EventData || [] : [];
19920      if (eventData.indexOf(e) < 0) {
19921        eventData.unshift(e);
19922      }
19923      listener.apply(this, eventData);
19924    }
19925    var events = eventType.split(' ');
19926    var j;
19927    for (var i = 0; i < this.length; i += 1) {
19928      var el = this[i];
19929      if (!targetSelector) {
19930        for (j = 0; j < events.length; j += 1) {
19931          var event = events[j];
19932          if (!el.dom7Listeners) { el.dom7Listeners = {}; }
19933          if (!el.dom7Listeners[event]) { el.dom7Listeners[event] = []; }
19934          el.dom7Listeners[event].push({
19935            listener: listener,
19936            proxyListener: handleEvent,
19937          });
19938          el.addEventListener(event, handleEvent, capture);
19939        }
19940      } else {
19941        // Live events
19942        for (j = 0; j < events.length; j += 1) {
19943          var event$1 = events[j];
19944          if (!el.dom7LiveListeners) { el.dom7LiveListeners = {}; }
19945          if (!el.dom7LiveListeners[event$1]) { el.dom7LiveListeners[event$1] = []; }
19946          el.dom7LiveListeners[event$1].push({
19947            listener: listener,
19948            proxyListener: handleLiveEvent,
19949          });
19950          el.addEventListener(event$1, handleLiveEvent, capture);
19951        }
19952      }
19953    }
19954    return this;
19955  }
19956  function off() {
19957    var assign;
19958
19959    var args = [], len = arguments.length;
19960    while ( len-- ) args[ len ] = arguments[ len ];
19961    var eventType = args[0];
19962    var targetSelector = args[1];
19963    var listener = args[2];
19964    var capture = args[3];
19965    if (typeof args[1] === 'function') {
19966      (assign = args, eventType = assign[0], listener = assign[1], capture = assign[2]);
19967      targetSelector = undefined;
19968    }
19969    if (!capture) { capture = false; }
19970
19971    var events = eventType.split(' ');
19972    for (var i = 0; i < events.length; i += 1) {
19973      var event = events[i];
19974      for (var j = 0; j < this.length; j += 1) {
19975        var el = this[j];
19976        var handlers = (void 0);
19977        if (!targetSelector && el.dom7Listeners) {
19978          handlers = el.dom7Listeners[event];
19979        } else if (targetSelector && el.dom7LiveListeners) {
19980          handlers = el.dom7LiveListeners[event];
19981        }
19982        if (handlers && handlers.length) {
19983          for (var k = handlers.length - 1; k >= 0; k -= 1) {
19984            var handler = handlers[k];
19985            if (listener && handler.listener === listener) {
19986              el.removeEventListener(event, handler.proxyListener, capture);
19987              handlers.splice(k, 1);
19988            } else if (listener && handler.listener && handler.listener.dom7proxy && handler.listener.dom7proxy === listener) {
19989              el.removeEventListener(event, handler.proxyListener, capture);
19990              handlers.splice(k, 1);
19991            } else if (!listener) {
19992              el.removeEventListener(event, handler.proxyListener, capture);
19993              handlers.splice(k, 1);
19994            }
19995          }
19996        }
19997      }
19998    }
19999    return this;
20000  }
20001  function trigger() {
20002    var args = [], len = arguments.length;
20003    while ( len-- ) args[ len ] = arguments[ len ];
20004
20005    var events = args[0].split(' ');
20006    var eventData = args[1];
20007    for (var i = 0; i < events.length; i += 1) {
20008      var event = events[i];
20009      for (var j = 0; j < this.length; j += 1) {
20010        var el = this[j];
20011        var evt = (void 0);
20012        try {
20013          evt = new win.CustomEvent(event, {
20014            detail: eventData,
20015            bubbles: true,
20016            cancelable: true,
20017          });
20018        } catch (e) {
20019          evt = doc.createEvent('Event');
20020          evt.initEvent(event, true, true);
20021          evt.detail = eventData;
20022        }
20023        // eslint-disable-next-line
20024        el.dom7EventData = args.filter(function (data, dataIndex) { return dataIndex > 0; });
20025        el.dispatchEvent(evt);
20026        el.dom7EventData = [];
20027        delete el.dom7EventData;
20028      }
20029    }
20030    return this;
20031  }
20032  function transitionEnd(callback) {
20033    var events = ['webkitTransitionEnd', 'transitionend'];
20034    var dom = this;
20035    var i;
20036    function fireCallBack(e) {
20037      /* jshint validthis:true */
20038      if (e.target !== this) { return; }
20039      callback.call(this, e);
20040      for (i = 0; i < events.length; i += 1) {
20041        dom.off(events[i], fireCallBack);
20042      }
20043    }
20044    if (callback) {
20045      for (i = 0; i < events.length; i += 1) {
20046        dom.on(events[i], fireCallBack);
20047      }
20048    }
20049    return this;
20050  }
20051  function outerWidth(includeMargins) {
20052    if (this.length > 0) {
20053      if (includeMargins) {
20054        // eslint-disable-next-line
20055        var styles = this.styles();
20056        return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left'));
20057      }
20058      return this[0].offsetWidth;
20059    }
20060    return null;
20061  }
20062  function outerHeight(includeMargins) {
20063    if (this.length > 0) {
20064      if (includeMargins) {
20065        // eslint-disable-next-line
20066        var styles = this.styles();
20067        return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom'));
20068      }
20069      return this[0].offsetHeight;
20070    }
20071    return null;
20072  }
20073  function offset() {
20074    if (this.length > 0) {
20075      var el = this[0];
20076      var box = el.getBoundingClientRect();
20077      var body = doc.body;
20078      var clientTop = el.clientTop || body.clientTop || 0;
20079      var clientLeft = el.clientLeft || body.clientLeft || 0;
20080      var scrollTop = el === win ? win.scrollY : el.scrollTop;
20081      var scrollLeft = el === win ? win.scrollX : el.scrollLeft;
20082      return {
20083        top: (box.top + scrollTop) - clientTop,
20084        left: (box.left + scrollLeft) - clientLeft,
20085      };
20086    }
20087
20088    return null;
20089  }
20090  function styles() {
20091    if (this[0]) { return win.getComputedStyle(this[0], null); }
20092    return {};
20093  }
20094  function css(props, value) {
20095    var i;
20096    if (arguments.length === 1) {
20097      if (typeof props === 'string') {
20098        if (this[0]) { return win.getComputedStyle(this[0], null).getPropertyValue(props); }
20099      } else {
20100        for (i = 0; i < this.length; i += 1) {
20101          // eslint-disable-next-line
20102          for (var prop in props) {
20103            this[i].style[prop] = props[prop];
20104          }
20105        }
20106        return this;
20107      }
20108    }
20109    if (arguments.length === 2 && typeof props === 'string') {
20110      for (i = 0; i < this.length; i += 1) {
20111        this[i].style[props] = value;
20112      }
20113      return this;
20114    }
20115    return this;
20116  }
20117  // Iterate over the collection passing elements to `callback`
20118  function each(callback) {
20119    // Don't bother continuing without a callback
20120    if (!callback) { return this; }
20121    // Iterate over the current collection
20122    for (var i = 0; i < this.length; i += 1) {
20123      // If the callback returns false
20124      if (callback.call(this[i], i, this[i]) === false) {
20125        // End the loop early
20126        return this;
20127      }
20128    }
20129    // Return `this` to allow chained DOM operations
20130    return this;
20131  }
20132  // eslint-disable-next-line
20133  function html(html) {
20134    if (typeof html === 'undefined') {
20135      return this[0] ? this[0].innerHTML : undefined;
20136    }
20137
20138    for (var i = 0; i < this.length; i += 1) {
20139      this[i].innerHTML = html;
20140    }
20141    return this;
20142  }
20143  // eslint-disable-next-line
20144  function text(text) {
20145    if (typeof text === 'undefined') {
20146      if (this[0]) {
20147        return this[0].textContent.trim();
20148      }
20149      return null;
20150    }
20151
20152    for (var i = 0; i < this.length; i += 1) {
20153      this[i].textContent = text;
20154    }
20155    return this;
20156  }
20157  function is(selector) {
20158    var el = this[0];
20159    var compareWith;
20160    var i;
20161    if (!el || typeof selector === 'undefined') { return false; }
20162    if (typeof selector === 'string') {
20163      if (el.matches) { return el.matches(selector); }
20164      else if (el.webkitMatchesSelector) { return el.webkitMatchesSelector(selector); }
20165      else if (el.msMatchesSelector) { return el.msMatchesSelector(selector); }
20166
20167      compareWith = $(selector);
20168      for (i = 0; i < compareWith.length; i += 1) {
20169        if (compareWith[i] === el) { return true; }
20170      }
20171      return false;
20172    } else if (selector === doc) { return el === doc; }
20173    else if (selector === win) { return el === win; }
20174
20175    if (selector.nodeType || selector instanceof Dom7) {
20176      compareWith = selector.nodeType ? [selector] : selector;
20177      for (i = 0; i < compareWith.length; i += 1) {
20178        if (compareWith[i] === el) { return true; }
20179      }
20180      return false;
20181    }
20182    return false;
20183  }
20184  function index() {
20185    var child = this[0];
20186    var i;
20187    if (child) {
20188      i = 0;
20189      // eslint-disable-next-line
20190      while ((child = child.previousSibling) !== null) {
20191        if (child.nodeType === 1) { i += 1; }
20192      }
20193      return i;
20194    }
20195    return undefined;
20196  }
20197  // eslint-disable-next-line
20198  function eq(index) {
20199    if (typeof index === 'undefined') { return this; }
20200    var length = this.length;
20201    var returnIndex;
20202    if (index > length - 1) {
20203      return new Dom7([]);
20204    }
20205    if (index < 0) {
20206      returnIndex = length + index;
20207      if (returnIndex < 0) { return new Dom7([]); }
20208      return new Dom7([this[returnIndex]]);
20209    }
20210    return new Dom7([this[index]]);
20211  }
20212  function append() {
20213    var args = [], len = arguments.length;
20214    while ( len-- ) args[ len ] = arguments[ len ];
20215
20216    var newChild;
20217
20218    for (var k = 0; k < args.length; k += 1) {
20219      newChild = args[k];
20220      for (var i = 0; i < this.length; i += 1) {
20221        if (typeof newChild === 'string') {
20222          var tempDiv = doc.createElement('div');
20223          tempDiv.innerHTML = newChild;
20224          while (tempDiv.firstChild) {
20225            this[i].appendChild(tempDiv.firstChild);
20226          }
20227        } else if (newChild instanceof Dom7) {
20228          for (var j = 0; j < newChild.length; j += 1) {
20229            this[i].appendChild(newChild[j]);
20230          }
20231        } else {
20232          this[i].appendChild(newChild);
20233        }
20234      }
20235    }
20236
20237    return this;
20238  }
20239  function prepend(newChild) {
20240    var i;
20241    var j;
20242    for (i = 0; i < this.length; i += 1) {
20243      if (typeof newChild === 'string') {
20244        var tempDiv = doc.createElement('div');
20245        tempDiv.innerHTML = newChild;
20246        for (j = tempDiv.childNodes.length - 1; j >= 0; j -= 1) {
20247          this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);
20248        }
20249      } else if (newChild instanceof Dom7) {
20250        for (j = 0; j < newChild.length; j += 1) {
20251          this[i].insertBefore(newChild[j], this[i].childNodes[0]);
20252        }
20253      } else {
20254        this[i].insertBefore(newChild, this[i].childNodes[0]);
20255      }
20256    }
20257    return this;
20258  }
20259  function next(selector) {
20260    if (this.length > 0) {
20261      if (selector) {
20262        if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) {
20263          return new Dom7([this[0].nextElementSibling]);
20264        }
20265        return new Dom7([]);
20266      }
20267
20268      if (this[0].nextElementSibling) { return new Dom7([this[0].nextElementSibling]); }
20269      return new Dom7([]);
20270    }
20271    return new Dom7([]);
20272  }
20273  function nextAll(selector) {
20274    var nextEls = [];
20275    var el = this[0];
20276    if (!el) { return new Dom7([]); }
20277    while (el.nextElementSibling) {
20278      var next = el.nextElementSibling; // eslint-disable-line
20279      if (selector) {
20280        if ($(next).is(selector)) { nextEls.push(next); }
20281      } else { nextEls.push(next); }
20282      el = next;
20283    }
20284    return new Dom7(nextEls);
20285  }
20286  function prev(selector) {
20287    if (this.length > 0) {
20288      var el = this[0];
20289      if (selector) {
20290        if (el.previousElementSibling && $(el.previousElementSibling).is(selector)) {
20291          return new Dom7([el.previousElementSibling]);
20292        }
20293        return new Dom7([]);
20294      }
20295
20296      if (el.previousElementSibling) { return new Dom7([el.previousElementSibling]); }
20297      return new Dom7([]);
20298    }
20299    return new Dom7([]);
20300  }
20301  function prevAll(selector) {
20302    var prevEls = [];
20303    var el = this[0];
20304    if (!el) { return new Dom7([]); }
20305    while (el.previousElementSibling) {
20306      var prev = el.previousElementSibling; // eslint-disable-line
20307      if (selector) {
20308        if ($(prev).is(selector)) { prevEls.push(prev); }
20309      } else { prevEls.push(prev); }
20310      el = prev;
20311    }
20312    return new Dom7(prevEls);
20313  }
20314  function parent(selector) {
20315    var parents = []; // eslint-disable-line
20316    for (var i = 0; i < this.length; i += 1) {
20317      if (this[i].parentNode !== null) {
20318        if (selector) {
20319          if ($(this[i].parentNode).is(selector)) { parents.push(this[i].parentNode); }
20320        } else {
20321          parents.push(this[i].parentNode);
20322        }
20323      }
20324    }
20325    return $(unique(parents));
20326  }
20327  function parents(selector) {
20328    var parents = []; // eslint-disable-line
20329    for (var i = 0; i < this.length; i += 1) {
20330      var parent = this[i].parentNode; // eslint-disable-line
20331      while (parent) {
20332        if (selector) {
20333          if ($(parent).is(selector)) { parents.push(parent); }
20334        } else {
20335          parents.push(parent);
20336        }
20337        parent = parent.parentNode;
20338      }
20339    }
20340    return $(unique(parents));
20341  }
20342  function closest(selector) {
20343    var closest = this; // eslint-disable-line
20344    if (typeof selector === 'undefined') {
20345      return new Dom7([]);
20346    }
20347    if (!closest.is(selector)) {
20348      closest = closest.parents(selector).eq(0);
20349    }
20350    return closest;
20351  }
20352  function find(selector) {
20353    var foundElements = [];
20354    for (var i = 0; i < this.length; i += 1) {
20355      var found = this[i].querySelectorAll(selector);
20356      for (var j = 0; j < found.length; j += 1) {
20357        foundElements.push(found[j]);
20358      }
20359    }
20360    return new Dom7(foundElements);
20361  }
20362  function children(selector) {
20363    var children = []; // eslint-disable-line
20364    for (var i = 0; i < this.length; i += 1) {
20365      var childNodes = this[i].childNodes;
20366
20367      for (var j = 0; j < childNodes.length; j += 1) {
20368        if (!selector) {
20369          if (childNodes[j].nodeType === 1) { children.push(childNodes[j]); }
20370        } else if (childNodes[j].nodeType === 1 && $(childNodes[j]).is(selector)) {
20371          children.push(childNodes[j]);
20372        }
20373      }
20374    }
20375    return new Dom7(unique(children));
20376  }
20377  function remove() {
20378    for (var i = 0; i < this.length; i += 1) {
20379      if (this[i].parentNode) { this[i].parentNode.removeChild(this[i]); }
20380    }
20381    return this;
20382  }
20383  function add() {
20384    var args = [], len = arguments.length;
20385    while ( len-- ) args[ len ] = arguments[ len ];
20386
20387    var dom = this;
20388    var i;
20389    var j;
20390    for (i = 0; i < args.length; i += 1) {
20391      var toAdd = $(args[i]);
20392      for (j = 0; j < toAdd.length; j += 1) {
20393        dom[dom.length] = toAdd[j];
20394        dom.length += 1;
20395      }
20396    }
20397    return dom;
20398  }
20399
20400  var Methods = {
20401    addClass: addClass,
20402    removeClass: removeClass,
20403    hasClass: hasClass,
20404    toggleClass: toggleClass,
20405    attr: attr,
20406    removeAttr: removeAttr,
20407    data: data,
20408    transform: transform,
20409    transition: transition,
20410    on: on,
20411    off: off,
20412    trigger: trigger,
20413    transitionEnd: transitionEnd,
20414    outerWidth: outerWidth,
20415    outerHeight: outerHeight,
20416    offset: offset,
20417    css: css,
20418    each: each,
20419    html: html,
20420    text: text,
20421    is: is,
20422    index: index,
20423    eq: eq,
20424    append: append,
20425    prepend: prepend,
20426    next: next,
20427    nextAll: nextAll,
20428    prev: prev,
20429    prevAll: prevAll,
20430    parent: parent,
20431    parents: parents,
20432    closest: closest,
20433    find: find,
20434    children: children,
20435    remove: remove,
20436    add: add,
20437    styles: styles,
20438  };
20439
20440  Object.keys(Methods).forEach(function (methodName) {
20441    $.fn[methodName] = Methods[methodName];
20442  });
20443
20444  var Utils = {
20445    deleteProps: function deleteProps(obj) {
20446      var object = obj;
20447      Object.keys(object).forEach(function (key) {
20448        try {
20449          object[key] = null;
20450        } catch (e) {
20451          // no getter for object
20452        }
20453        try {
20454          delete object[key];
20455        } catch (e) {
20456          // something got wrong
20457        }
20458      });
20459    },
20460    nextTick: function nextTick(callback, delay) {
20461      if ( delay === void 0 ) delay = 0;
20462
20463      return setTimeout(callback, delay);
20464    },
20465    now: function now() {
20466      return Date.now();
20467    },
20468    getTranslate: function getTranslate(el, axis) {
20469      if ( axis === void 0 ) axis = 'x';
20470
20471      var matrix;
20472      var curTransform;
20473      var transformMatrix;
20474
20475      var curStyle = win.getComputedStyle(el, null);
20476
20477      if (win.WebKitCSSMatrix) {
20478        curTransform = curStyle.transform || curStyle.webkitTransform;
20479        if (curTransform.split(',').length > 6) {
20480          curTransform = curTransform.split(', ').map(function (a) { return a.replace(',', '.'); }).join(', ');
20481        }
20482        // Some old versions of Webkit choke when 'none' is passed; pass
20483        // empty string instead in this case
20484        transformMatrix = new win.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
20485      } else {
20486        transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
20487        matrix = transformMatrix.toString().split(',');
20488      }
20489
20490      if (axis === 'x') {
20491        // Latest Chrome and webkits Fix
20492        if (win.WebKitCSSMatrix) { curTransform = transformMatrix.m41; }
20493        // Crazy IE10 Matrix
20494        else if (matrix.length === 16) { curTransform = parseFloat(matrix[12]); }
20495        // Normal Browsers
20496        else { curTransform = parseFloat(matrix[4]); }
20497      }
20498      if (axis === 'y') {
20499        // Latest Chrome and webkits Fix
20500        if (win.WebKitCSSMatrix) { curTransform = transformMatrix.m42; }
20501        // Crazy IE10 Matrix
20502        else if (matrix.length === 16) { curTransform = parseFloat(matrix[13]); }
20503        // Normal Browsers
20504        else { curTransform = parseFloat(matrix[5]); }
20505      }
20506      return curTransform || 0;
20507    },
20508    parseUrlQuery: function parseUrlQuery(url) {
20509      var query = {};
20510      var urlToParse = url || win.location.href;
20511      var i;
20512      var params;
20513      var param;
20514      var length;
20515      if (typeof urlToParse === 'string' && urlToParse.length) {
20516        urlToParse = urlToParse.indexOf('?') > -1 ? urlToParse.replace(/\S*\?/, '') : '';
20517        params = urlToParse.split('&').filter(function (paramsPart) { return paramsPart !== ''; });
20518        length = params.length;
20519
20520        for (i = 0; i < length; i += 1) {
20521          param = params[i].replace(/#\S+/g, '').split('=');
20522          query[decodeURIComponent(param[0])] = typeof param[1] === 'undefined' ? undefined : decodeURIComponent(param[1]) || '';
20523        }
20524      }
20525      return query;
20526    },
20527    isObject: function isObject(o) {
20528      return typeof o === 'object' && o !== null && o.constructor && o.constructor === Object;
20529    },
20530    extend: function extend() {
20531      var args = [], len$1 = arguments.length;
20532      while ( len$1-- ) args[ len$1 ] = arguments[ len$1 ];
20533
20534      var to = Object(args[0]);
20535      for (var i = 1; i < args.length; i += 1) {
20536        var nextSource = args[i];
20537        if (nextSource !== undefined && nextSource !== null) {
20538          var keysArray = Object.keys(Object(nextSource));
20539          for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {
20540            var nextKey = keysArray[nextIndex];
20541            var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
20542            if (desc !== undefined && desc.enumerable) {
20543              if (Utils.isObject(to[nextKey]) && Utils.isObject(nextSource[nextKey])) {
20544                Utils.extend(to[nextKey], nextSource[nextKey]);
20545              } else if (!Utils.isObject(to[nextKey]) && Utils.isObject(nextSource[nextKey])) {
20546                to[nextKey] = {};
20547                Utils.extend(to[nextKey], nextSource[nextKey]);
20548              } else {
20549                to[nextKey] = nextSource[nextKey];
20550              }
20551            }
20552          }
20553        }
20554      }
20555      return to;
20556    },
20557  };
20558
20559  var Support = (function Support() {
20560    var testDiv = doc.createElement('div');
20561    return {
20562      touch: (win.Modernizr && win.Modernizr.touch === true) || (function checkTouch() {
20563        return !!((win.navigator.maxTouchPoints > 0) || ('ontouchstart' in win) || (win.DocumentTouch && doc instanceof win.DocumentTouch));
20564      }()),
20565
20566      pointerEvents: !!(win.navigator.pointerEnabled || win.PointerEvent || ('maxTouchPoints' in win.navigator && win.navigator.maxTouchPoints > 0)),
20567      prefixedPointerEvents: !!win.navigator.msPointerEnabled,
20568
20569      transition: (function checkTransition() {
20570        var style = testDiv.style;
20571        return ('transition' in style || 'webkitTransition' in style || 'MozTransition' in style);
20572      }()),
20573      transforms3d: (win.Modernizr && win.Modernizr.csstransforms3d === true) || (function checkTransforms3d() {
20574        var style = testDiv.style;
20575        return ('webkitPerspective' in style || 'MozPerspective' in style || 'OPerspective' in style || 'MsPerspective' in style || 'perspective' in style);
20576      }()),
20577
20578      flexbox: (function checkFlexbox() {
20579        var style = testDiv.style;
20580        var styles = ('alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient').split(' ');
20581        for (var i = 0; i < styles.length; i += 1) {
20582          if (styles[i] in style) { return true; }
20583        }
20584        return false;
20585      }()),
20586
20587      observer: (function checkObserver() {
20588        return ('MutationObserver' in win || 'WebkitMutationObserver' in win);
20589      }()),
20590
20591      passiveListener: (function checkPassiveListener() {
20592        var supportsPassive = false;
20593        try {
20594          var opts = Object.defineProperty({}, 'passive', {
20595            // eslint-disable-next-line
20596            get: function get() {
20597              supportsPassive = true;
20598            },
20599          });
20600          win.addEventListener('testPassiveListener', null, opts);
20601        } catch (e) {
20602          // No support
20603        }
20604        return supportsPassive;
20605      }()),
20606
20607      gestures: (function checkGestures() {
20608        return 'ongesturestart' in win;
20609      }()),
20610    };
20611  }());
20612
20613  var Browser = (function Browser() {
20614    function isSafari() {
20615      var ua = win.navigator.userAgent.toLowerCase();
20616      return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0);
20617    }
20618    return {
20619      isIE: !!win.navigator.userAgent.match(/Trident/g) || !!win.navigator.userAgent.match(/MSIE/g),
20620      isEdge: !!win.navigator.userAgent.match(/Edge/g),
20621      isSafari: isSafari(),
20622      isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(win.navigator.userAgent),
20623    };
20624  }());
20625
20626  var SwiperClass = function SwiperClass(params) {
20627    if ( params === void 0 ) params = {};
20628
20629    var self = this;
20630    self.params = params;
20631
20632    // Events
20633    self.eventsListeners = {};
20634
20635    if (self.params && self.params.on) {
20636      Object.keys(self.params.on).forEach(function (eventName) {
20637        self.on(eventName, self.params.on[eventName]);
20638      });
20639    }
20640  };
20641
20642  var staticAccessors = { components: { configurable: true } };
20643
20644  SwiperClass.prototype.on = function on (events, handler, priority) {
20645    var self = this;
20646    if (typeof handler !== 'function') { return self; }
20647    var method = priority ? 'unshift' : 'push';
20648    events.split(' ').forEach(function (event) {
20649      if (!self.eventsListeners[event]) { self.eventsListeners[event] = []; }
20650      self.eventsListeners[event][method](handler);
20651    });
20652    return self;
20653  };
20654
20655  SwiperClass.prototype.once = function once (events, handler, priority) {
20656    var self = this;
20657    if (typeof handler !== 'function') { return self; }
20658    function onceHandler() {
20659        var args = [], len = arguments.length;
20660        while ( len-- ) args[ len ] = arguments[ len ];
20661
20662      handler.apply(self, args);
20663      self.off(events, onceHandler);
20664      if (onceHandler.f7proxy) {
20665        delete onceHandler.f7proxy;
20666      }
20667    }
20668    onceHandler.f7proxy = handler;
20669    return self.on(events, onceHandler, priority);
20670  };
20671
20672  SwiperClass.prototype.off = function off (events, handler) {
20673    var self = this;
20674    if (!self.eventsListeners) { return self; }
20675    events.split(' ').forEach(function (event) {
20676      if (typeof handler === 'undefined') {
20677        self.eventsListeners[event] = [];
20678      } else if (self.eventsListeners[event] && self.eventsListeners[event].length) {
20679        self.eventsListeners[event].forEach(function (eventHandler, index) {
20680          if (eventHandler === handler || (eventHandler.f7proxy && eventHandler.f7proxy === handler)) {
20681            self.eventsListeners[event].splice(index, 1);
20682          }
20683        });
20684      }
20685    });
20686    return self;
20687  };
20688
20689  SwiperClass.prototype.emit = function emit () {
20690      var args = [], len = arguments.length;
20691      while ( len-- ) args[ len ] = arguments[ len ];
20692
20693    var self = this;
20694    if (!self.eventsListeners) { return self; }
20695    var events;
20696    var data;
20697    var context;
20698    if (typeof args[0] === 'string' || Array.isArray(args[0])) {
20699      events = args[0];
20700      data = args.slice(1, args.length);
20701      context = self;
20702    } else {
20703      events = args[0].events;
20704      data = args[0].data;
20705      context = args[0].context || self;
20706    }
20707    var eventsArray = Array.isArray(events) ? events : events.split(' ');
20708    eventsArray.forEach(function (event) {
20709      if (self.eventsListeners && self.eventsListeners[event]) {
20710        var handlers = [];
20711        self.eventsListeners[event].forEach(function (eventHandler) {
20712          handlers.push(eventHandler);
20713        });
20714        handlers.forEach(function (eventHandler) {
20715          eventHandler.apply(context, data);
20716        });
20717      }
20718    });
20719    return self;
20720  };
20721
20722  SwiperClass.prototype.useModulesParams = function useModulesParams (instanceParams) {
20723    var instance = this;
20724    if (!instance.modules) { return; }
20725    Object.keys(instance.modules).forEach(function (moduleName) {
20726      var module = instance.modules[moduleName];
20727      // Extend params
20728      if (module.params) {
20729        Utils.extend(instanceParams, module.params);
20730      }
20731    });
20732  };
20733
20734  SwiperClass.prototype.useModules = function useModules (modulesParams) {
20735      if ( modulesParams === void 0 ) modulesParams = {};
20736
20737    var instance = this;
20738    if (!instance.modules) { return; }
20739    Object.keys(instance.modules).forEach(function (moduleName) {
20740      var module = instance.modules[moduleName];
20741      var moduleParams = modulesParams[moduleName] || {};
20742      // Extend instance methods and props
20743      if (module.instance) {
20744        Object.keys(module.instance).forEach(function (modulePropName) {
20745          var moduleProp = module.instance[modulePropName];
20746          if (typeof moduleProp === 'function') {
20747            instance[modulePropName] = moduleProp.bind(instance);
20748          } else {
20749            instance[modulePropName] = moduleProp;
20750          }
20751        });
20752      }
20753      // Add event listeners
20754      if (module.on && instance.on) {
20755        Object.keys(module.on).forEach(function (moduleEventName) {
20756          instance.on(moduleEventName, module.on[moduleEventName]);
20757        });
20758      }
20759
20760      // Module create callback
20761      if (module.create) {
20762        module.create.bind(instance)(moduleParams);
20763      }
20764    });
20765  };
20766
20767  staticAccessors.components.set = function (components) {
20768    var Class = this;
20769    if (!Class.use) { return; }
20770    Class.use(components);
20771  };
20772
20773  SwiperClass.installModule = function installModule (module) {
20774      var params = [], len = arguments.length - 1;
20775      while ( len-- > 0 ) params[ len ] = arguments[ len + 1 ];
20776
20777    var Class = this;
20778    if (!Class.prototype.modules) { Class.prototype.modules = {}; }
20779    var name = module.name || (((Object.keys(Class.prototype.modules).length) + "_" + (Utils.now())));
20780    Class.prototype.modules[name] = module;
20781    // Prototype
20782    if (module.proto) {
20783      Object.keys(module.proto).forEach(function (key) {
20784        Class.prototype[key] = module.proto[key];
20785      });
20786    }
20787    // Class
20788    if (module.static) {
20789      Object.keys(module.static).forEach(function (key) {
20790        Class[key] = module.static[key];
20791      });
20792    }
20793    // Callback
20794    if (module.install) {
20795      module.install.apply(Class, params);
20796    }
20797    return Class;
20798  };
20799
20800  SwiperClass.use = function use (module) {
20801      var params = [], len = arguments.length - 1;
20802      while ( len-- > 0 ) params[ len ] = arguments[ len + 1 ];
20803
20804    var Class = this;
20805    if (Array.isArray(module)) {
20806      module.forEach(function (m) { return Class.installModule(m); });
20807      return Class;
20808    }
20809    return Class.installModule.apply(Class, [ module ].concat( params ));
20810  };
20811
20812  Object.defineProperties( SwiperClass, staticAccessors );
20813
20814  function updateSize () {
20815    var swiper = this;
20816    var width;
20817    var height;
20818    var $el = swiper.$el;
20819    if (typeof swiper.params.width !== 'undefined') {
20820      width = swiper.params.width;
20821    } else {
20822      width = $el[0].clientWidth;
20823    }
20824    if (typeof swiper.params.height !== 'undefined') {
20825      height = swiper.params.height;
20826    } else {
20827      height = $el[0].clientHeight;
20828    }
20829    if ((width === 0 && swiper.isHorizontal()) || (height === 0 && swiper.isVertical())) {
20830      return;
20831    }
20832
20833    // Subtract paddings
20834    width = width - parseInt($el.css('padding-left'), 10) - parseInt($el.css('padding-right'), 10);
20835    height = height - parseInt($el.css('padding-top'), 10) - parseInt($el.css('padding-bottom'), 10);
20836
20837    Utils.extend(swiper, {
20838      width: width,
20839      height: height,
20840      size: swiper.isHorizontal() ? width : height,
20841    });
20842  }
20843
20844  function updateSlides () {
20845    var swiper = this;
20846    var params = swiper.params;
20847
20848    var $wrapperEl = swiper.$wrapperEl;
20849    var swiperSize = swiper.size;
20850    var rtl = swiper.rtlTranslate;
20851    var wrongRTL = swiper.wrongRTL;
20852    var isVirtual = swiper.virtual && params.virtual.enabled;
20853    var previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;
20854    var slides = $wrapperEl.children(("." + (swiper.params.slideClass)));
20855    var slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;
20856    var snapGrid = [];
20857    var slidesGrid = [];
20858    var slidesSizesGrid = [];
20859
20860    var offsetBefore = params.slidesOffsetBefore;
20861    if (typeof offsetBefore === 'function') {
20862      offsetBefore = params.slidesOffsetBefore.call(swiper);
20863    }
20864
20865    var offsetAfter = params.slidesOffsetAfter;
20866    if (typeof offsetAfter === 'function') {
20867      offsetAfter = params.slidesOffsetAfter.call(swiper);
20868    }
20869
20870    var previousSnapGridLength = swiper.snapGrid.length;
20871    var previousSlidesGridLength = swiper.snapGrid.length;
20872
20873    var spaceBetween = params.spaceBetween;
20874    var slidePosition = -offsetBefore;
20875    var prevSlideSize = 0;
20876    var index = 0;
20877    if (typeof swiperSize === 'undefined') {
20878      return;
20879    }
20880    if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
20881      spaceBetween = (parseFloat(spaceBetween.replace('%', '')) / 100) * swiperSize;
20882    }
20883
20884    swiper.virtualSize = -spaceBetween;
20885
20886    // reset margins
20887    if (rtl) { slides.css({ marginLeft: '', marginTop: '' }); }
20888    else { slides.css({ marginRight: '', marginBottom: '' }); }
20889
20890    var slidesNumberEvenToRows;
20891    if (params.slidesPerColumn > 1) {
20892      if (Math.floor(slidesLength / params.slidesPerColumn) === slidesLength / swiper.params.slidesPerColumn) {
20893        slidesNumberEvenToRows = slidesLength;
20894      } else {
20895        slidesNumberEvenToRows = Math.ceil(slidesLength / params.slidesPerColumn) * params.slidesPerColumn;
20896      }
20897      if (params.slidesPerView !== 'auto' && params.slidesPerColumnFill === 'row') {
20898        slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, params.slidesPerView * params.slidesPerColumn);
20899      }
20900    }
20901
20902    // Calc slides
20903    var slideSize;
20904    var slidesPerColumn = params.slidesPerColumn;
20905    var slidesPerRow = slidesNumberEvenToRows / slidesPerColumn;
20906    var numFullColumns = Math.floor(slidesLength / params.slidesPerColumn);
20907    for (var i = 0; i < slidesLength; i += 1) {
20908      slideSize = 0;
20909      var slide = slides.eq(i);
20910      if (params.slidesPerColumn > 1) {
20911        // Set slides order
20912        var newSlideOrderIndex = (void 0);
20913        var column = (void 0);
20914        var row = (void 0);
20915        if (
vendor: 12,118 bytes, lines 20915-21216
20915params.slidesPerColumnFill === 'column') {
20916          column = Math.floor(i / slidesPerColumn);
20917          row = i - (column * slidesPerColumn);
20918          if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn - 1)) {
20919            row += 1;
20920            if (row >= slidesPerColumn) {
20921              row = 0;
20922              column += 1;
20923            }
20924          }
20925          newSlideOrderIndex = column + ((row * slidesNumberEvenToRows) / slidesPerColumn);
20926          slide
20927            .css({
20928              '-webkit-box-ordinal-group': newSlideOrderIndex,
20929              '-moz-box-ordinal-group': newSlideOrderIndex,
20930              '-ms-flex-order': newSlideOrderIndex,
20931              '-webkit-order': newSlideOrderIndex,
20932              order: newSlideOrderIndex,
20933            });
20934        } else {
20935          row = Math.floor(i / slidesPerRow);
20936          column = i - (row * slidesPerRow);
20937        }
20938        slide
20939          .css(
20940            ("margin-" + (swiper.isHorizontal() ? 'top' : 'left')),
20941            (row !== 0 && params.spaceBetween) && (((params.spaceBetween) + "px"))
20942          )
20943          .attr('data-swiper-column', column)
20944          .attr('data-swiper-row', row);
20945      }
20946      if (slide.css('display') === 'none') { continue; } // eslint-disable-line
20947
20948      if (params.slidesPerView === 'auto') {
20949        var slideStyles = win.getComputedStyle(slide[0], null);
20950        var currentTransform = slide[0].style.transform;
20951        var currentWebKitTransform = slide[0].style.webkitTransform;
20952        if (currentTransform) {
20953          slide[0].style.transform = 'none';
20954        }
20955        if (currentWebKitTransform) {
20956          slide[0].style.webkitTransform = 'none';
20957        }
20958        if (params.roundLengths) {
20959          slideSize = swiper.isHorizontal()
20960            ? slide.outerWidth(true)
20961            : slide.outerHeight(true);
20962        } else {
20963          // eslint-disable-next-line
20964          if (swiper.isHorizontal()) {
20965            var width = parseFloat(slideStyles.getPropertyValue('width'));
20966            var paddingLeft = parseFloat(slideStyles.getPropertyValue('padding-left'));
20967            var paddingRight = parseFloat(slideStyles.getPropertyValue('padding-right'));
20968            var marginLeft = parseFloat(slideStyles.getPropertyValue('margin-left'));
20969            var marginRight = parseFloat(slideStyles.getPropertyValue('margin-right'));
20970            var boxSizing = slideStyles.getPropertyValue('box-sizing');
20971            if (boxSizing && boxSizing === 'border-box') {
20972              slideSize = width + marginLeft + marginRight;
20973            } else {
20974              slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight;
20975            }
20976          } else {
20977            var height = parseFloat(slideStyles.getPropertyValue('height'));
20978            var paddingTop = parseFloat(slideStyles.getPropertyValue('padding-top'));
20979            var paddingBottom = parseFloat(slideStyles.getPropertyValue('padding-bottom'));
20980            var marginTop = parseFloat(slideStyles.getPropertyValue('margin-top'));
20981            var marginBottom = parseFloat(slideStyles.getPropertyValue('margin-bottom'));
20982            var boxSizing$1 = slideStyles.getPropertyValue('box-sizing');
20983            if (boxSizing$1 && boxSizing$1 === 'border-box') {
20984              slideSize = height + marginTop + marginBottom;
20985            } else {
20986              slideSize = height + paddingTop + paddingBottom + marginTop + marginBottom;
20987            }
20988          }
20989        }
20990        if (currentTransform) {
20991          slide[0].style.transform = currentTransform;
20992        }
20993        if (currentWebKitTransform) {
20994          slide[0].style.webkitTransform = currentWebKitTransform;
20995        }
20996        if (params.roundLengths) { slideSize = Math.floor(slideSize); }
20997      } else {
20998        slideSize = (swiperSize - ((params.slidesPerView - 1) * spaceBetween)) / params.slidesPerView;
20999        if (params.roundLengths) { slideSize = Math.floor(slideSize); }
21000
21001        if (slides[i]) {
21002          if (swiper.isHorizontal()) {
21003            slides[i].style.width = slideSize + "px";
21004          } else {
21005            slides[i].style.height = slideSize + "px";
21006          }
21007        }
21008      }
21009      if (slides[i]) {
21010        slides[i].swiperSlideSize = slideSize;
21011      }
21012      slidesSizesGrid.push(slideSize);
21013
21014
21015      if (params.centeredSlides) {
21016        slidePosition = slidePosition + (slideSize / 2) + (prevSlideSize / 2) + spaceBetween;
21017        if (prevSlideSize === 0 && i !== 0) { slidePosition = slidePosition - (swiperSize / 2) - spaceBetween; }
21018        if (i === 0) { slidePosition = slidePosition - (swiperSize / 2) - spaceBetween; }
21019        if (Math.abs(slidePosition) < 1 / 1000) { slidePosition = 0; }
21020        if (params.roundLengths) { slidePosition = Math.floor(slidePosition); }
21021        if ((index) % params.slidesPerGroup === 0) { snapGrid.push(slidePosition); }
21022        slidesGrid.push(slidePosition);
21023      } else {
21024        if (params.roundLengths) { slidePosition = Math.floor(slidePosition); }
21025        if ((index) % params.slidesPerGroup === 0) { snapGrid.push(slidePosition); }
21026        slidesGrid.push(slidePosition);
21027        slidePosition = slidePosition + slideSize + spaceBetween;
21028      }
21029
21030      swiper.virtualSize += slideSize + spaceBetween;
21031
21032      prevSlideSize = slideSize;
21033
21034      index += 1;
21035    }
21036    swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;
21037    var newSlidesGrid;
21038
21039    if (
21040      rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {
21041      $wrapperEl.css({ width: ((swiper.virtualSize + params.spaceBetween) + "px") });
21042    }
21043    if (!Support.flexbox || params.setWrapperSize) {
21044      if (swiper.isHorizontal()) { $wrapperEl.css({ width: ((swiper.virtualSize + params.spaceBetween) + "px") }); }
21045      else { $wrapperEl.css({ height: ((swiper.virtualSize + params.spaceBetween) + "px") }); }
21046    }
21047
21048    if (params.slidesPerColumn > 1) {
21049      swiper.virtualSize = (slideSize + params.spaceBetween) * slidesNumberEvenToRows;
21050      swiper.virtualSize = Math.ceil(swiper.virtualSize / params.slidesPerColumn) - params.spaceBetween;
21051      if (swiper.isHorizontal()) { $wrapperEl.css({ width: ((swiper.virtualSize + params.spaceBetween) + "px") }); }
21052      else { $wrapperEl.css({ height: ((swiper.virtualSize + params.spaceBetween) + "px") }); }
21053      if (params.centeredSlides) {
21054        newSlidesGrid = [];
21055        for (var i$1 = 0; i$1 < snapGrid.length; i$1 += 1) {
21056          var slidesGridItem = snapGrid[i$1];
21057          if (params.roundLengths) { slidesGridItem = Math.floor(slidesGridItem); }
21058          if (snapGrid[i$1] < swiper.virtualSize + snapGrid[0]) { newSlidesGrid.push(slidesGridItem); }
21059        }
21060        snapGrid = newSlidesGrid;
21061      }
21062    }
21063
21064    // Remove last grid elements depending on width
21065    if (!params.centeredSlides) {
21066      newSlidesGrid = [];
21067      for (var i$2 = 0; i$2 < snapGrid.length; i$2 += 1) {
21068        var slidesGridItem$1 = snapGrid[i$2];
21069        if (params.roundLengths) { slidesGridItem$1 = Math.floor(slidesGridItem$1); }
21070        if (snapGrid[i$2] <= swiper.virtualSize - swiperSize) {
21071          newSlidesGrid.push(slidesGridItem$1);
21072        }
21073      }
21074      snapGrid = newSlidesGrid;
21075      if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
21076        snapGrid.push(swiper.virtualSize - swiperSize);
21077      }
21078    }
21079    if (snapGrid.length === 0) { snapGrid = [0]; }
21080
21081    if (params.spaceBetween !== 0) {
21082      if (swiper.isHorizontal()) {
21083        if (rtl) { slides.css({ marginLeft: (spaceBetween + "px") }); }
21084        else { slides.css({ marginRight: (spaceBetween + "px") }); }
21085      } else { slides.css({ marginBottom: (spaceBetween + "px") }); }
21086    }
21087
21088    if (params.centerInsufficientSlides) {
21089      var allSlidesSize = 0;
21090      slidesSizesGrid.forEach(function (slideSizeValue) {
21091        allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);
21092      });
21093      allSlidesSize -= params.spaceBetween;
21094      if (allSlidesSize < swiperSize) {
21095        var allSlidesOffset = (swiperSize - allSlidesSize) / 2;
21096        snapGrid.forEach(function (snap, snapIndex) {
21097          snapGrid[snapIndex] = snap - allSlidesOffset;
21098        });
21099        slidesGrid.forEach(function (snap, snapIndex) {
21100          slidesGrid[snapIndex] = snap + allSlidesOffset;
21101        });
21102      }
21103    }
21104
21105    Utils.extend(swiper, {
21106      slides: slides,
21107      snapGrid: snapGrid,
21108      slidesGrid: slidesGrid,
21109      slidesSizesGrid: slidesSizesGrid,
21110    });
21111
21112    if (slidesLength !== previousSlidesLength) {
21113      swiper.emit('slidesLengthChange');
21114    }
21115    if (snapGrid.length !== previousSnapGridLength) {
21116      if (swiper.params.watchOverflow) { swiper.checkOverflow(); }
21117      swiper.emit('snapGridLengthChange');
21118    }
21119    if (slidesGrid.length !== previousSlidesGridLength) {
21120      swiper.emit('slidesGridLengthChange');
21121    }
21122
21123    if (params.watchSlidesProgress || params.watchSlidesVisibility) {
21124      swiper.updateSlidesOffset();
21125    }
21126  }
21127
21128  function updateAutoHeight (speed) {
21129    var swiper = this;
21130    var activeSlides = [];
21131    var newHeight = 0;
21132    var i;
21133    if (typeof speed === 'number') {
21134      swiper.setTransition(speed);
21135    } else if (speed === true) {
21136      swiper.setTransition(swiper.params.speed);
21137    }
21138    // Find slides currently in view
21139    if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {
21140      for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
21141        var index = swiper.activeIndex + i;
21142        if (index > swiper.slides.length) { break; }
21143        activeSlides.push(swiper.slides.eq(index)[0]);
21144      }
21145    } else {
21146      activeSlides.push(swiper.slides.eq(swiper.activeIndex)[0]);
21147    }
21148
21149    // Find new height from highest slide in view
21150    for (i = 0; i < activeSlides.length; i += 1) {
21151      if (typeof activeSlides[i] !== 'undefined') {
21152        var height = activeSlides[i].offsetHeight;
21153        newHeight = height > newHeight ? height : newHeight;
21154      }
21155    }
21156
21157    // Update Height
21158    if (newHeight) { swiper.$wrapperEl.css('height', (newHeight + "px")); }
21159  }
21160
21161  function updateSlidesOffset () {
21162    var swiper = this;
21163    var slides = swiper.slides;
21164    for (var i = 0; i < slides.length; i += 1) {
21165      slides[i].swiperSlideOffset = swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop;
21166    }
21167  }
21168
21169  function updateSlidesProgress (translate) {
21170    if ( translate === void 0 ) translate = (this && this.translate) || 0;
21171
21172    var swiper = this;
21173    var params = swiper.params;
21174
21175    var slides = swiper.slides;
21176    var rtl = swiper.rtlTranslate;
21177
21178    if (slides.length === 0) { return; }
21179    if (typeof slides[0].swiperSlideOffset === 'undefined') { swiper.updateSlidesOffset(); }
21180
21181    var offsetCenter = -translate;
21182    if (rtl) { offsetCenter = translate; }
21183
21184    // Visible Slides
21185    slides.removeClass(params.slideVisibleClass);
21186
21187    swiper.visibleSlidesIndexes = [];
21188    swiper.visibleSlides = [];
21189
21190    for (var i = 0; i < slides.length; i += 1) {
21191      var slide = slides[i];
21192      var slideProgress = (
21193        (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0)) - slide.swiperSlideOffset
21194      ) / (slide.swiperSlideSize + params.spaceBetween);
21195      if (params.watchSlidesVisibility) {
21196        var slideBefore = -(offsetCenter - slide.swiperSlideOffset);
21197        var slideAfter = slideBefore + swiper.slidesSizesGrid[i];
21198        var isVisible = (slideBefore >= 0 && slideBefore < swiper.size)
21199                  || (slideAfter > 0 && slideAfter <= swiper.size)
21200                  || (slideBefore <= 0 && slideAfter >= swiper.size);
21201        if (isVisible) {
21202          swiper.visibleSlides.push(slide);
21203          swiper.visibleSlidesIndexes.push(i);
21204          slides.eq(i).addClass(params.slideVisibleClass);
21205        }
21206      }
21207      slide.progress = rtl ? -slideProgress : slideProgress;
21208    }
21209    swiper.visibleSlides = $(swiper.visibleSlides);
21210  }
21211
21212  function updateProgress (translate) {
21213    if ( translate === void 0 ) translate = (this && this.translate) || 0;
21214
21215    var swiper = this;
21216    var params = swiper.params;
vendor: 6,283 bytes, lines 21216-21379
21216
21217
21218    var translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
21219    var progress = swiper.progress;
21220    var isBeginning = swiper.isBeginning;
21221    var isEnd = swiper.isEnd;
21222    var wasBeginning = isBeginning;
21223    var wasEnd = isEnd;
21224    if (translatesDiff === 0) {
21225      progress = 0;
21226      isBeginning = true;
21227      isEnd = true;
21228    } else {
21229      progress = (translate - swiper.minTranslate()) / (translatesDiff);
21230      isBeginning = progress <= 0;
21231      isEnd = progress >= 1;
21232    }
21233    Utils.extend(swiper, {
21234      progress: progress,
21235      isBeginning: isBeginning,
21236      isEnd: isEnd,
21237    });
21238
21239    if (params.watchSlidesProgress || params.watchSlidesVisibility) { swiper.updateSlidesProgress(translate); }
21240
21241    if (isBeginning && !wasBeginning) {
21242      swiper.emit('reachBeginning toEdge');
21243    }
21244    if (isEnd && !wasEnd) {
21245      swiper.emit('reachEnd toEdge');
21246    }
21247    if ((wasBeginning && !isBeginning) || (wasEnd && !isEnd)) {
21248      swiper.emit('fromEdge');
21249    }
21250
21251    swiper.emit('progress', progress);
21252  }
21253
21254  function updateSlidesClasses () {
21255    var swiper = this;
21256
21257    var slides = swiper.slides;
21258    var params = swiper.params;
21259    var $wrapperEl = swiper.$wrapperEl;
21260    var activeIndex = swiper.activeIndex;
21261    var realIndex = swiper.realIndex;
21262    var isVirtual = swiper.virtual && params.virtual.enabled;
21263
21264    slides.removeClass(((params.slideActiveClass) + " " + (params.slideNextClass) + " " + (params.slidePrevClass) + " " + (params.slideDuplicateActiveClass) + " " + (params.slideDuplicateNextClass) + " " + (params.slideDuplicatePrevClass)));
21265
21266    var activeSlide;
21267    if (isVirtual) {
21268      activeSlide = swiper.$wrapperEl.find(("." + (params.slideClass) + "[data-swiper-slide-index=\"" + activeIndex + "\"]"));
21269    } else {
21270      activeSlide = slides.eq(activeIndex);
21271    }
21272
21273    // Active classes
21274    activeSlide.addClass(params.slideActiveClass);
21275
21276    if (params.loop) {
21277      // Duplicate to all looped slides
21278      if (activeSlide.hasClass(params.slideDuplicateClass)) {
21279        $wrapperEl
21280          .children(("." + (params.slideClass) + ":not(." + (params.slideDuplicateClass) + ")[data-swiper-slide-index=\"" + realIndex + "\"]"))
21281          .addClass(params.slideDuplicateActiveClass);
21282      } else {
21283        $wrapperEl
21284          .children(("." + (params.slideClass) + "." + (params.slideDuplicateClass) + "[data-swiper-slide-index=\"" + realIndex + "\"]"))
21285          .addClass(params.slideDuplicateActiveClass);
21286      }
21287    }
21288    // Next Slide
21289    var nextSlide = activeSlide.nextAll(("." + (params.slideClass))).eq(0).addClass(params.slideNextClass);
21290    if (params.loop && nextSlide.length === 0) {
21291      nextSlide = slides.eq(0);
21292      nextSlide.addClass(params.slideNextClass);
21293    }
21294    // Prev Slide
21295    var prevSlide = activeSlide.prevAll(("." + (params.slideClass))).eq(0).addClass(params.slidePrevClass);
21296    if (params.loop && prevSlide.length === 0) {
21297      prevSlide = slides.eq(-1);
21298      prevSlide.addClass(params.slidePrevClass);
21299    }
21300    if (params.loop) {
21301      // Duplicate to all looped slides
21302      if (nextSlide.hasClass(params.slideDuplicateClass)) {
21303        $wrapperEl
21304          .children(("." + (params.slideClass) + ":not(." + (params.slideDuplicateClass) + ")[data-swiper-slide-index=\"" + (nextSlide.attr('data-swiper-slide-index')) + "\"]"))
21305          .addClass(params.slideDuplicateNextClass);
21306      } else {
21307        $wrapperEl
21308          .children(("." + (params.slideClass) + "." + (params.slideDuplicateClass) + "[data-swiper-slide-index=\"" + (nextSlide.attr('data-swiper-slide-index')) + "\"]"))
21309          .addClass(params.slideDuplicateNextClass);
21310      }
21311      if (prevSlide.hasClass(params.slideDuplicateClass)) {
21312        $wrapperEl
21313          .children(("." + (params.slideClass) + ":not(." + (params.slideDuplicateClass) + ")[data-swiper-slide-index=\"" + (prevSlide.attr('data-swiper-slide-index')) + "\"]"))
21314          .addClass(params.slideDuplicatePrevClass);
21315      } else {
21316        $wrapperEl
21317          .children(("." + (params.slideClass) + "." + (params.slideDuplicateClass) + "[data-swiper-slide-index=\"" + (prevSlide.attr('data-swiper-slide-index')) + "\"]"))
21318          .addClass(params.slideDuplicatePrevClass);
21319      }
21320    }
21321  }
21322
21323  function updateActiveIndex (newActiveIndex) {
21324    var swiper = this;
21325    var translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
21326    var slidesGrid = swiper.slidesGrid;
21327    var snapGrid = swiper.snapGrid;
21328    var params = swiper.params;
21329    var previousIndex = swiper.activeIndex;
21330    var previousRealIndex = swiper.realIndex;
21331    var previousSnapIndex = swiper.snapIndex;
21332    var activeIndex = newActiveIndex;
21333    var snapIndex;
21334    if (typeof activeIndex === 'undefined') {
21335      for (var i = 0; i < slidesGrid.length; i += 1) {
21336        if (typeof slidesGrid[i + 1] !== 'undefined') {
21337          if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1] - ((slidesGrid[i + 1] - slidesGrid[i]) / 2)) {
21338            activeIndex = i;
21339          } else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) {
21340            activeIndex = i + 1;
21341          }
21342        } else if (translate >= slidesGrid[i]) {
21343          activeIndex = i;
21344        }
21345      }
21346      // Normalize slideIndex
21347      if (params.normalizeSlideIndex) {
21348        if (activeIndex < 0 || typeof activeIndex === 'undefined') { activeIndex = 0; }
21349      }
21350    }
21351    if (snapGrid.indexOf(translate) >= 0) {
21352      snapIndex = snapGrid.indexOf(translate);
21353    } else {
21354      snapIndex = Math.floor(activeIndex / params.slidesPerGroup);
21355    }
21356    if (snapIndex >= snapGrid.length) { snapIndex = snapGrid.length - 1; }
21357    if (activeIndex === previousIndex) {
21358      if (snapIndex !== previousSnapIndex) {
21359        swiper.snapIndex = snapIndex;
21360        swiper.emit('snapIndexChange');
21361      }
21362      return;
21363    }
21364
21365    // Get real index
21366    var realIndex = parseInt(swiper.slides.eq(activeIndex).attr('data-swiper-slide-index') || activeIndex, 10);
21367
21368    Utils.extend(swiper, {
21369      snapIndex: snapIndex,
21370      realIndex: realIndex,
21371      previousIndex: previousIndex,
21372      activeIndex: activeIndex,
21373    });
21374    swiper.emit('activeIndexChange');
21375    swiper.emit('snapIndexChange');
21376    if (previousRealIndex !== realIndex) {
21377      swiper.emit('realIndexChange');
21378    }
21379    
21379swiper.emit('slideChange');
vendor: 29,880 bytes, lines 21379-22301
21379
21380  }
21381
21382  function updateClickedSlide (e) {
21383    var swiper = this;
21384    var params = swiper.params;
21385    var slide = $(e.target).closest(("." + (params.slideClass)))[0];
21386    var slideFound = false;
21387    if (slide) {
21388      for (var i = 0; i < swiper.slides.length; i += 1) {
21389        if (swiper.slides[i] === slide) { slideFound = true; }
21390      }
21391    }
21392
21393    if (slide && slideFound) {
21394      swiper.clickedSlide = slide;
21395      if (swiper.virtual && swiper.params.virtual.enabled) {
21396        swiper.clickedIndex = parseInt($(slide).attr('data-swiper-slide-index'), 10);
21397      } else {
21398        swiper.clickedIndex = $(slide).index();
21399      }
21400    } else {
21401      swiper.clickedSlide = undefined;
21402      swiper.clickedIndex = undefined;
21403      return;
21404    }
21405    if (params.slideToClickedSlide && swiper.clickedIndex !== undefined && swiper.clickedIndex !== swiper.activeIndex) {
21406      swiper.slideToClickedSlide();
21407    }
21408  }
21409
21410  var update = {
21411    updateSize: updateSize,
21412    updateSlides: updateSlides,
21413    updateAutoHeight: updateAutoHeight,
21414    updateSlidesOffset: updateSlidesOffset,
21415    updateSlidesProgress: updateSlidesProgress,
21416    updateProgress: updateProgress,
21417    updateSlidesClasses: updateSlidesClasses,
21418    updateActiveIndex: updateActiveIndex,
21419    updateClickedSlide: updateClickedSlide,
21420  };
21421
21422  function getTranslate (axis) {
21423    if ( axis === void 0 ) axis = this.isHorizontal() ? 'x' : 'y';
21424
21425    var swiper = this;
21426
21427    var params = swiper.params;
21428    var rtl = swiper.rtlTranslate;
21429    var translate = swiper.translate;
21430    var $wrapperEl = swiper.$wrapperEl;
21431
21432    if (params.virtualTranslate) {
21433      return rtl ? -translate : translate;
21434    }
21435
21436    var currentTranslate = Utils.getTranslate($wrapperEl[0], axis);
21437    if (rtl) { currentTranslate = -currentTranslate; }
21438
21439    return currentTranslate || 0;
21440  }
21441
21442  function setTranslate (translate, byController) {
21443    var swiper = this;
21444    var rtl = swiper.rtlTranslate;
21445    var params = swiper.params;
21446    var $wrapperEl = swiper.$wrapperEl;
21447    var progress = swiper.progress;
21448    var x = 0;
21449    var y = 0;
21450    var z = 0;
21451
21452    if (swiper.isHorizontal()) {
21453      x = rtl ? -translate : translate;
21454    } else {
21455      y = translate;
21456    }
21457
21458    if (params.roundLengths) {
21459      x = Math.floor(x);
21460      y = Math.floor(y);
21461    }
21462
21463    if (!params.virtualTranslate) {
21464      if (Support.transforms3d) { $wrapperEl.transform(("translate3d(" + x + "px, " + y + "px, " + z + "px)")); }
21465      else { $wrapperEl.transform(("translate(" + x + "px, " + y + "px)")); }
21466    }
21467    swiper.previousTranslate = swiper.translate;
21468    swiper.translate = swiper.isHorizontal() ? x : y;
21469
21470    // Check if we need to update progress
21471    var newProgress;
21472    var translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
21473    if (translatesDiff === 0) {
21474      newProgress = 0;
21475    } else {
21476      newProgress = (translate - swiper.minTranslate()) / (translatesDiff);
21477    }
21478    if (newProgress !== progress) {
21479      swiper.updateProgress(translate);
21480    }
21481
21482    swiper.emit('setTranslate', swiper.translate, byController);
21483  }
21484
21485  function minTranslate () {
21486    return (-this.snapGrid[0]);
21487  }
21488
21489  function maxTranslate () {
21490    return (-this.snapGrid[this.snapGrid.length - 1]);
21491  }
21492
21493  var translate = {
21494    getTranslate: getTranslate,
21495    setTranslate: setTranslate,
21496    minTranslate: minTranslate,
21497    maxTranslate: maxTranslate,
21498  };
21499
21500  function setTransition (duration, byController) {
21501    var swiper = this;
21502
21503    swiper.$wrapperEl.transition(duration);
21504
21505    swiper.emit('setTransition', duration, byController);
21506  }
21507
21508  function transitionStart (runCallbacks, direction) {
21509    if ( runCallbacks === void 0 ) runCallbacks = true;
21510
21511    var swiper = this;
21512    var activeIndex = swiper.activeIndex;
21513    var params = swiper.params;
21514    var previousIndex = swiper.previousIndex;
21515    if (params.autoHeight) {
21516      swiper.updateAutoHeight();
21517    }
21518
21519    var dir = direction;
21520    if (!dir) {
21521      if (activeIndex > previousIndex) { dir = 'next'; }
21522      else if (activeIndex < previousIndex) { dir = 'prev'; }
21523      else { dir = 'reset'; }
21524    }
21525
21526    swiper.emit('transitionStart');
21527
21528    if (runCallbacks && activeIndex !== previousIndex) {
21529      if (dir === 'reset') {
21530        swiper.emit('slideResetTransitionStart');
21531        return;
21532      }
21533      swiper.emit('slideChangeTransitionStart');
21534      if (dir === 'next') {
21535        swiper.emit('slideNextTransitionStart');
21536      } else {
21537        swiper.emit('slidePrevTransitionStart');
21538      }
21539    }
21540  }
21541
21542  function transitionEnd$1 (runCallbacks, direction) {
21543    if ( runCallbacks === void 0 ) runCallbacks = true;
21544
21545    var swiper = this;
21546    var activeIndex = swiper.activeIndex;
21547    var previousIndex = swiper.previousIndex;
21548    swiper.animating = false;
21549    swiper.setTransition(0);
21550
21551    var dir = direction;
21552    if (!dir) {
21553      if (activeIndex > previousIndex) { dir = 'next'; }
21554      else if (activeIndex < previousIndex) { dir = 'prev'; }
21555      else { dir = 'reset'; }
21556    }
21557
21558    swiper.emit('transitionEnd');
21559
21560    if (runCallbacks && activeIndex !== previousIndex) {
21561      if (dir === 'reset') {
21562        swiper.emit('slideResetTransitionEnd');
21563        return;
21564      }
21565      swiper.emit('slideChangeTransitionEnd');
21566      if (dir === 'next') {
21567        swiper.emit('slideNextTransitionEnd');
21568      } else {
21569        swiper.emit('slidePrevTransitionEnd');
21570      }
21571    }
21572  }
21573
21574  var transition$1 = {
21575    setTransition: setTransition,
21576    transitionStart: transitionStart,
21577    transitionEnd: transitionEnd$1,
21578  };
21579
21580  function slideTo (index, speed, runCallbacks, internal) {
21581    if ( index === void 0 ) index = 0;
21582    if ( speed === void 0 ) speed = this.params.speed;
21583    if ( runCallbacks === void 0 ) runCallbacks = true;
21584
21585    var swiper = this;
21586    var slideIndex = index;
21587    if (slideIndex < 0) { slideIndex = 0; }
21588
21589    var params = swiper.params;
21590    var snapGrid = swiper.snapGrid;
21591    var slidesGrid = swiper.slidesGrid;
21592    var previousIndex = swiper.previousIndex;
21593    var activeIndex = swiper.activeIndex;
21594    var rtl = swiper.rtlTranslate;
21595    if (swiper.animating && params.preventInteractionOnTransition) {
21596      return false;
21597    }
21598
21599    var snapIndex = Math.floor(slideIndex / params.slidesPerGroup);
21600    if (snapIndex >= snapGrid.length) { snapIndex = snapGrid.length - 1; }
21601
21602    if ((activeIndex || params.initialSlide || 0) === (previousIndex || 0) && runCallbacks) {
21603      swiper.emit('beforeSlideChangeStart');
21604    }
21605
21606    var translate = -snapGrid[snapIndex];
21607
21608    // Update progress
21609    swiper.updateProgress(translate);
21610
21611    // Normalize slideIndex
21612    if (params.normalizeSlideIndex) {
21613      for (var i = 0; i < slidesGrid.length; i += 1) {
21614        if (-Math.floor(translate * 100) >= Math.floor(slidesGrid[i] * 100)) {
21615          slideIndex = i;
21616        }
21617      }
21618    }
21619    // Directions locks
21620    if (swiper.initialized && slideIndex !== activeIndex) {
21621      if (!swiper.allowSlideNext && translate < swiper.translate && translate < swiper.minTranslate()) {
21622        return false;
21623      }
21624      if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {
21625        if ((activeIndex || 0) !== slideIndex) { return false; }
21626      }
21627    }
21628
21629    var direction;
21630    if (slideIndex > activeIndex) { direction = 'next'; }
21631    else if (slideIndex < activeIndex) { direction = 'prev'; }
21632    else { direction = 'reset'; }
21633
21634
21635    // Update Index
21636    if ((rtl && -translate === swiper.translate) || (!rtl && translate === swiper.translate)) {
21637      swiper.updateActiveIndex(slideIndex);
21638      // Update Height
21639      if (params.autoHeight) {
21640        swiper.updateAutoHeight();
21641      }
21642      swiper.updateSlidesClasses();
21643      if (params.effect !== 'slide') {
21644        swiper.setTranslate(translate);
21645      }
21646      if (direction !== 'reset') {
21647        swiper.transitionStart(runCallbacks, direction);
21648        swiper.transitionEnd(runCallbacks, direction);
21649      }
21650      return false;
21651    }
21652
21653    if (speed === 0 || !Support.transition) {
21654      swiper.setTransition(0);
21655      swiper.setTranslate(translate);
21656      swiper.updateActiveIndex(slideIndex);
21657      swiper.updateSlidesClasses();
21658      swiper.emit('beforeTransitionStart', speed, internal);
21659      swiper.transitionStart(runCallbacks, direction);
21660      swiper.transitionEnd(runCallbacks, direction);
21661    } else {
21662      swiper.setTransition(speed);
21663      swiper.setTranslate(translate);
21664      swiper.updateActiveIndex(slideIndex);
21665      swiper.updateSlidesClasses();
21666      swiper.emit('beforeTransitionStart', speed, internal);
21667      swiper.transitionStart(runCallbacks, direction);
21668      if (!swiper.animating) {
21669        swiper.animating = true;
21670        if (!swiper.onSlideToWrapperTransitionEnd) {
21671          swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) {
21672            if (!swiper || swiper.destroyed) { return; }
21673            if (e.target !== this) { return; }
21674            swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
21675            swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);
21676            swiper.onSlideToWrapperTransitionEnd = null;
21677            delete swiper.onSlideToWrapperTransitionEnd;
21678            swiper.transitionEnd(runCallbacks, direction);
21679          };
21680        }
21681        swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
21682        swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);
21683      }
21684    }
21685
21686    return true;
21687  }
21688
21689  function slideToLoop (index, speed, runCallbacks, internal) {
21690    if ( index === void 0 ) index = 0;
21691    if ( speed === void 0 ) speed = this.params.speed;
21692    if ( runCallbacks === void 0 ) runCallbacks = true;
21693
21694    var swiper = this;
21695    var newIndex = index;
21696    if (swiper.params.loop) {
21697      newIndex += swiper.loopedSlides;
21698    }
21699
21700    return swiper.slideTo(newIndex, speed, runCallbacks, internal);
21701  }
21702
21703  /* eslint no-unused-vars: "off" */
21704  function slideNext (speed, runCallbacks, internal) {
21705    if ( speed === void 0 ) speed = this.params.speed;
21706    if ( runCallbacks === void 0 ) runCallbacks = true;
21707
21708    var swiper = this;
21709    var params = swiper.params;
21710    var animating = swiper.animating;
21711    if (params.loop) {
21712      if (animating) { return false; }
21713      swiper.loopFix();
21714      // eslint-disable-next-line
21715      swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
21716      return swiper.slideTo(swiper.activeIndex + params.slidesPerGroup, speed, runCallbacks, internal);
21717    }
21718    return swiper.slideTo(swiper.activeIndex + params.slidesPerGroup, speed, runCallbacks, internal);
21719  }
21720
21721  /* eslint no-unused-vars: "off" */
21722  function slidePrev (speed, runCallbacks, internal) {
21723    if ( speed === void 0 ) speed = this.params.speed;
21724    if ( runCallbacks === void 0 ) runCallbacks = true;
21725
21726    var swiper = this;
21727    var params = swiper.params;
21728    var animating = swiper.animating;
21729    var snapGrid = swiper.snapGrid;
21730    var slidesGrid = swiper.slidesGrid;
21731    var rtlTranslate = swiper.rtlTranslate;
21732
21733    if (params.loop) {
21734      if (animating) { return false; }
21735      swiper.loopFix();
21736      // eslint-disable-next-line
21737      swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
21738    }
21739    var translate = rtlTranslate ? swiper.translate : -swiper.translate;
21740    function normalize(val) {
21741      if (val < 0) { return -Math.floor(Math.abs(val)); }
21742      return Math.floor(val);
21743    }
21744    var normalizedTranslate = normalize(translate);
21745    var normalizedSnapGrid = snapGrid.map(function (val) { return normalize(val); });
21746    var normalizedSlidesGrid = slidesGrid.map(function (val) { return normalize(val); });
21747
21748    var currentSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate)];
21749    var prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];
21750    var prevIndex;
21751    if (typeof prevSnap !== 'undefined') {
21752      prevIndex = slidesGrid.indexOf(prevSnap);
21753      if (prevIndex < 0) { prevIndex = swiper.activeIndex - 1; }
21754    }
21755    return swiper.slideTo(prevIndex, speed, runCallbacks, internal);
21756  }
21757
21758  /* eslint no-unused-vars: "off" */
21759  function slideReset (speed, runCallbacks, internal) {
21760    if ( speed === void 0 ) speed = this.params.speed;
21761    if ( runCallbacks === void 0 ) runCallbacks = true;
21762
21763    var swiper = this;
21764    return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
21765  }
21766
21767  /* eslint no-unused-vars: "off" */
21768  function slideToClosest (speed, runCallbacks, internal) {
21769    if ( speed === void 0 ) speed = this.params.speed;
21770    if ( runCallbacks === void 0 ) runCallbacks = true;
21771
21772    var swiper = this;
21773    var index = swiper.activeIndex;
21774    var snapIndex = Math.floor(index / swiper.params.slidesPerGroup);
21775
21776    if (snapIndex < swiper.snapGrid.length - 1) {
21777      var translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
21778
21779      var currentSnap = swiper.snapGrid[snapIndex];
21780      var nextSnap = swiper.snapGrid[snapIndex + 1];
21781
21782      if ((translate - currentSnap) > (nextSnap - currentSnap) / 2) {
21783        index = swiper.params.slidesPerGroup;
21784      }
21785    }
21786
21787    return swiper.slideTo(index, speed, runCallbacks, internal);
21788  }
21789
21790  function slideToClickedSlide () {
21791    var swiper = this;
21792    var params = swiper.params;
21793    var $wrapperEl = swiper.$wrapperEl;
21794
21795    var slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;
21796    var slideToIndex = swiper.clickedIndex;
21797    var realIndex;
21798    if (params.loop) {
21799      if (swiper.animating) { return; }
21800      realIndex = parseInt($(swiper.clickedSlide).attr('data-swiper-slide-index'), 10);
21801      if (params.centeredSlides) {
21802        if (
21803          (slideToIndex < swiper.loopedSlides - (slidesPerView / 2))
21804          || (slideToIndex > (swiper.slides.length - swiper.loopedSlides) + (slidesPerView / 2))
21805        ) {
21806          swiper.loopFix();
21807          slideToIndex = $wrapperEl
21808            .children(("." + (params.slideClass) + "[data-swiper-slide-index=\"" + realIndex + "\"]:not(." + (params.slideDuplicateClass) + ")"))
21809            .eq(0)
21810            .index();
21811
21812          Utils.nextTick(function () {
21813            swiper.slideTo(slideToIndex);
21814          });
21815        } else {
21816          swiper.slideTo(slideToIndex);
21817        }
21818      } else if (slideToIndex > swiper.slides.length - slidesPerView) {
21819        swiper.loopFix();
21820        slideToIndex = $wrapperEl
21821          .children(("." + (params.slideClass) + "[data-swiper-slide-index=\"" + realIndex + "\"]:not(." + (params.slideDuplicateClass) + ")"))
21822          .eq(0)
21823          .index();
21824
21825        Utils.nextTick(function () {
21826          swiper.slideTo(slideToIndex);
21827        });
21828      } else {
21829        swiper.slideTo(slideToIndex);
21830      }
21831    } else {
21832      swiper.slideTo(slideToIndex);
21833    }
21834  }
21835
21836  var slide = {
21837    slideTo: slideTo,
21838    slideToLoop: slideToLoop,
21839    slideNext: slideNext,
21840    slidePrev: slidePrev,
21841    slideReset: slideReset,
21842    slideToClosest: slideToClosest,
21843    slideToClickedSlide: slideToClickedSlide,
21844  };
21845
21846  function loopCreate () {
21847    var swiper = this;
21848    var params = swiper.params;
21849    var $wrapperEl = swiper.$wrapperEl;
21850    // Remove duplicated slides
21851    $wrapperEl.children(("." + (params.slideClass) + "." + (params.slideDuplicateClass))).remove();
21852
21853    var slides = $wrapperEl.children(("." + (params.slideClass)));
21854
21855    if (params.loopFillGroupWithBlank) {
21856      var blankSlidesNum = params.slidesPerGroup - (slides.length % params.slidesPerGroup);
21857      if (blankSlidesNum !== params.slidesPerGroup) {
21858        for (var i = 0; i < blankSlidesNum; i += 1) {
21859          var blankNode = $(doc.createElement('div')).addClass(((params.slideClass) + " " + (params.slideBlankClass)));
21860          $wrapperEl.append(blankNode);
21861        }
21862        slides = $wrapperEl.children(("." + (params.slideClass)));
21863      }
21864    }
21865
21866    if (params.slidesPerView === 'auto' && !params.loopedSlides) { params.loopedSlides = slides.length; }
21867
21868    swiper.loopedSlides = parseInt(params.loopedSlides || params.slidesPerView, 10);
21869    swiper.loopedSlides += params.loopAdditionalSlides;
21870    if (swiper.loopedSlides > slides.length) {
21871      swiper.loopedSlides = slides.length;
21872    }
21873
21874    var prependSlides = [];
21875    var appendSlides = [];
21876    slides.each(function (index, el) {
21877      var slide = $(el);
21878      if (index < swiper.loopedSlides) { appendSlides.push(el); }
21879      if (index < slides.length && index >= slides.length - swiper.loopedSlides) { prependSlides.push(el); }
21880      slide.attr('data-swiper-slide-index', index);
21881    });
21882    for (var i$1 = 0; i$1 < appendSlides.length; i$1 += 1) {
21883      $wrapperEl.append($(appendSlides[i$1].cloneNode(true)).addClass(params.slideDuplicateClass));
21884    }
21885    for (var i$2 = prependSlides.length - 1; i$2 >= 0; i$2 -= 1) {
21886      $wrapperEl.prepend($(prependSlides[i$2].cloneNode(true)).addClass(params.slideDuplicateClass));
21887    }
21888  }
21889
21890  function loopFix () {
21891    var swiper = this;
21892    var params = swiper.params;
21893    var activeIndex = swiper.activeIndex;
21894    var slides = swiper.slides;
21895    var loopedSlides = swiper.loopedSlides;
21896    var allowSlidePrev = swiper.allowSlidePrev;
21897    var allowSlideNext = swiper.allowSlideNext;
21898    var snapGrid = swiper.snapGrid;
21899    var rtl = swiper.rtlTranslate;
21900    var newIndex;
21901    swiper.allowSlidePrev = true;
21902    swiper.allowSlideNext = true;
21903
21904    var snapTranslate = -snapGrid[activeIndex];
21905    var diff = snapTranslate - swiper.getTranslate();
21906
21907
21908    // Fix For Negative Oversliding
21909    if (activeIndex < loopedSlides) {
21910      newIndex = (slides.length - (loopedSlides * 3)) + activeIndex;
21911      newIndex += loopedSlides;
21912      var slideChanged = swiper.slideTo(newIndex, 0, false, true);
21913      if (slideChanged && diff !== 0) {
21914        swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);
21915      }
21916    } else if ((params.slidesPerView === 'auto' && activeIndex >= loopedSlides * 2) || (activeIndex >= slides.length - loopedSlides)) {
21917      // Fix For Positive Oversliding
21918      newIndex = -slides.length + activeIndex + loopedSlides;
21919      newIndex += loopedSlides;
21920      var slideChanged$1 = swiper.slideTo(newIndex, 0, false, true);
21921      if (slideChanged$1 && diff !== 0) {
21922        swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);
21923      }
21924    }
21925    swiper.allowSlidePrev = allowSlidePrev;
21926    swiper.allowSlideNext = allowSlideNext;
21927  }
21928
21929  function loopDestroy () {
21930    var swiper = this;
21931    var $wrapperEl = swiper.$wrapperEl;
21932    var params = swiper.params;
21933    var slides = swiper.slides;
21934    $wrapperEl.children(("." + (params.slideClass) + "." + (params.slideDuplicateClass) + ",." + (params.slideClass) + "." + (params.slideBlankClass))).remove();
21935    slides.removeAttr('data-swiper-slide-index');
21936  }
21937
21938  var loop = {
21939    loopCreate: loopCreate,
21940    loopFix: loopFix,
21941    loopDestroy: loopDestroy,
21942  };
21943
21944  function setGrabCursor (moving) {
21945    var swiper = this;
21946    if (Support.touch || !swiper.params.simulateTouch || (swiper.params.watchOverflow && swiper.isLocked)) { return; }
21947    var el = swiper.el;
21948    el.style.cursor = 'move';
21949    el.style.cursor = moving ? '-webkit-grabbing' : '-webkit-grab';
21950    el.style.cursor = moving ? '-moz-grabbin' : '-moz-grab';
21951    el.style.cursor = moving ? 'grabbing' : 'grab';
21952  }
21953
21954  function unsetGrabCursor () {
21955    var swiper = this;
21956    if (Support.touch || (swiper.params.watchOverflow && swiper.isLocked)) { return; }
21957    swiper.el.style.cursor = '';
21958  }
21959
21960  var grabCursor = {
21961    setGrabCursor: setGrabCursor,
21962    unsetGrabCursor: unsetGrabCursor,
21963  };
21964
21965  function appendSlide (slides) {
21966    var swiper = this;
21967    var $wrapperEl = swiper.$wrapperEl;
21968    var params = swiper.params;
21969    if (params.loop) {
21970      swiper.loopDestroy();
21971    }
21972    if (typeof slides === 'object' && 'length' in slides) {
21973      for (var i = 0; i < slides.length; i += 1) {
21974        if (slides[i]) { $wrapperEl.append(slides[i]); }
21975      }
21976    } else {
21977      $wrapperEl.append(slides);
21978    }
21979    if (params.loop) {
21980      swiper.loopCreate();
21981    }
21982    if (!(params.observer && Support.observer)) {
21983      swiper.update();
21984    }
21985  }
21986
21987  function prependSlide (slides) {
21988    var swiper = this;
21989    var params = swiper.params;
21990    var $wrapperEl = swiper.$wrapperEl;
21991    var activeIndex = swiper.activeIndex;
21992
21993    if (params.loop) {
21994      swiper.loopDestroy();
21995    }
21996    var newActiveIndex = activeIndex + 1;
21997    if (typeof slides === 'object' && 'length' in slides) {
21998      for (var i = 0; i < slides.length; i += 1) {
21999        if (slides[i]) { $wrapperEl.prepend(slides[i]); }
22000      }
22001      newActiveIndex = activeIndex + slides.length;
22002    } else {
22003      $wrapperEl.prepend(slides);
22004    }
22005    if (params.loop) {
22006      swiper.loopCreate();
22007    }
22008    if (!(params.observer && Support.observer)) {
22009      swiper.update();
22010    }
22011    swiper.slideTo(newActiveIndex, 0, false);
22012  }
22013
22014  function addSlide (index, slides) {
22015    var swiper = this;
22016    var $wrapperEl = swiper.$wrapperEl;
22017    var params = swiper.params;
22018    var activeIndex = swiper.activeIndex;
22019    var activeIndexBuffer = activeIndex;
22020    if (params.loop) {
22021      activeIndexBuffer -= swiper.loopedSlides;
22022      swiper.loopDestroy();
22023      swiper.slides = $wrapperEl.children(("." + (params.slideClass)));
22024    }
22025    var baseLength = swiper.slides.length;
22026    if (index <= 0) {
22027      swiper.prependSlide(slides);
22028      return;
22029    }
22030    if (index >= baseLength) {
22031      swiper.appendSlide(slides);
22032      return;
22033    }
22034    var newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer;
22035
22036    var slidesBuffer = [];
22037    for (var i = baseLength - 1; i >= index; i -= 1) {
22038      var currentSlide = swiper.slides.eq(i);
22039      currentSlide.remove();
22040      slidesBuffer.unshift(currentSlide);
22041    }
22042
22043    if (typeof slides === 'object' && 'length' in slides) {
22044      for (var i$1 = 0; i$1 < slides.length; i$1 += 1) {
22045        if (slides[i$1]) { $wrapperEl.append(slides[i$1]); }
22046      }
22047      newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer;
22048    } else {
22049      $wrapperEl.append(slides);
22050    }
22051
22052    for (var i$2 = 0; i$2 < slidesBuffer.length; i$2 += 1) {
22053      $wrapperEl.append(slidesBuffer[i$2]);
22054    }
22055
22056    if (params.loop) {
22057      swiper.loopCreate();
22058    }
22059    if (!(params.observer && Support.observer)) {
22060      swiper.update();
22061    }
22062    if (params.loop) {
22063      swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
22064    } else {
22065      swiper.slideTo(newActiveIndex, 0, false);
22066    }
22067  }
22068
22069  function removeSlide (slidesIndexes) {
22070    var swiper = this;
22071    var params = swiper.params;
22072    var $wrapperEl = swiper.$wrapperEl;
22073    var activeIndex = swiper.activeIndex;
22074
22075    var activeIndexBuffer = activeIndex;
22076    if (params.loop) {
22077      activeIndexBuffer -= swiper.loopedSlides;
22078      swiper.loopDestroy();
22079      swiper.slides = $wrapperEl.children(("." + (params.slideClass)));
22080    }
22081    var newActiveIndex = activeIndexBuffer;
22082    var indexToRemove;
22083
22084    if (typeof slidesIndexes === 'object' && 'length' in slidesIndexes) {
22085      for (var i = 0; i < slidesIndexes.length; i += 1) {
22086        indexToRemove = slidesIndexes[i];
22087        if (swiper.slides[indexToRemove]) { swiper.slides.eq(indexToRemove).remove(); }
22088        if (indexToRemove < newActiveIndex) { newActiveIndex -= 1; }
22089      }
22090      newActiveIndex = Math.max(newActiveIndex, 0);
22091    } else {
22092      indexToRemove = slidesIndexes;
22093      if (swiper.slides[indexToRemove]) { swiper.slides.eq(indexToRemove).remove(); }
22094      if (indexToRemove < newActiveIndex) { newActiveIndex -= 1; }
22095      newActiveIndex = Math.max(newActiveIndex, 0);
22096    }
22097
22098    if (params.loop) {
22099      swiper.loopCreate();
22100    }
22101
22102    if (!(params.observer && Support.observer)) {
22103      swiper.update();
22104    }
22105    if (params.loop) {
22106      swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
22107    } else {
22108      swiper.slideTo(newActiveIndex, 0, false);
22109    }
22110  }
22111
22112  function removeAllSlides () {
22113    var swiper = this;
22114
22115    var slidesIndexes = [];
22116    for (var i = 0; i < swiper.slides.length; i += 1) {
22117      slidesIndexes.push(i);
22118    }
22119    swiper.removeSlide(slidesIndexes);
22120  }
22121
22122  var manipulation = {
22123    appendSlide: appendSlide,
22124    prependSlide: prependSlide,
22125    addSlide: addSlide,
22126    removeSlide: removeSlide,
22127    removeAllSlides: removeAllSlides,
22128  };
22129
22130  var Device = (function Device() {
22131    var ua = win.navigator.userAgent;
22132
22133    var device = {
22134      ios: false,
22135      android: false,
22136      androidChrome: false,
22137      desktop: false,
22138      windows: false,
22139      iphone: false,
22140      ipod: false,
22141      ipad: false,
22142      cordova: win.cordova || win.phonegap,
22143      phonegap: win.cordova || win.phonegap,
22144    };
22145
22146    var windows = ua.match(/(Windows Phone);?[\s\/]+([\d.]+)?/); // eslint-disable-line
22147    var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
22148    var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
22149    var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
22150    var iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);
22151
22152
22153    // Windows
22154    if (windows) {
22155      device.os = 'windows';
22156      device.osVersion = windows[2];
22157      device.windows = true;
22158    }
22159    // Android
22160    if (android && !windows) {
22161      device.os = 'android';
22162      device.osVersion = android[2];
22163      device.android = true;
22164      device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
22165    }
22166    if (ipad || iphone || ipod) {
22167      device.os = 'ios';
22168      device.ios = true;
22169    }
22170    // iOS
22171    if (iphone && !ipod) {
22172      device.osVersion = iphone[2].replace(/_/g, '.');
22173      device.iphone = true;
22174    }
22175    if (ipad) {
22176      device.osVersion = ipad[2].replace(/_/g, '.');
22177      device.ipad = true;
22178    }
22179    if (ipod) {
22180      device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
22181      device.iphone = true;
22182    }
22183    // iOS 8+ changed UA
22184    if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
22185      if (device.osVersion.split('.')[0] === '10') {
22186        device.osVersion = ua.toLowerCase().split('version/')[1].split(' ')[0];
22187      }
22188    }
22189
22190    // Desktop
22191    device.desktop = !(device.os || device.android || device.webView);
22192
22193    // Webview
22194    device.webView = (iphone || ipad || ipod) && ua.match(/.*AppleWebKit(?!.*Safari)/i);
22195
22196    // Minimal UI
22197    if (device.os && device.os === 'ios') {
22198      var osVersionArr = device.osVersion.split('.');
22199      var metaViewport = doc.querySelector('meta[name="viewport"]');
22200      device.minimalUi = !device.webView
22201        && (ipod || iphone)
22202        && (osVersionArr[0] * 1 === 7 ? osVersionArr[1] * 1 >= 1 : osVersionArr[0] * 1 > 7)
22203        && metaViewport && metaViewport.getAttribute('content').indexOf('minimal-ui') >= 0;
22204    }
22205
22206    // Pixel Ratio
22207    device.pixelRatio = win.devicePixelRatio || 1;
22208
22209    // Export object
22210    return device;
22211  }());
22212
22213  function onTouchStart (event) {
22214    var swiper = this;
22215    var data = swiper.touchEventsData;
22216    var params = swiper.params;
22217    var touches = swiper.touches;
22218    if (swiper.animating && params.preventInteractionOnTransition) {
22219      return;
22220    }
22221    var e = event;
22222    if (e.originalEvent) { e = e.originalEvent; }
22223    data.isTouchEvent = e.type === 'touchstart';
22224    if (!data.isTouchEvent && 'which' in e && e.which === 3) { return; }
22225    if (!data.isTouchEvent && 'button' in e && e.button > 0) { return; }
22226    if (data.isTouched && data.isMoved) { return; }
22227    if (params.noSwiping && $(e.target).closest(params.noSwipingSelector ? params.noSwipingSelector : ("." + (params.noSwipingClass)))[0]) {
22228      swiper.allowClick = true;
22229      return;
22230    }
22231    if (params.swipeHandler) {
22232      if (!$(e).closest(params.swipeHandler)[0]) { return; }
22233    }
22234
22235    touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
22236    touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
22237    var startX = touches.currentX;
22238    var startY = touches.currentY;
22239
22240    // Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore
22241
22242    var edgeSwipeDetection = params.edgeSwipeDetection || params.iOSEdgeSwipeDetection;
22243    var edgeSwipeThreshold = params.edgeSwipeThreshold || params.iOSEdgeSwipeThreshold;
22244    if (
22245      edgeSwipeDetection
22246      && ((startX <= edgeSwipeThreshold)
22247      || (startX >= win.screen.width - edgeSwipeThreshold))
22248    ) {
22249      return;
22250    }
22251
22252    Utils.extend(data, {
22253      isTouched: true,
22254      isMoved: false,
22255      allowTouchCallbacks: true,
22256      isScrolling: undefined,
22257      startMoving: undefined,
22258    });
22259
22260    touches.startX = startX;
22261    touches.startY = startY;
22262    data.touchStartTime = Utils.now();
22263    swiper.allowClick = true;
22264    swiper.updateSize();
22265    swiper.swipeDirection = undefined;
22266    if (params.threshold > 0) { data.allowThresholdMove = false; }
22267    if (e.type !== 'touchstart') {
22268      var preventDefault = true;
22269      if ($(e.target).is(data.formElements)) { preventDefault = false; }
22270      if (
22271        doc.activeElement
22272        && $(doc.activeElement).is(data.formElements)
22273        && doc.activeElement !== e.target
22274      ) {
22275        doc.activeElement.blur();
22276      }
22277
22278      var shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault;
22279      if (params.touchStartForcePreventDefault || shouldPreventDefault) {
22280        e.preventDefault();
22281      }
22282    }
22283    swiper.emit('touchStart', e);
22284  }
22285
22286  function onTouchMove (event) {
22287    var swiper = this;
22288    var data = swiper.touchEventsData;
22289    var params = swiper.params;
22290    var touches = swiper.touches;
22291    var rtl = swiper.rtlTranslate;
22292    var e = event;
22293    if (e.originalEvent) { e = e.originalEvent; }
22294    if (!data.isTouched) {
22295      if (data.startMoving && data.isScrolling) {
22296        swiper.emit('touchMoveOpposite', e);
22297      }
22298      return;
22299    }
22300    if (data.isTouchEvent && e.type === 'mousemove') { return; }
22301    var 
vendor: 2,929 bytes, lines 22301-22387
22301pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
22302    var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
22303    if (e.preventedByNestedSwiper) {
22304      touches.startX = pageX;
22305      touches.startY = pageY;
22306      return;
22307    }
22308    if (!swiper.allowTouchMove) {
22309      // isMoved = true;
22310      swiper.allowClick = false;
22311      if (data.isTouched) {
22312        Utils.extend(touches, {
22313          startX: pageX,
22314          startY: pageY,
22315          currentX: pageX,
22316          currentY: pageY,
22317        });
22318        data.touchStartTime = Utils.now();
22319      }
22320      return;
22321    }
22322    if (data.isTouchEvent && params.touchReleaseOnEdges && !params.loop) {
22323      if (swiper.isVertical()) {
22324        // Vertical
22325        if (
22326          (pageY < touches.startY && swiper.translate <= swiper.maxTranslate())
22327          || (pageY > touches.startY && swiper.translate >= swiper.minTranslate())
22328        ) {
22329          data.isTouched = false;
22330          data.isMoved = false;
22331          return;
22332        }
22333      } else if (
22334        (pageX < touches.startX && swiper.translate <= swiper.maxTranslate())
22335        || (pageX > touches.startX && swiper.translate >= swiper.minTranslate())
22336      ) {
22337        return;
22338      }
22339    }
22340    if (data.isTouchEvent && doc.activeElement) {
22341      if (e.target === doc.activeElement && $(e.target).is(data.formElements)) {
22342        data.isMoved = true;
22343        swiper.allowClick = false;
22344        return;
22345      }
22346    }
22347    if (data.allowTouchCallbacks) {
22348      swiper.emit('touchMove', e);
22349    }
22350    if (e.targetTouches && e.targetTouches.length > 1) { return; }
22351
22352    touches.currentX = pageX;
22353    touches.currentY = pageY;
22354
22355    var diffX = touches.currentX - touches.startX;
22356    var diffY = touches.currentY - touches.startY;
22357    if (swiper.params.threshold && Math.sqrt((Math.pow( diffX, 2 )) + (Math.pow( diffY, 2 ))) < swiper.params.threshold) { return; }
22358
22359    if (typeof data.isScrolling === 'undefined') {
22360      var touchAngle;
22361      if ((swiper.isHorizontal() && touches.currentY === touches.startY) || (swiper.isVertical() && touches.currentX === touches.startX)) {
22362        data.isScrolling = false;
22363      } else {
22364        // eslint-disable-next-line
22365        if ((diffX * diffX) + (diffY * diffY) >= 25) {
22366          touchAngle = (Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180) / Math.PI;
22367          data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : (90 - touchAngle > params.touchAngle);
22368        }
22369      }
22370    }
22371    if (data.isScrolling) {
22372      swiper.emit('touchMoveOpposite', e);
22373    }
22374    if (typeof data.startMoving === 'undefined') {
22375      if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) {
22376        data.startMoving = true;
22377      }
22378    }
22379    if (data.isScrolling) {
22380      data.isTouched = false;
22381      return;
22382    }
22383    if (!data.startMoving) {
22384      return;
22385    }
22386    swiper.allowClick = false;
22387    e.preventDefault();
vendor: 14,334 bytes, lines 22387-22802
22387
22388    if (params.touchMoveStopPropagation && !params.nested) {
22389      e.stopPropagation();
22390    }
22391
22392    if (!data.isMoved) {
22393      if (params.loop) {
22394        swiper.loopFix();
22395      }
22396      data.startTranslate = swiper.getTranslate();
22397      swiper.setTransition(0);
22398      if (swiper.animating) {
22399        swiper.$wrapperEl.trigger('webkitTransitionEnd transitionend');
22400      }
22401      data.allowMomentumBounce = false;
22402      // Grab Cursor
22403      if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
22404        swiper.setGrabCursor(true);
22405      }
22406      swiper.emit('sliderFirstMove', e);
22407    }
22408    swiper.emit('sliderMove', e);
22409    data.isMoved = true;
22410
22411    var diff = swiper.isHorizontal() ? diffX : diffY;
22412    touches.diff = diff;
22413
22414    diff *= params.touchRatio;
22415    if (rtl) { diff = -diff; }
22416
22417    swiper.swipeDirection = diff > 0 ? 'prev' : 'next';
22418    data.currentTranslate = diff + data.startTranslate;
22419
22420    var disableParentSwiper = true;
22421    var resistanceRatio = params.resistanceRatio;
22422    if (params.touchReleaseOnEdges) {
22423      resistanceRatio = 0;
22424    }
22425    if ((diff > 0 && data.currentTranslate > swiper.minTranslate())) {
22426      disableParentSwiper = false;
22427      if (params.resistance) { data.currentTranslate = (swiper.minTranslate() - 1) + (Math.pow( (-swiper.minTranslate() + data.startTranslate + diff), resistanceRatio )); }
22428    } else if (diff < 0 && data.currentTranslate < swiper.maxTranslate()) {
22429      disableParentSwiper = false;
22430      if (params.resistance) { data.currentTranslate = (swiper.maxTranslate() + 1) - (Math.pow( (swiper.maxTranslate() - data.startTranslate - diff), resistanceRatio )); }
22431    }
22432
22433    if (disableParentSwiper) {
22434      e.preventedByNestedSwiper = true;
22435    }
22436
22437    // Directions locks
22438    if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) {
22439      data.currentTranslate = data.startTranslate;
22440    }
22441    if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) {
22442      data.currentTranslate = data.startTranslate;
22443    }
22444
22445
22446    // Threshold
22447    if (params.threshold > 0) {
22448      if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {
22449        if (!data.allowThresholdMove) {
22450          data.allowThresholdMove = true;
22451          touches.startX = touches.currentX;
22452          touches.startY = touches.currentY;
22453          data.currentTranslate = data.startTranslate;
22454          touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches.startY;
22455          return;
22456        }
22457      } else {
22458        data.currentTranslate = data.startTranslate;
22459        return;
22460      }
22461    }
22462
22463    if (!params.followFinger) { return; }
22464
22465    // Update active index in free mode
22466    if (params.freeMode || params.watchSlidesProgress || params.watchSlidesVisibility) {
22467      swiper.updateActiveIndex();
22468      swiper.updateSlidesClasses();
22469    }
22470    if (params.freeMode) {
22471      // Velocity
22472      if (data.velocities.length === 0) {
22473        data.velocities.push({
22474          position: touches[swiper.isHorizontal() ? 'startX' : 'startY'],
22475          time: data.touchStartTime,
22476        });
22477      }
22478      data.velocities.push({
22479        position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'],
22480        time: Utils.now(),
22481      });
22482    }
22483    // Update progress
22484    swiper.updateProgress(data.currentTranslate);
22485    // Update translate
22486    swiper.setTranslate(data.currentTranslate);
22487  }
22488
22489  function onTouchEnd (event) {
22490    var swiper = this;
22491    var data = swiper.touchEventsData;
22492
22493    var params = swiper.params;
22494    var touches = swiper.touches;
22495    var rtl = swiper.rtlTranslate;
22496    var $wrapperEl = swiper.$wrapperEl;
22497    var slidesGrid = swiper.slidesGrid;
22498    var snapGrid = swiper.snapGrid;
22499    var e = event;
22500    if (e.originalEvent) { e = e.originalEvent; }
22501    if (data.allowTouchCallbacks) {
22502      swiper.emit('touchEnd', e);
22503    }
22504    data.allowTouchCallbacks = false;
22505    if (!data.isTouched) {
22506      if (data.isMoved && params.grabCursor) {
22507        swiper.setGrabCursor(false);
22508      }
22509      data.isMoved = false;
22510      data.startMoving = false;
22511      return;
22512    }
22513    // Return Grab Cursor
22514    if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
22515      swiper.setGrabCursor(false);
22516    }
22517
22518    // Time diff
22519    var touchEndTime = Utils.now();
22520    var timeDiff = touchEndTime - data.touchStartTime;
22521
22522    // Tap, doubleTap, Click
22523    if (swiper.allowClick) {
22524      swiper.updateClickedSlide(e);
22525      swiper.emit('tap', e);
22526      if (timeDiff < 300 && (touchEndTime - data.lastClickTime) > 300) {
22527        if (data.clickTimeout) { clearTimeout(data.clickTimeout); }
22528        data.clickTimeout = Utils.nextTick(function () {
22529          if (!swiper || swiper.destroyed) { return; }
22530          swiper.emit('click', e);
22531        }, 300);
22532      }
22533      if (timeDiff < 300 && (touchEndTime - data.lastClickTime) < 300) {
22534        if (data.clickTimeout) { clearTimeout(data.clickTimeout); }
22535        swiper.emit('doubleTap', e);
22536      }
22537    }
22538
22539    data.lastClickTime = Utils.now();
22540    Utils.nextTick(function () {
22541      if (!swiper.destroyed) { swiper.allowClick = true; }
22542    });
22543
22544    if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate === data.startTranslate) {
22545      data.isTouched = false;
22546      data.isMoved = false;
22547      data.startMoving = false;
22548      return;
22549    }
22550    data.isTouched = false;
22551    data.isMoved = false;
22552    data.startMoving = false;
22553
22554    var currentPos;
22555    if (params.followFinger) {
22556      currentPos = rtl ? swiper.translate : -swiper.translate;
22557    } else {
22558      currentPos = -data.currentTranslate;
22559    }
22560
22561    if (params.freeMode) {
22562      if (currentPos < -swiper.minTranslate()) {
22563        swiper.slideTo(swiper.activeIndex);
22564        return;
22565      }
22566      if (currentPos > -swiper.maxTranslate()) {
22567        if (swiper.slides.length < snapGrid.length) {
22568          swiper.slideTo(snapGrid.length - 1);
22569        } else {
22570          swiper.slideTo(swiper.slides.length - 1);
22571        }
22572        return;
22573      }
22574
22575      if (params.freeModeMomentum) {
22576        if (data.velocities.length > 1) {
22577          var lastMoveEvent = data.velocities.pop();
22578          var velocityEvent = data.velocities.pop();
22579
22580          var distance = lastMoveEvent.position - velocityEvent.position;
22581          var time = lastMoveEvent.time - velocityEvent.time;
22582          swiper.velocity = distance / time;
22583          swiper.velocity /= 2;
22584          if (Math.abs(swiper.velocity) < params.freeModeMinimumVelocity) {
22585            swiper.velocity = 0;
22586          }
22587          // this implies that the user stopped moving a finger then released.
22588          // There would be no events with distance zero, so the last event is stale.
22589          if (time > 150 || (Utils.now() - lastMoveEvent.time) > 300) {
22590            swiper.velocity = 0;
22591          }
22592        } else {
22593          swiper.velocity = 0;
22594        }
22595        swiper.velocity *= params.freeModeMomentumVelocityRatio;
22596
22597        data.velocities.length = 0;
22598        var momentumDuration = 1000 * params.freeModeMomentumRatio;
22599        var momentumDistance = swiper.velocity * momentumDuration;
22600
22601        var newPosition = swiper.translate + momentumDistance;
22602        if (rtl) { newPosition = -newPosition; }
22603
22604        var doBounce = false;
22605        var afterBouncePosition;
22606        var bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeModeMomentumBounceRatio;
22607        var needsLoopFix;
22608        if (newPosition < swiper.maxTranslate()) {
22609          if (params.freeModeMomentumBounce) {
22610            if (newPosition + swiper.maxTranslate() < -bounceAmount) {
22611              newPosition = swiper.maxTranslate() - bounceAmount;
22612            }
22613            afterBouncePosition = swiper.maxTranslate();
22614            doBounce = true;
22615            data.allowMomentumBounce = true;
22616          } else {
22617            newPosition = swiper.maxTranslate();
22618          }
22619          if (params.loop && params.centeredSlides) { needsLoopFix = true; }
22620        } else if (newPosition > swiper.minTranslate()) {
22621          if (params.freeModeMomentumBounce) {
22622            if (newPosition - swiper.minTranslate() > bounceAmount) {
22623              newPosition = swiper.minTranslate() + bounceAmount;
22624            }
22625            afterBouncePosition = swiper.minTranslate();
22626            doBounce = true;
22627            data.allowMomentumBounce = true;
22628          } else {
22629            newPosition = swiper.minTranslate();
22630          }
22631          if (params.loop && params.centeredSlides) { needsLoopFix = true; }
22632        } else if (params.freeModeSticky) {
22633          var nextSlide;
22634          for (var j = 0; j < snapGrid.length; j += 1) {
22635            if (snapGrid[j] > -newPosition) {
22636              nextSlide = j;
22637              break;
22638            }
22639          }
22640
22641          if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {
22642            newPosition = snapGrid[nextSlide];
22643          } else {
22644            newPosition = snapGrid[nextSlide - 1];
22645          }
22646          newPosition = -newPosition;
22647        }
22648        if (needsLoopFix) {
22649          swiper.once('transitionEnd', function () {
22650            swiper.loopFix();
22651          });
22652        }
22653        // Fix duration
22654        if (swiper.velocity !== 0) {
22655          if (rtl) {
22656            momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
22657          } else {
22658            momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
22659          }
22660        } else if (params.freeModeSticky) {
22661          swiper.slideToClosest();
22662          return;
22663        }
22664
22665        if (params.freeModeMomentumBounce && doBounce) {
22666          swiper.updateProgress(afterBouncePosition);
22667          swiper.setTransition(momentumDuration);
22668          swiper.setTranslate(newPosition);
22669          swiper.transitionStart(true, swiper.swipeDirection);
22670          swiper.animating = true;
22671          $wrapperEl.transitionEnd(function () {
22672            if (!swiper || swiper.destroyed || !data.allowMomentumBounce) { return; }
22673            swiper.emit('momentumBounce');
22674
22675            swiper.setTransition(params.speed);
22676            swiper.setTranslate(afterBouncePosition);
22677            $wrapperEl.transitionEnd(function () {
22678              if (!swiper || swiper.destroyed) { return; }
22679              swiper.transitionEnd();
22680            });
22681          });
22682        } else if (swiper.velocity) {
22683          swiper.updateProgress(newPosition);
22684          swiper.setTransition(momentumDuration);
22685          swiper.setTranslate(newPosition);
22686          swiper.transitionStart(true, swiper.swipeDirection);
22687          if (!swiper.animating) {
22688            swiper.animating = true;
22689            $wrapperEl.transitionEnd(function () {
22690              if (!swiper || swiper.destroyed) { return; }
22691              swiper.transitionEnd();
22692            });
22693          }
22694        } else {
22695          swiper.updateProgress(newPosition);
22696        }
22697
22698        swiper.updateActiveIndex();
22699        swiper.updateSlidesClasses();
22700      } else if (params.freeModeSticky) {
22701        swiper.slideToClosest();
22702        return;
22703      }
22704
22705      if (!params.freeModeMomentum || timeDiff >= params.longSwipesMs) {
22706        swiper.updateProgress();
22707        swiper.updateActiveIndex();
22708        swiper.updateSlidesClasses();
22709      }
22710      return;
22711    }
22712
22713    // Find current slide
22714    var stopIndex = 0;
22715    var groupSize = swiper.slidesSizesGrid[0];
22716    for (var i = 0; i < slidesGrid.length; i += params.slidesPerGroup) {
22717      if (typeof slidesGrid[i + params.slidesPerGroup] !== 'undefined') {
22718        if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + params.slidesPerGroup]) {
22719          stopIndex = i;
22720          groupSize = slidesGrid[i + params.slidesPerGroup] - slidesGrid[i];
22721        }
22722      } else if (currentPos >= slidesGrid[i]) {
22723        stopIndex = i;
22724        groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];
22725      }
22726    }
22727
22728    // Find current slide size
22729    var ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
22730
22731    if (timeDiff > params.longSwipesMs) {
22732      // Long touches
22733      if (!params.longSwipes) {
22734        swiper.slideTo(swiper.activeIndex);
22735        return;
22736      }
22737      if (swiper.swipeDirection === 'next') {
22738        if (ratio >= params.longSwipesRatio) { swiper.slideTo(stopIndex + params.slidesPerGroup); }
22739        else { swiper.slideTo(stopIndex); }
22740      }
22741      if (swiper.swipeDirection === 'prev') {
22742        if (ratio > (1 - params.longSwipesRatio)) { swiper.slideTo(stopIndex + params.slidesPerGroup); }
22743        else { swiper.slideTo(stopIndex); }
22744      }
22745    } else {
22746      // Short swipes
22747      if (!params.shortSwipes) {
22748        swiper.slideTo(swiper.activeIndex);
22749        return;
22750      }
22751      if (swiper.swipeDirection === 'next') {
22752        swiper.slideTo(stopIndex + params.slidesPerGroup);
22753      }
22754      if (swiper.swipeDirection === 'prev') {
22755        swiper.slideTo(stopIndex);
22756      }
22757    }
22758  }
22759
22760  function onResize () {
22761    var swiper = this;
22762
22763    var params = swiper.params;
22764    var el = swiper.el;
22765
22766    if (el && el.offsetWidth === 0) { return; }
22767
22768    // Breakpoints
22769    if (params.breakpoints) {
22770      swiper.setBreakpoint();
22771    }
22772
22773    // Save locks
22774    var allowSlideNext = swiper.allowSlideNext;
22775    var allowSlidePrev = swiper.allowSlidePrev;
22776    var snapGrid = swiper.snapGrid;
22777
22778    // Disable locks on resize
22779    swiper.allowSlideNext = true;
22780    swiper.allowSlidePrev = true;
22781
22782    swiper.updateSize();
22783    swiper.updateSlides();
22784
22785    if (params.freeMode) {
22786      var newTranslate = Math.min(Math.max(swiper.translate, swiper.maxTranslate()), swiper.minTranslate());
22787      swiper.setTranslate(newTranslate);
22788      swiper.updateActiveIndex();
22789      swiper.updateSlidesClasses();
22790
22791      if (params.autoHeight) {
22792        swiper.updateAutoHeight();
22793      }
22794    } else {
22795      swiper.updateSlidesClasses();
22796      if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {
22797        swiper.slideTo(swiper.slides.length - 1, 0, false, true);
22798      } else {
22799        swiper.slideTo(swiper.activeIndex, 0, false, true);
22800      }
22801    }
22802    
vendor: 1,925 bytes, lines 22802-22851
22802// Return locks after resize
22803    swiper.allowSlidePrev = allowSlidePrev;
22804    swiper.allowSlideNext = allowSlideNext;
22805
22806    if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {
22807      swiper.checkOverflow();
22808    }
22809  }
22810
22811  function onClick (e) {
22812    var swiper = this;
22813    if (!swiper.allowClick) {
22814      if (swiper.params.preventClicks) { e.preventDefault(); }
22815      if (swiper.params.preventClicksPropagation && swiper.animating) {
22816        e.stopPropagation();
22817        e.stopImmediatePropagation();
22818      }
22819    }
22820  }
22821
22822  function attachEvents() {
22823    var swiper = this;
22824    var params = swiper.params;
22825    var touchEvents = swiper.touchEvents;
22826    var el = swiper.el;
22827    var wrapperEl = swiper.wrapperEl;
22828
22829    {
22830      swiper.onTouchStart = onTouchStart.bind(swiper);
22831      swiper.onTouchMove = onTouchMove.bind(swiper);
22832      swiper.onTouchEnd = onTouchEnd.bind(swiper);
22833    }
22834
22835    swiper.onClick = onClick.bind(swiper);
22836
22837    var target = params.touchEventsTarget === 'container' ? el : wrapperEl;
22838    var capture = !!params.nested;
22839
22840    // Touch Events
22841    {
22842      if (!Support.touch && (Support.pointerEvents || Support.prefixedPointerEvents)) {
22843        target.addEventListener(touchEvents.start, swiper.onTouchStart, false);
22844        doc.addEventListener(touchEvents.move, swiper.onTouchMove, capture);
22845        doc.addEventListener(touchEvents.end, swiper.onTouchEnd, false);
22846      } else {
22847        if (Support.touch) {
22848          var passiveListener = touchEvents.start === 'touchstart' && Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
22849          target.addEventListener(touchEvents.start, swiper.onTouchStart, passiveListener);
22850          target.addEventListener(touchEvents.move, swiper.onTouchMove, Support.passiveListener ? { passive: false, capture: capture } : capture);
22851          target.addEventListener(touchEvents.end, swiper.onTouchEnd, passiveListener);
vendor: 22,581 bytes, lines 22851-23582
22851
22852        }
22853        if ((params.simulateTouch && !Device.ios && !Device.android) || (params.simulateTouch && !Support.touch && Device.ios)) {
22854          target.addEventListener('mousedown', swiper.onTouchStart, false);
22855          doc.addEventListener('mousemove', swiper.onTouchMove, capture);
22856          doc.addEventListener('mouseup', swiper.onTouchEnd, false);
22857        }
22858      }
22859      // Prevent Links Clicks
22860      if (params.preventClicks || params.preventClicksPropagation) {
22861        target.addEventListener('click', swiper.onClick, true);
22862      }
22863    }
22864
22865    // Resize handler
22866    swiper.on((Device.ios || Device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate'), onResize, true);
22867  }
22868
22869  function detachEvents() {
22870    var swiper = this;
22871
22872    var params = swiper.params;
22873    var touchEvents = swiper.touchEvents;
22874    var el = swiper.el;
22875    var wrapperEl = swiper.wrapperEl;
22876
22877    var target = params.touchEventsTarget === 'container' ? el : wrapperEl;
22878    var capture = !!params.nested;
22879
22880    // Touch Events
22881    {
22882      if (!Support.touch && (Support.pointerEvents || Support.prefixedPointerEvents)) {
22883        target.removeEventListener(touchEvents.start, swiper.onTouchStart, false);
22884        doc.removeEventListener(touchEvents.move, swiper.onTouchMove, capture);
22885        doc.removeEventListener(touchEvents.end, swiper.onTouchEnd, false);
22886      } else {
22887        if (Support.touch) {
22888          var passiveListener = touchEvents.start === 'onTouchStart' && Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
22889          target.removeEventListener(touchEvents.start, swiper.onTouchStart, passiveListener);
22890          target.removeEventListener(touchEvents.move, swiper.onTouchMove, capture);
22891          target.removeEventListener(touchEvents.end, swiper.onTouchEnd, passiveListener);
22892        }
22893        if ((params.simulateTouch && !Device.ios && !Device.android) || (params.simulateTouch && !Support.touch && Device.ios)) {
22894          target.removeEventListener('mousedown', swiper.onTouchStart, false);
22895          doc.removeEventListener('mousemove', swiper.onTouchMove, capture);
22896          doc.removeEventListener('mouseup', swiper.onTouchEnd, false);
22897        }
22898      }
22899      // Prevent Links Clicks
22900      if (params.preventClicks || params.preventClicksPropagation) {
22901        target.removeEventListener('click', swiper.onClick, true);
22902      }
22903    }
22904
22905    // Resize handler
22906    swiper.off((Device.ios || Device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate'), onResize);
22907  }
22908
22909  var events = {
22910    attachEvents: attachEvents,
22911    detachEvents: detachEvents,
22912  };
22913
22914  function setBreakpoint () {
22915    var swiper = this;
22916    var activeIndex = swiper.activeIndex;
22917    var initialized = swiper.initialized;
22918    var loopedSlides = swiper.loopedSlides; if ( loopedSlides === void 0 ) loopedSlides = 0;
22919    var params = swiper.params;
22920    var breakpoints = params.breakpoints;
22921    if (!breakpoints || (breakpoints && Object.keys(breakpoints).length === 0)) { return; }
22922
22923    // Set breakpoint for window width and update parameters
22924    var breakpoint = swiper.getBreakpoint(breakpoints);
22925
22926    if (breakpoint && swiper.currentBreakpoint !== breakpoint) {
22927      var breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;
22928      if (breakpointOnlyParams) {
22929        ['slidesPerView', 'spaceBetween', 'slidesPerGroup'].forEach(function (param) {
22930          var paramValue = breakpointOnlyParams[param];
22931          if (typeof paramValue === 'undefined') { return; }
22932          if (param === 'slidesPerView' && (paramValue === 'AUTO' || paramValue === 'auto')) {
22933            breakpointOnlyParams[param] = 'auto';
22934          } else if (param === 'slidesPerView') {
22935            breakpointOnlyParams[param] = parseFloat(paramValue);
22936          } else {
22937            breakpointOnlyParams[param] = parseInt(paramValue, 10);
22938          }
22939        });
22940      }
22941
22942      var breakpointParams = breakpointOnlyParams || swiper.originalParams;
22943      var directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;
22944      var needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);
22945
22946      if (directionChanged && initialized) {
22947        swiper.changeDirection();
22948      }
22949
22950      Utils.extend(swiper.params, breakpointParams);
22951
22952      Utils.extend(swiper, {
22953        allowTouchMove: swiper.params.allowTouchMove,
22954        allowSlideNext: swiper.params.allowSlideNext,
22955        allowSlidePrev: swiper.params.allowSlidePrev,
22956      });
22957
22958      swiper.currentBreakpoint = breakpoint;
22959
22960      if (needsReLoop && initialized) {
22961        swiper.loopDestroy();
22962        swiper.loopCreate();
22963        swiper.updateSlides();
22964        swiper.slideTo((activeIndex - loopedSlides) + swiper.loopedSlides, 0, false);
22965      }
22966
22967      swiper.emit('breakpoint', breakpointParams);
22968    }
22969  }
22970
22971  function getBreakpoint (breakpoints) {
22972    var swiper = this;
22973    // Get breakpoint for window width
22974    if (!breakpoints) { return undefined; }
22975    var breakpoint = false;
22976    var points = [];
22977    Object.keys(breakpoints).forEach(function (point) {
22978      points.push(point);
22979    });
22980    points.sort(function (a, b) { return parseInt(a, 10) - parseInt(b, 10); });
22981    for (var i = 0; i < points.length; i += 1) {
22982      var point = points[i];
22983      if (swiper.params.breakpointsInverse) {
22984        if (point <= win.innerWidth) {
22985          breakpoint = point;
22986        }
22987      } else if (point >= win.innerWidth && !breakpoint) {
22988        breakpoint = point;
22989      }
22990    }
22991    return breakpoint || 'max';
22992  }
22993
22994  var breakpoints = { setBreakpoint: setBreakpoint, getBreakpoint: getBreakpoint };
22995
22996  function addClasses () {
22997    var swiper = this;
22998    var classNames = swiper.classNames;
22999    var params = swiper.params;
23000    var rtl = swiper.rtl;
23001    var $el = swiper.$el;
23002    var suffixes = [];
23003
23004    suffixes.push('initialized');
23005    suffixes.push(params.direction);
23006
23007    if (params.freeMode) {
23008      suffixes.push('free-mode');
23009    }
23010    if (!Support.flexbox) {
23011      suffixes.push('no-flexbox');
23012    }
23013    if (params.autoHeight) {
23014      suffixes.push('autoheight');
23015    }
23016    if (rtl) {
23017      suffixes.push('rtl');
23018    }
23019    if (params.slidesPerColumn > 1) {
23020      suffixes.push('multirow');
23021    }
23022    if (Device.android) {
23023      suffixes.push('android');
23024    }
23025    if (Device.ios) {
23026      suffixes.push('ios');
23027    }
23028    // WP8 Touch Events Fix
23029    if ((Browser.isIE || Browser.isEdge) && (Support.pointerEvents || Support.prefixedPointerEvents)) {
23030      suffixes.push(("wp8-" + (params.direction)));
23031    }
23032
23033    suffixes.forEach(function (suffix) {
23034      classNames.push(params.containerModifierClass + suffix);
23035    });
23036
23037    $el.addClass(classNames.join(' '));
23038  }
23039
23040  function removeClasses () {
23041    var swiper = this;
23042    var $el = swiper.$el;
23043    var classNames = swiper.classNames;
23044
23045    $el.removeClass(classNames.join(' '));
23046  }
23047
23048  var classes = { addClasses: addClasses, removeClasses: removeClasses };
23049
23050  function loadImage (imageEl, src, srcset, sizes, checkForComplete, callback) {
23051    var image;
23052    function onReady() {
23053      if (callback) { callback(); }
23054    }
23055    if (!imageEl.complete || !checkForComplete) {
23056      if (src) {
23057        image = new win.Image();
23058        image.onload = onReady;
23059        image.onerror = onReady;
23060        if (sizes) {
23061          image.sizes = sizes;
23062        }
23063        if (srcset) {
23064          image.srcset = srcset;
23065        }
23066        if (src) {
23067          image.src = src;
23068        }
23069      } else {
23070        onReady();
23071      }
23072    } else {
23073      // image already loaded...
23074      onReady();
23075    }
23076  }
23077
23078  function preloadImages () {
23079    var swiper = this;
23080    swiper.imagesToLoad = swiper.$el.find('img');
23081    function onReady() {
23082      if (typeof swiper === 'undefined' || swiper === null || !swiper || swiper.destroyed) { return; }
23083      if (swiper.imagesLoaded !== undefined) { swiper.imagesLoaded += 1; }
23084      if (swiper.imagesLoaded === swiper.imagesToLoad.length) {
23085        if (swiper.params.updateOnImagesReady) { swiper.update(); }
23086        swiper.emit('imagesReady');
23087      }
23088    }
23089    for (var i = 0; i < swiper.imagesToLoad.length; i += 1) {
23090      var imageEl = swiper.imagesToLoad[i];
23091      swiper.loadImage(
23092        imageEl,
23093        imageEl.currentSrc || imageEl.getAttribute('src'),
23094        imageEl.srcset || imageEl.getAttribute('srcset'),
23095        imageEl.sizes || imageEl.getAttribute('sizes'),
23096        true,
23097        onReady
23098      );
23099    }
23100  }
23101
23102  var images = {
23103    loadImage: loadImage,
23104    preloadImages: preloadImages,
23105  };
23106
23107  function checkOverflow() {
23108    var swiper = this;
23109    var wasLocked = swiper.isLocked;
23110
23111    swiper.isLocked = swiper.snapGrid.length === 1;
23112    swiper.allowSlideNext = !swiper.isLocked;
23113    swiper.allowSlidePrev = !swiper.isLocked;
23114
23115    // events
23116    if (wasLocked !== swiper.isLocked) { swiper.emit(swiper.isLocked ? 'lock' : 'unlock'); }
23117
23118    if (wasLocked && wasLocked !== swiper.isLocked) {
23119      swiper.isEnd = false;
23120      swiper.navigation.update();
23121    }
23122  }
23123
23124  var checkOverflow$1 = { checkOverflow: checkOverflow };
23125
23126  var defaults = {
23127    init: true,
23128    direction: 'horizontal',
23129    touchEventsTarget: 'container',
23130    initialSlide: 0,
23131    speed: 300,
23132    //
23133    preventInteractionOnTransition: false,
23134
23135    // To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView).
23136    edgeSwipeDetection: false,
23137    edgeSwipeThreshold: 20,
23138
23139    // Free mode
23140    freeMode: false,
23141    freeModeMomentum: true,
23142    freeModeMomentumRatio: 1,
23143    freeModeMomentumBounce: true,
23144    freeModeMomentumBounceRatio: 1,
23145    freeModeMomentumVelocityRatio: 1,
23146    freeModeSticky: false,
23147    freeModeMinimumVelocity: 0.02,
23148
23149    // Autoheight
23150    autoHeight: false,
23151
23152    // Set wrapper width
23153    setWrapperSize: false,
23154
23155    // Virtual Translate
23156    virtualTranslate: false,
23157
23158    // Effects
23159    effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
23160
23161    // Breakpoints
23162    breakpoints: undefined,
23163    breakpointsInverse: false,
23164
23165    // Slides grid
23166    spaceBetween: 0,
23167    slidesPerView: 1,
23168    slidesPerColumn: 1,
23169    slidesPerColumnFill: 'column',
23170    slidesPerGroup: 1,
23171    centeredSlides: false,
23172    slidesOffsetBefore: 0, // in px
23173    slidesOffsetAfter: 0, // in px
23174    normalizeSlideIndex: true,
23175    centerInsufficientSlides: false,
23176
23177    // Disable swiper and hide navigation when container not overflow
23178    watchOverflow: false,
23179
23180    // Round length
23181    roundLengths: false,
23182
23183    // Touches
23184    touchRatio: 1,
23185    touchAngle: 45,
23186    simulateTouch: true,
23187    shortSwipes: true,
23188    longSwipes: true,
23189    longSwipesRatio: 0.5,
23190    longSwipesMs: 300,
23191    followFinger: true,
23192    allowTouchMove: true,
23193    threshold: 0,
23194    touchMoveStopPropagation: true,
23195    touchStartPreventDefault: true,
23196    touchStartForcePreventDefault: false,
23197    touchReleaseOnEdges: false,
23198
23199    // Unique Navigation Elements
23200    uniqueNavElements: true,
23201
23202    // Resistance
23203    resistance: true,
23204    resistanceRatio: 0.85,
23205
23206    // Progress
23207    watchSlidesProgress: false,
23208    watchSlidesVisibility: false,
23209
23210    // Cursor
23211    grabCursor: false,
23212
23213    // Clicks
23214    preventClicks: true,
23215    preventClicksPropagation: true,
23216    slideToClickedSlide: false,
23217
23218    // Images
23219    preloadImages: true,
23220    updateOnImagesReady: true,
23221
23222    // loop
23223    loop: false,
23224    loopAdditionalSlides: 0,
23225    loopedSlides: null,
23226    loopFillGroupWithBlank: false,
23227
23228    // Swiping/no swiping
23229    allowSlidePrev: true,
23230    allowSlideNext: true,
23231    swipeHandler: null, // '.swipe-handler',
23232    noSwiping: true,
23233    noSwipingClass: 'swiper-no-swiping',
23234    noSwipingSelector: null,
23235
23236    // Passive Listeners
23237    passiveListeners: true,
23238
23239    // NS
23240    containerModifierClass: 'swiper-container-', // NEW
23241    slideClass: 'swiper-slide',
23242    slideBlankClass: 'swiper-slide-invisible-blank',
23243    slideActiveClass: 'swiper-slide-active',
23244    slideDuplicateActiveClass: 'swiper-slide-duplicate-active',
23245    slideVisibleClass: 'swiper-slide-visible',
23246    slideDuplicateClass: 'swiper-slide-duplicate',
23247    slideNextClass: 'swiper-slide-next',
23248    slideDuplicateNextClass: 'swiper-slide-duplicate-next',
23249    slidePrevClass: 'swiper-slide-prev',
23250    slideDuplicatePrevClass: 'swiper-slide-duplicate-prev',
23251    wrapperClass: 'swiper-wrapper',
23252
23253    // Callbacks
23254    runCallbacksOnInit: true,
23255  };
23256
23257  /* eslint no-param-reassign: "off" */
23258
23259  var prototypes = {
23260    update: update,
23261    translate: translate,
23262    transition: transition$1,
23263    slide: slide,
23264    loop: loop,
23265    grabCursor: grabCursor,
23266    manipulation: manipulation,
23267    events: events,
23268    breakpoints: breakpoints,
23269    checkOverflow: checkOverflow$1,
23270    classes: classes,
23271    images: images,
23272  };
23273
23274  var extendedDefaults = {};
23275
23276  var Swiper = /*@__PURE__*/(function (SwiperClass) {
23277    function Swiper() {
23278      var assign;
23279
23280      var args = [], len = arguments.length;
23281      while ( len-- ) args[ len ] = arguments[ len ];
23282      var el;
23283      var params;
23284      if (args.length === 1 && args[0].constructor && args[0].constructor === Object) {
23285        params = args[0];
23286      } else {
23287        (assign = args, el = assign[0], params = assign[1]);
23288      }
23289      if (!params) { params = {}; }
23290
23291      params = Utils.extend({}, params);
23292      if (el && !params.el) { params.el = el; }
23293
23294      SwiperClass.call(this, params);
23295
23296      Object.keys(prototypes).forEach(function (prototypeGroup) {
23297        Object.keys(prototypes[prototypeGroup]).forEach(function (protoMethod) {
23298          if (!Swiper.prototype[protoMethod]) {
23299            Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod];
23300          }
23301        });
23302      });
23303
23304      // Swiper Instance
23305      var swiper = this;
23306      if (typeof swiper.modules === 'undefined') {
23307        swiper.modules = {};
23308      }
23309      Object.keys(swiper.modules).forEach(function (moduleName) {
23310        var module = swiper.modules[moduleName];
23311        if (module.params) {
23312          var moduleParamName = Object.keys(module.params)[0];
23313          var moduleParams = module.params[moduleParamName];
23314          if (typeof moduleParams !== 'object' || moduleParams === null) { return; }
23315          if (!(moduleParamName in params && 'enabled' in moduleParams)) { return; }
23316          if (params[moduleParamName] === true) {
23317            params[moduleParamName] = { enabled: true };
23318          }
23319          if (
23320            typeof params[moduleParamName] === 'object'
23321            && !('enabled' in params[moduleParamName])
23322          ) {
23323            params[moduleParamName].enabled = true;
23324          }
23325          if (!params[moduleParamName]) { params[moduleParamName] = { enabled: false }; }
23326        }
23327      });
23328
23329      // Extend defaults with modules params
23330      var swiperParams = Utils.extend({}, defaults);
23331      swiper.useModulesParams(swiperParams);
23332
23333      // Extend defaults with passed params
23334      swiper.params = Utils.extend({}, swiperParams, extendedDefaults, params);
23335      swiper.originalParams = Utils.extend({}, swiper.params);
23336      swiper.passedParams = Utils.extend({}, params);
23337
23338      // Save Dom lib
23339      swiper.$ = $;
23340
23341      // Find el
23342      var $el = $(swiper.params.el);
23343      el = $el[0];
23344
23345      if (!el) {
23346        return undefined;
23347      }
23348
23349      if ($el.length > 1) {
23350        var swipers = [];
23351        $el.each(function (index, containerEl) {
23352          var newParams = Utils.extend({}, params, { el: containerEl });
23353          swipers.push(new Swiper(newParams));
23354        });
23355        return swipers;
23356      }
23357
23358      el.swiper = swiper;
23359      $el.data('swiper', swiper);
23360
23361      // Find Wrapper
23362      var $wrapperEl = $el.children(("." + (swiper.params.wrapperClass)));
23363
23364      // Extend Swiper
23365      Utils.extend(swiper, {
23366        $el: $el,
23367        el: el,
23368        $wrapperEl: $wrapperEl,
23369        wrapperEl: $wrapperEl[0],
23370
23371        // Classes
23372        classNames: [],
23373
23374        // Slides
23375        slides: $(),
23376        slidesGrid: [],
23377        snapGrid: [],
23378        slidesSizesGrid: [],
23379
23380        // isDirection
23381        isHorizontal: function isHorizontal() {
23382          return swiper.params.direction === 'horizontal';
23383        },
23384        isVertical: function isVertical() {
23385          return swiper.params.direction === 'vertical';
23386        },
23387        // RTL
23388        rtl: (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),
23389        rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),
23390        wrongRTL: $wrapperEl.css('display') === '-webkit-box',
23391
23392        // Indexes
23393        activeIndex: 0,
23394        realIndex: 0,
23395
23396        //
23397        isBeginning: true,
23398        isEnd: false,
23399
23400        // Props
23401        translate: 0,
23402        previousTranslate: 0,
23403        progress: 0,
23404        velocity: 0,
23405        animating: false,
23406
23407        // Locks
23408        allowSlideNext: swiper.params.allowSlideNext,
23409        allowSlidePrev: swiper.params.allowSlidePrev,
23410
23411        // Touch Events
23412        touchEvents: (function touchEvents() {
23413          var touch = ['touchstart', 'touchmove', 'touchend'];
23414          var desktop = ['mousedown', 'mousemove', 'mouseup'];
23415          if (Support.pointerEvents) {
23416            desktop = ['pointerdown', 'pointermove', 'pointerup'];
23417          } else if (Support.prefixedPointerEvents) {
23418            desktop = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp'];
23419          }
23420          swiper.touchEventsTouch = {
23421            start: touch[0],
23422            move: touch[1],
23423            end: touch[2],
23424          };
23425          swiper.touchEventsDesktop = {
23426            start: desktop[0],
23427            move: desktop[1],
23428            end: desktop[2],
23429          };
23430          return Support.touch || !swiper.params.simulateTouch ? swiper.touchEventsTouch : swiper.touchEventsDesktop;
23431        }()),
23432        touchEventsData: {
23433          isTouched: undefined,
23434          isMoved: undefined,
23435          allowTouchCallbacks: undefined,
23436          touchStartTime: undefined,
23437          isScrolling: undefined,
23438          currentTranslate: undefined,
23439          startTranslate: undefined,
23440          allowThresholdMove: undefined,
23441          // Form elements to match
23442          formElements: 'input, select, option, textarea, button, video',
23443          // Last click time
23444          lastClickTime: Utils.now(),
23445          clickTimeout: undefined,
23446          // Velocities
23447          velocities: [],
23448          allowMomentumBounce: undefined,
23449          isTouchEvent: undefined,
23450          startMoving: undefined,
23451        },
23452
23453        // Clicks
23454        allowClick: true,
23455
23456        // Touches
23457        allowTouchMove: swiper.params.allowTouchMove,
23458
23459        touches: {
23460          startX: 0,
23461          startY: 0,
23462          currentX: 0,
23463          currentY: 0,
23464          diff: 0,
23465        },
23466
23467        // Images
23468        imagesToLoad: [],
23469        imagesLoaded: 0,
23470
23471      });
23472
23473      // Install Modules
23474      swiper.useModules();
23475
23476      // Init
23477      if (swiper.params.init) {
23478        swiper.init();
23479      }
23480
23481      // Return app instance
23482      return swiper;
23483    }
23484
23485    if ( SwiperClass ) Swiper.__proto__ = SwiperClass;
23486    Swiper.prototype = Object.create( SwiperClass && SwiperClass.prototype );
23487    Swiper.prototype.constructor = Swiper;
23488
23489    var staticAccessors = { extendedDefaults: { configurable: true },defaults: { configurable: true },Class: { configurable: true },$: { configurable: true } };
23490
23491    Swiper.prototype.slidesPerViewDynamic = function slidesPerViewDynamic () {
23492      var swiper = this;
23493      var params = swiper.params;
23494      var slides = swiper.slides;
23495      var slidesGrid = swiper.slidesGrid;
23496      var swiperSize = swiper.size;
23497      var activeIndex = swiper.activeIndex;
23498      var spv = 1;
23499      if (params.centeredSlides) {
23500        var slideSize = slides[activeIndex].swiperSlideSize;
23501        var breakLoop;
23502        for (var i = activeIndex + 1; i < slides.length; i += 1) {
23503          if (slides[i] && !breakLoop) {
23504            slideSize += slides[i].swiperSlideSize;
23505            spv += 1;
23506            if (slideSize > swiperSize) { breakLoop = true; }
23507          }
23508        }
23509        for (var i$1 = activeIndex - 1; i$1 >= 0; i$1 -= 1) {
23510          if (slides[i$1] && !breakLoop) {
23511            slideSize += slides[i$1].swiperSlideSize;
23512            spv += 1;
23513            if (slideSize > swiperSize) { breakLoop = true; }
23514          }
23515        }
23516      } else {
23517        for (var i$2 = activeIndex + 1; i$2 < slides.length; i$2 += 1) {
23518          if (slidesGrid[i$2] - slidesGrid[activeIndex] < swiperSize) {
23519            spv += 1;
23520          }
23521        }
23522      }
23523      return spv;
23524    };
23525
23526    Swiper.prototype.update = function update () {
23527      var swiper = this;
23528      if (!swiper || swiper.destroyed) { return; }
23529      var snapGrid = swiper.snapGrid;
23530      var params = swiper.params;
23531      // Breakpoints
23532      if (params.breakpoints) {
23533        swiper.setBreakpoint();
23534      }
23535      swiper.updateSize();
23536      swiper.updateSlides();
23537      swiper.updateProgress();
23538      swiper.updateSlidesClasses();
23539
23540      function setTranslate() {
23541        var translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate;
23542        var newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate());
23543        swiper.setTranslate(newTranslate);
23544        swiper.updateActiveIndex();
23545        swiper.updateSlidesClasses();
23546      }
23547      var translated;
23548      if (swiper.params.freeMode) {
23549        setTranslate();
23550        if (swiper.params.autoHeight) {
23551          swiper.updateAutoHeight();
23552        }
23553      } else {
23554        if ((swiper.params.slidesPerView === 'auto' || swiper.params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {
23555          translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);
23556        } else {
23557          translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
23558        }
23559        if (!translated) {
23560          setTranslate();
23561        }
23562      }
23563      if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
23564        swiper.checkOverflow();
23565      }
23566      swiper.emit('update');
23567    };
23568
23569    Swiper.prototype.changeDirection = function changeDirection (newDirection, needUpdate) {
23570      if ( needUpdate === void 0 ) needUpdate = true;
23571
23572      var swiper = this;
23573      var currentDirection = swiper.params.direction;
23574      if (!newDirection) {
23575        // eslint-disable-next-line
23576        newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';
23577      }
23578      if ((newDirection === currentDirection) || (newDirection !== 'horizontal' && newDirection !== 'vertical')) {
23579        return swiper;
23580      }
23581
23582      
23582if (currentDirection === 'vertical') {
23583        swiper.$el
23584          .removeClass(((swiper.params.containerModifierClass) + "vertical wp8-vertical"))
23585          .addClass(("" + (swiper.params.containerModifierClass) + newDirection));
23586
23587        if ((Browser.isIE || Browser.isEdge) && (Support.pointerEvents || Support.prefixedPointerEvents)) {
23588          swiper.$el.addClass(((swiper.params.containerModifierClass) + "wp8-" + newDirection));
23589        }
23590      }
23591      if (currentDirection === 'horizontal') {
23592        swiper.$el
23593          .removeClass(((swiper.params.containerModifierClass) + "horizontal wp8-horizontal"))
23594          .addClass(("" + (swiper.params.containerModifierClass) + newDirection));
23595
23596        if ((Browser.isIE || Browser.isEdge) && (Support.pointerEvents || Support.prefixedPointerEvents)) {
23597          swiper.$el.addClass(((swiper.params.containerModifierClass) + "wp8-" + newDirection));
23598        }
vendor: 17,112 bytes, lines 23598-24164
23598
23599      }
23600
23601      swiper.params.direction = newDirection;
23602
23603      swiper.slides.each(function (slideIndex, slideEl) {
23604        if (newDirection === 'vertical') {
23605          slideEl.style.width = '';
23606        } else {
23607          slideEl.style.height = '';
23608        }
23609      });
23610
23611      swiper.emit('changeDirection');
23612      if (needUpdate) { swiper.update(); }
23613
23614      return swiper;
23615    };
23616
23617    Swiper.prototype.init = function init () {
23618      var swiper = this;
23619      if (swiper.initialized) { return; }
23620
23621      swiper.emit('beforeInit');
23622
23623      // Set breakpoint
23624      if (swiper.params.breakpoints) {
23625        swiper.setBreakpoint();
23626      }
23627
23628      // Add Classes
23629      swiper.addClasses();
23630
23631      // Create loop
23632      if (swiper.params.loop) {
23633        swiper.loopCreate();
23634      }
23635
23636      // Update size
23637      swiper.updateSize();
23638
23639      // Update slides
23640      swiper.updateSlides();
23641
23642      if (swiper.params.watchOverflow) {
23643        swiper.checkOverflow();
23644      }
23645
23646      // Set Grab Cursor
23647      if (swiper.params.grabCursor) {
23648        swiper.setGrabCursor();
23649      }
23650
23651      if (swiper.params.preloadImages) {
23652        swiper.preloadImages();
23653      }
23654
23655      // Slide To Initial Slide
23656      if (swiper.params.loop) {
23657        swiper.slideTo(swiper.params.initialSlide + swiper.loopedSlides, 0, swiper.params.runCallbacksOnInit);
23658      } else {
23659        swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit);
23660      }
23661
23662      // Attach events
23663      swiper.attachEvents();
23664
23665      // Init Flag
23666      swiper.initialized = true;
23667
23668      // Emit
23669      swiper.emit('init');
23670    };
23671
23672    Swiper.prototype.destroy = function destroy (deleteInstance, cleanStyles) {
23673      if ( deleteInstance === void 0 ) deleteInstance = true;
23674      if ( cleanStyles === void 0 ) cleanStyles = true;
23675
23676      var swiper = this;
23677      var params = swiper.params;
23678      var $el = swiper.$el;
23679      var $wrapperEl = swiper.$wrapperEl;
23680      var slides = swiper.slides;
23681
23682      if (typeof swiper.params === 'undefined' || swiper.destroyed) {
23683        return null;
23684      }
23685
23686      swiper.emit('beforeDestroy');
23687
23688      // Init Flag
23689      swiper.initialized = false;
23690
23691      // Detach events
23692      swiper.detachEvents();
23693
23694      // Destroy loop
23695      if (params.loop) {
23696        swiper.loopDestroy();
23697      }
23698
23699      // Cleanup styles
23700      if (cleanStyles) {
23701        swiper.removeClasses();
23702        $el.removeAttr('style');
23703        $wrapperEl.removeAttr('style');
23704        if (slides && slides.length) {
23705          slides
23706            .removeClass([
23707              params.slideVisibleClass,
23708              params.slideActiveClass,
23709              params.slideNextClass,
23710              params.slidePrevClass ].join(' '))
23711            .removeAttr('style')
23712            .removeAttr('data-swiper-slide-index')
23713            .removeAttr('data-swiper-column')
23714            .removeAttr('data-swiper-row');
23715        }
23716      }
23717
23718      swiper.emit('destroy');
23719
23720      // Detach emitter events
23721      Object.keys(swiper.eventsListeners).forEach(function (eventName) {
23722        swiper.off(eventName);
23723      });
23724
23725      if (deleteInstance !== false) {
23726        swiper.$el[0].swiper = null;
23727        swiper.$el.data('swiper', null);
23728        Utils.deleteProps(swiper);
23729      }
23730      swiper.destroyed = true;
23731
23732      return null;
23733    };
23734
23735    Swiper.extendDefaults = function extendDefaults (newDefaults) {
23736      Utils.extend(extendedDefaults, newDefaults);
23737    };
23738
23739    staticAccessors.extendedDefaults.get = function () {
23740      return extendedDefaults;
23741    };
23742
23743    staticAccessors.defaults.get = function () {
23744      return defaults;
23745    };
23746
23747    staticAccessors.Class.get = function () {
23748      return SwiperClass;
23749    };
23750
23751    staticAccessors.$.get = function () {
23752      return $;
23753    };
23754
23755    Object.defineProperties( Swiper, staticAccessors );
23756
23757    return Swiper;
23758  }(SwiperClass));
23759
23760  var Device$1 = {
23761    name: 'device',
23762    proto: {
23763      device: Device,
23764    },
23765    static: {
23766      device: Device,
23767    },
23768  };
23769
23770  var Support$1 = {
23771    name: 'support',
23772    proto: {
23773      support: Support,
23774    },
23775    static: {
23776      support: Support,
23777    },
23778  };
23779
23780  var Browser$1 = {
23781    name: 'browser',
23782    proto: {
23783      browser: Browser,
23784    },
23785    static: {
23786      browser: Browser,
23787    },
23788  };
23789
23790  var Resize = {
23791    name: 'resize',
23792    create: function create() {
23793      var swiper = this;
23794      Utils.extend(swiper, {
23795        resize: {
23796          resizeHandler: function resizeHandler() {
23797            if (!swiper || swiper.destroyed || !swiper.initialized) { return; }
23798            swiper.emit('beforeResize');
23799            swiper.emit('resize');
23800          },
23801          orientationChangeHandler: function orientationChangeHandler() {
23802            if (!swiper || swiper.destroyed || !swiper.initialized) { return; }
23803            swiper.emit('orientationchange');
23804          },
23805        },
23806      });
23807    },
23808    on: {
23809      init: function init() {
23810        var swiper = this;
23811        // Emit resize
23812        win.addEventListener('resize', swiper.resize.resizeHandler);
23813
23814        // Emit orientationchange
23815        win.addEventListener('orientationchange', swiper.resize.orientationChangeHandler);
23816      },
23817      destroy: function destroy() {
23818        var swiper = this;
23819        win.removeEventListener('resize', swiper.resize.resizeHandler);
23820        win.removeEventListener('orientationchange', swiper.resize.orientationChangeHandler);
23821      },
23822    },
23823  };
23824
23825  var Observer = {
23826    func: win.MutationObserver || win.WebkitMutationObserver,
23827    attach: function attach(target, options) {
23828      if ( options === void 0 ) options = {};
23829
23830      var swiper = this;
23831
23832      var ObserverFunc = Observer.func;
23833      var observer = new ObserverFunc(function (mutations) {
23834        // The observerUpdate event should only be triggered
23835        // once despite the number of mutations.  Additional
23836        // triggers are redundant and are very costly
23837        if (mutations.length === 1) {
23838          swiper.emit('observerUpdate', mutations[0]);
23839          return;
23840        }
23841        var observerUpdate = function observerUpdate() {
23842          swiper.emit('observerUpdate', mutations[0]);
23843        };
23844
23845        if (win.requestAnimationFrame) {
23846          win.requestAnimationFrame(observerUpdate);
23847        } else {
23848          win.setTimeout(observerUpdate, 0);
23849        }
23850      });
23851
23852      observer.observe(target, {
23853        attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
23854        childList: typeof options.childList === 'undefined' ? true : options.childList,
23855        characterData: typeof options.characterData === 'undefined' ? true : options.characterData,
23856      });
23857
23858      swiper.observer.observers.push(observer);
23859    },
23860    init: function init() {
23861      var swiper = this;
23862      if (!Support.observer || !swiper.params.observer) { return; }
23863      if (swiper.params.observeParents) {
23864        var containerParents = swiper.$el.parents();
23865        for (var i = 0; i < containerParents.length; i += 1) {
23866          swiper.observer.attach(containerParents[i]);
23867        }
23868      }
23869      // Observe container
23870      swiper.observer.attach(swiper.$el[0], { childList: swiper.params.observeSlideChildren });
23871
23872      // Observe wrapper
23873      swiper.observer.attach(swiper.$wrapperEl[0], { attributes: false });
23874    },
23875    destroy: function destroy() {
23876      var swiper = this;
23877      swiper.observer.observers.forEach(function (observer) {
23878        observer.disconnect();
23879      });
23880      swiper.observer.observers = [];
23881    },
23882  };
23883
23884  var Observer$1 = {
23885    name: 'observer',
23886    params: {
23887      observer: false,
23888      observeParents: false,
23889      observeSlideChildren: false,
23890    },
23891    create: function create() {
23892      var swiper = this;
23893      Utils.extend(swiper, {
23894        observer: {
23895          init: Observer.init.bind(swiper),
23896          attach: Observer.attach.bind(swiper),
23897          destroy: Observer.destroy.bind(swiper),
23898          observers: [],
23899        },
23900      });
23901    },
23902    on: {
23903      init: function init() {
23904        var swiper = this;
23905        swiper.observer.init();
23906      },
23907      destroy: function destroy() {
23908        var swiper = this;
23909        swiper.observer.destroy();
23910      },
23911    },
23912  };
23913
23914  var Virtual = {
23915    update: function update(force) {
23916      var swiper = this;
23917      var ref = swiper.params;
23918      var slidesPerView = ref.slidesPerView;
23919      var slidesPerGroup = ref.slidesPerGroup;
23920      var centeredSlides = ref.centeredSlides;
23921      var ref$1 = swiper.params.virtual;
23922      var addSlidesBefore = ref$1.addSlidesBefore;
23923      var addSlidesAfter = ref$1.addSlidesAfter;
23924      var ref$2 = swiper.virtual;
23925      var previousFrom = ref$2.from;
23926      var previousTo = ref$2.to;
23927      var slides = ref$2.slides;
23928      var previousSlidesGrid = ref$2.slidesGrid;
23929      var renderSlide = ref$2.renderSlide;
23930      var previousOffset = ref$2.offset;
23931      swiper.updateActiveIndex();
23932      var activeIndex = swiper.activeIndex || 0;
23933
23934      var offsetProp;
23935      if (swiper.rtlTranslate) { offsetProp = 'right'; }
23936      else { offsetProp = swiper.isHorizontal() ? 'left' : 'top'; }
23937
23938      var slidesAfter;
23939      var slidesBefore;
23940      if (centeredSlides) {
23941        slidesAfter = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesBefore;
23942        slidesBefore = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesAfter;
23943      } else {
23944        slidesAfter = slidesPerView + (slidesPerGroup - 1) + addSlidesBefore;
23945        slidesBefore = slidesPerGroup + addSlidesAfter;
23946      }
23947      var from = Math.max((activeIndex || 0) - slidesBefore, 0);
23948      var to = Math.min((activeIndex || 0) + slidesAfter, slides.length - 1);
23949      var offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0);
23950
23951      Utils.extend(swiper.virtual, {
23952        from: from,
23953        to: to,
23954        offset: offset,
23955        slidesGrid: swiper.slidesGrid,
23956      });
23957
23958      function onRendered() {
23959        swiper.updateSlides();
23960        swiper.updateProgress();
23961        swiper.updateSlidesClasses();
23962        if (swiper.lazy && swiper.params.lazy.enabled) {
23963          swiper.lazy.load();
23964        }
23965      }
23966
23967      if (previousFrom === from && previousTo === to && !force) {
23968        if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {
23969          swiper.slides.css(offsetProp, (offset + "px"));
23970        }
23971        swiper.updateProgress();
23972        return;
23973      }
23974      if (swiper.params.virtual.renderExternal) {
23975        swiper.params.virtual.renderExternal.call(swiper, {
23976          offset: offset,
23977          from: from,
23978          to: to,
23979          slides: (function getSlides() {
23980            var slidesToRender = [];
23981            for (var i = from; i <= to; i += 1) {
23982              slidesToRender.push(slides[i]);
23983            }
23984            return slidesToRender;
23985          }()),
23986        });
23987        onRendered();
23988        return;
23989      }
23990      var prependIndexes = [];
23991      var appendIndexes = [];
23992      if (force) {
23993        swiper.$wrapperEl.find(("." + (swiper.params.slideClass))).remove();
23994      } else {
23995        for (var i = previousFrom; i <= previousTo; i += 1) {
23996          if (i < from || i > to) {
23997            swiper.$wrapperEl.find(("." + (swiper.params.slideClass) + "[data-swiper-slide-index=\"" + i + "\"]")).remove();
23998          }
23999        }
24000      }
24001      for (var i$1 = 0; i$1 < slides.length; i$1 += 1) {
24002        if (i$1 >= from && i$1 <= to) {
24003          if (typeof previousTo === 'undefined' || force) {
24004            appendIndexes.push(i$1);
24005          } else {
24006            if (i$1 > previousTo) { appendIndexes.push(i$1); }
24007            if (i$1 < previousFrom) { prependIndexes.push(i$1); }
24008          }
24009        }
24010      }
24011      appendIndexes.forEach(function (index) {
24012        swiper.$wrapperEl.append(renderSlide(slides[index], index));
24013      });
24014      prependIndexes.sort(function (a, b) { return b - a; }).forEach(function (index) {
24015        swiper.$wrapperEl.prepend(renderSlide(slides[index], index));
24016      });
24017      swiper.$wrapperEl.children('.swiper-slide').css(offsetProp, (offset + "px"));
24018      onRendered();
24019    },
24020    renderSlide: function renderSlide(slide, index) {
24021      var swiper = this;
24022      var params = swiper.params.virtual;
24023      if (params.cache && swiper.virtual.cache[index]) {
24024        return swiper.virtual.cache[index];
24025      }
24026      var $slideEl = params.renderSlide
24027        ? $(params.renderSlide.call(swiper, slide, index))
24028        : $(("<div class=\"" + (swiper.params.slideClass) + "\" data-swiper-slide-index=\"" + index + "\">" + slide + "</div>"));
24029      if (!$slideEl.attr('data-swiper-slide-index')) { $slideEl.attr('data-swiper-slide-index', index); }
24030      if (params.cache) { swiper.virtual.cache[index] = $slideEl; }
24031      return $slideEl;
24032    },
24033    appendSlide: function appendSlide(slides) {
24034      var swiper = this;
24035      if (typeof slides === 'object' && 'length' in slides) {
24036        for (var i = 0; i < slides.length; i += 1) {
24037          if (slides[i]) { swiper.virtual.slides.push(slides[i]); }
24038        }
24039      } else {
24040        swiper.virtual.slides.push(slides);
24041      }
24042      swiper.virtual.update(true);
24043    },
24044    prependSlide: function prependSlide(slides) {
24045      var swiper = this;
24046      var activeIndex = swiper.activeIndex;
24047      var newActiveIndex = activeIndex + 1;
24048      var numberOfNewSlides = 1;
24049
24050      if (Array.isArray(slides)) {
24051        for (var i = 0; i < slides.length; i += 1) {
24052          if (slides[i]) { swiper.virtual.slides.unshift(slides[i]); }
24053        }
24054        newActiveIndex = activeIndex + slides.length;
24055        numberOfNewSlides = slides.length;
24056      } else {
24057        swiper.virtual.slides.unshift(slides);
24058      }
24059      if (swiper.params.virtual.cache) {
24060        var cache = swiper.virtual.cache;
24061        var newCache = {};
24062        Object.keys(cache).forEach(function (cachedIndex) {
24063          newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = cache[cachedIndex];
24064        });
24065        swiper.virtual.cache = newCache;
24066      }
24067      swiper.virtual.update(true);
24068      swiper.slideTo(newActiveIndex, 0);
24069    },
24070    removeSlide: function removeSlide(slidesIndexes) {
24071      var swiper = this;
24072      if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) { return; }
24073      var activeIndex = swiper.activeIndex;
24074      if (Array.isArray(slidesIndexes)) {
24075        for (var i = slidesIndexes.length - 1; i >= 0; i -= 1) {
24076          swiper.virtual.slides.splice(slidesIndexes[i], 1);
24077          if (swiper.params.virtual.cache) {
24078            delete swiper.virtual.cache[slidesIndexes[i]];
24079          }
24080          if (slidesIndexes[i] < activeIndex) { activeIndex -= 1; }
24081          activeIndex = Math.max(activeIndex, 0);
24082        }
24083      } else {
24084        swiper.virtual.slides.splice(slidesIndexes, 1);
24085        if (swiper.params.virtual.cache) {
24086          delete swiper.virtual.cache[slidesIndexes];
24087        }
24088        if (slidesIndexes < activeIndex) { activeIndex -= 1; }
24089        activeIndex = Math.max(activeIndex, 0);
24090      }
24091      swiper.virtual.update(true);
24092      swiper.slideTo(activeIndex, 0);
24093    },
24094    removeAllSlides: function removeAllSlides() {
24095      var swiper = this;
24096      swiper.virtual.slides = [];
24097      if (swiper.params.virtual.cache) {
24098        swiper.virtual.cache = {};
24099      }
24100      swiper.virtual.update(true);
24101      swiper.slideTo(0, 0);
24102    },
24103  };
24104
24105  var Virtual$1 = {
24106    name: 'virtual',
24107    params: {
24108      virtual: {
24109        enabled: false,
24110        slides: [],
24111        cache: true,
24112        renderSlide: null,
24113        renderExternal: null,
24114        addSlidesBefore: 0,
24115        addSlidesAfter: 0,
24116      },
24117    },
24118    create: function create() {
24119      var swiper = this;
24120      Utils.extend(swiper, {
24121        virtual: {
24122          update: Virtual.update.bind(swiper),
24123          appendSlide: Virtual.appendSlide.bind(swiper),
24124          prependSlide: Virtual.prependSlide.bind(swiper),
24125          removeSlide: Virtual.removeSlide.bind(swiper),
24126          removeAllSlides: Virtual.removeAllSlides.bind(swiper),
24127          renderSlide: Virtual.renderSlide.bind(swiper),
24128          slides: swiper.params.virtual.slides,
24129          cache: {},
24130        },
24131      });
24132    },
24133    on: {
24134      beforeInit: function beforeInit() {
24135        var swiper = this;
24136        if (!swiper.params.virtual.enabled) { return; }
24137        swiper.classNames.push(((swiper.params.containerModifierClass) + "virtual"));
24138        var overwriteParams = {
24139          watchSlidesProgress: true,
24140        };
24141        Utils.extend(swiper.params, overwriteParams);
24142        Utils.extend(swiper.originalParams, overwriteParams);
24143
24144        if (!swiper.params.initialSlide) {
24145          swiper.virtual.update();
24146        }
24147      },
24148      setTranslate: function setTranslate() {
24149        var swiper = this;
24150        if (!swiper.params.virtual.enabled) { return; }
24151        swiper.virtual.update();
24152      },
24153    },
24154  };
24155
24156  var Keyboard = {
24157    handle: function handle(event) {
24158      var swiper = this;
24159      var rtl = swiper.rtlTranslate;
24160      var e = event;
24161      if (e.originalEvent) { e = e.originalEvent; } // jquery fix
24162      var kc = e.keyCode || e.charCode;
24163      // Directions locks
24164      if (!swiper.allowSlideNext && ((swiper.isHorizontal() && kc === 39) || (swiper.isVertical() && kc === 40)
vendor: 2,274 bytes, lines 24164-24215
24164)) {
24165        return false;
24166      }
24167      if (!swiper.allowSlidePrev && ((swiper.isHorizontal() && kc === 37) || (swiper.isVertical() && kc === 38))) {
24168        return false;
24169      }
24170      if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {
24171        return undefined;
24172      }
24173      if (doc.activeElement && doc.activeElement.nodeName && (doc.activeElement.nodeName.toLowerCase() === 'input' || doc.activeElement.nodeName.toLowerCase() === 'textarea')) {
24174        return undefined;
24175      }
24176      if (swiper.params.keyboard.onlyInViewport && (kc === 37 || kc === 39 || kc === 38 || kc === 40)) {
24177        var inView = false;
24178        // Check that swiper should be inside of visible area of window
24179        if (swiper.$el.parents(("." + (swiper.params.slideClass))).length > 0 && swiper.$el.parents(("." + (swiper.params.slideActiveClass))).length === 0) {
24180          return undefined;
24181        }
24182        var windowWidth = win.innerWidth;
24183        var windowHeight = win.innerHeight;
24184        var swiperOffset = swiper.$el.offset();
24185        if (rtl) { swiperOffset.left -= swiper.$el[0].scrollLeft; }
24186        var swiperCoord = [
24187          [swiperOffset.left, swiperOffset.top],
24188          [swiperOffset.left + swiper.width, swiperOffset.top],
24189          [swiperOffset.left, swiperOffset.top + swiper.height],
24190          [swiperOffset.left + swiper.width, swiperOffset.top + swiper.height] ];
24191        for (var i = 0; i < swiperCoord.length; i += 1) {
24192          var point = swiperCoord[i];
24193          if (
24194            point[0] >= 0 && point[0] <= windowWidth
24195            && point[1] >= 0 && point[1] <= windowHeight
24196          ) {
24197            inView = true;
24198          }
24199        }
24200        if (!inView) { return undefined; }
24201      }
24202      if (swiper.isHorizontal()) {
24203        if (kc === 37 || kc === 39) {
24204          if (e.preventDefault) { e.preventDefault(); }
24205          else { e.returnValue = false; }
24206        }
24207        if ((kc === 39 && !rtl) || (kc === 37 && rtl)) { swiper.slideNext(); }
24208        if ((kc === 37 && !rtl) || (kc === 39 && rtl)) { swiper.slidePrev(); }
24209      } else {
24210        if (kc === 38 || kc === 40) {
24211          if (e.preventDefault) { e.preventDefault(); }
24212          else { e.returnValue = false; }
24213        }
24214        if (kc === 40) { swiper.slideNext(); }
24215        if (
vendor: 31,875 bytes, lines 24215-25132
24215kc === 38) { swiper.slidePrev(); }
24216      }
24217      swiper.emit('keyPress', kc);
24218      return undefined;
24219    },
24220    enable: function enable() {
24221      var swiper = this;
24222      if (swiper.keyboard.enabled) { return; }
24223      $(doc).on('keydown', swiper.keyboard.handle);
24224      swiper.keyboard.enabled = true;
24225    },
24226    disable: function disable() {
24227      var swiper = this;
24228      if (!swiper.keyboard.enabled) { return; }
24229      $(doc).off('keydown', swiper.keyboard.handle);
24230      swiper.keyboard.enabled = false;
24231    },
24232  };
24233
24234  var Keyboard$1 = {
24235    name: 'keyboard',
24236    params: {
24237      keyboard: {
24238        enabled: false,
24239        onlyInViewport: true,
24240      },
24241    },
24242    create: function create() {
24243      var swiper = this;
24244      Utils.extend(swiper, {
24245        keyboard: {
24246          enabled: false,
24247          enable: Keyboard.enable.bind(swiper),
24248          disable: Keyboard.disable.bind(swiper),
24249          handle: Keyboard.handle.bind(swiper),
24250        },
24251      });
24252    },
24253    on: {
24254      init: function init() {
24255        var swiper = this;
24256        if (swiper.params.keyboard.enabled) {
24257          swiper.keyboard.enable();
24258        }
24259      },
24260      destroy: function destroy() {
24261        var swiper = this;
24262        if (swiper.keyboard.enabled) {
24263          swiper.keyboard.disable();
24264        }
24265      },
24266    },
24267  };
24268
24269  function isEventSupported() {
24270    var eventName = 'onwheel';
24271    var isSupported = eventName in doc;
24272
24273    if (!isSupported) {
24274      var element = doc.createElement('div');
24275      element.setAttribute(eventName, 'return;');
24276      isSupported = typeof element[eventName] === 'function';
24277    }
24278
24279    if (!isSupported
24280      && doc.implementation
24281      && doc.implementation.hasFeature
24282      // always returns true in newer browsers as per the standard.
24283      // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
24284      && doc.implementation.hasFeature('', '') !== true
24285    ) {
24286      // This is the only way to test support for the `wheel` event in IE9+.
24287      isSupported = doc.implementation.hasFeature('Events.wheel', '3.0');
24288    }
24289
24290    return isSupported;
24291  }
24292  var Mousewheel = {
24293    lastScrollTime: Utils.now(),
24294    event: (function getEvent() {
24295      if (win.navigator.userAgent.indexOf('firefox') > -1) { return 'DOMMouseScroll'; }
24296      return isEventSupported() ? 'wheel' : 'mousewheel';
24297    }()),
24298    normalize: function normalize(e) {
24299      // Reasonable defaults
24300      var PIXEL_STEP = 10;
24301      var LINE_HEIGHT = 40;
24302      var PAGE_HEIGHT = 800;
24303
24304      var sX = 0;
24305      var sY = 0; // spinX, spinY
24306      var pX = 0;
24307      var pY = 0; // pixelX, pixelY
24308
24309      // Legacy
24310      if ('detail' in e) {
24311        sY = e.detail;
24312      }
24313      if ('wheelDelta' in e) {
24314        sY = -e.wheelDelta / 120;
24315      }
24316      if ('wheelDeltaY' in e) {
24317        sY = -e.wheelDeltaY / 120;
24318      }
24319      if ('wheelDeltaX' in e) {
24320        sX = -e.wheelDeltaX / 120;
24321      }
24322
24323      // side scrolling on FF with DOMMouseScroll
24324      if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) {
24325        sX = sY;
24326        sY = 0;
24327      }
24328
24329      pX = sX * PIXEL_STEP;
24330      pY = sY * PIXEL_STEP;
24331
24332      if ('deltaY' in e) {
24333        pY = e.deltaY;
24334      }
24335      if ('deltaX' in e) {
24336        pX = e.deltaX;
24337      }
24338
24339      if ((pX || pY) && e.deltaMode) {
24340        if (e.deltaMode === 1) { // delta in LINE units
24341          pX *= LINE_HEIGHT;
24342          pY *= LINE_HEIGHT;
24343        } else { // delta in PAGE units
24344          pX *= PAGE_HEIGHT;
24345          pY *= PAGE_HEIGHT;
24346        }
24347      }
24348
24349      // Fall-back if spin cannot be determined
24350      if (pX && !sX) {
24351        sX = (pX < 1) ? -1 : 1;
24352      }
24353      if (pY && !sY) {
24354        sY = (pY < 1) ? -1 : 1;
24355      }
24356
24357      return {
24358        spinX: sX,
24359        spinY: sY,
24360        pixelX: pX,
24361        pixelY: pY,
24362      };
24363    },
24364    handleMouseEnter: function handleMouseEnter() {
24365      var swiper = this;
24366      swiper.mouseEntered = true;
24367    },
24368    handleMouseLeave: function handleMouseLeave() {
24369      var swiper = this;
24370      swiper.mouseEntered = false;
24371    },
24372    handle: function handle(event) {
24373      var e = event;
24374      var swiper = this;
24375      var params = swiper.params.mousewheel;
24376
24377      if (!swiper.mouseEntered && !params.releaseOnEdges) { return true; }
24378
24379      if (e.originalEvent) { e = e.originalEvent; } // jquery fix
24380      var delta = 0;
24381      var rtlFactor = swiper.rtlTranslate ? -1 : 1;
24382
24383      var data = Mousewheel.normalize(e);
24384
24385      if (params.forceToAxis) {
24386        if (swiper.isHorizontal()) {
24387          if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) { delta = data.pixelX * rtlFactor; }
24388          else { return true; }
24389        } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) { delta = data.pixelY; }
24390        else { return true; }
24391      } else {
24392        delta = Math.abs(data.pixelX) > Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY;
24393      }
24394
24395      if (delta === 0) { return true; }
24396
24397      if (params.invert) { delta = -delta; }
24398
24399      if (!swiper.params.freeMode) {
24400        if (Utils.now() - swiper.mousewheel.lastScrollTime > 60) {
24401          if (delta < 0) {
24402            if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) {
24403              swiper.slideNext();
24404              swiper.emit('scroll', e);
24405            } else if (params.releaseOnEdges) { return true; }
24406          } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) {
24407            swiper.slidePrev();
24408            swiper.emit('scroll', e);
24409          } else if (params.releaseOnEdges) { return true; }
24410        }
24411        swiper.mousewheel.lastScrollTime = (new win.Date()).getTime();
24412      } else {
24413        // Freemode or scrollContainer:
24414        if (swiper.params.loop) {
24415          swiper.loopFix();
24416        }
24417        var position = swiper.getTranslate() + (delta * params.sensitivity);
24418        var wasBeginning = swiper.isBeginning;
24419        var wasEnd = swiper.isEnd;
24420
24421        if (position >= swiper.minTranslate()) { position = swiper.minTranslate(); }
24422        if (position <= swiper.maxTranslate()) { position = swiper.maxTranslate(); }
24423
24424        swiper.setTransition(0);
24425        swiper.setTranslate(position);
24426        swiper.updateProgress();
24427        swiper.updateActiveIndex();
24428        swiper.updateSlidesClasses();
24429
24430        if ((!wasBeginning && swiper.isBeginning) || (!wasEnd && swiper.isEnd)) {
24431          swiper.updateSlidesClasses();
24432        }
24433
24434        if (swiper.params.freeModeSticky) {
24435          clearTimeout(swiper.mousewheel.timeout);
24436          swiper.mousewheel.timeout = Utils.nextTick(function () {
24437            swiper.slideToClosest();
24438          }, 300);
24439        }
24440        // Emit event
24441        swiper.emit('scroll', e);
24442
24443        // Stop autoplay
24444        if (swiper.params.autoplay && swiper.params.autoplayDisableOnInteraction) { swiper.autoplay.stop(); }
24445        // Return page scroll on edge positions
24446        if (position === swiper.minTranslate() || position === swiper.maxTranslate()) { return true; }
24447      }
24448
24449      if (e.preventDefault) { e.preventDefault(); }
24450      else { e.returnValue = false; }
24451      return false;
24452    },
24453    enable: function enable() {
24454      var swiper = this;
24455      if (!Mousewheel.event) { return false; }
24456      if (swiper.mousewheel.enabled) { return false; }
24457      var target = swiper.$el;
24458      if (swiper.params.mousewheel.eventsTarged !== 'container') {
24459        target = $(swiper.params.mousewheel.eventsTarged);
24460      }
24461      target.on('mouseenter', swiper.mousewheel.handleMouseEnter);
24462      target.on('mouseleave', swiper.mousewheel.handleMouseLeave);
24463      target.on(Mousewheel.event, swiper.mousewheel.handle);
24464      swiper.mousewheel.enabled = true;
24465      return true;
24466    },
24467    disable: function disable() {
24468      var swiper = this;
24469      if (!Mousewheel.event) { return false; }
24470      if (!swiper.mousewheel.enabled) { return false; }
24471      var target = swiper.$el;
24472      if (swiper.params.mousewheel.eventsTarged !== 'container') {
24473        target = $(swiper.params.mousewheel.eventsTarged);
24474      }
24475      target.off(Mousewheel.event, swiper.mousewheel.handle);
24476      swiper.mousewheel.enabled = false;
24477      return true;
24478    },
24479  };
24480
24481  var Mousewheel$1 = {
24482    name: 'mousewheel',
24483    params: {
24484      mousewheel: {
24485        enabled: false,
24486        releaseOnEdges: false,
24487        invert: false,
24488        forceToAxis: false,
24489        sensitivity: 1,
24490        eventsTarged: 'container',
24491      },
24492    },
24493    create: function create() {
24494      var swiper = this;
24495      Utils.extend(swiper, {
24496        mousewheel: {
24497          enabled: false,
24498          enable: Mousewheel.enable.bind(swiper),
24499          disable: Mousewheel.disable.bind(swiper),
24500          handle: Mousewheel.handle.bind(swiper),
24501          handleMouseEnter: Mousewheel.handleMouseEnter.bind(swiper),
24502          handleMouseLeave: Mousewheel.handleMouseLeave.bind(swiper),
24503          lastScrollTime: Utils.now(),
24504        },
24505      });
24506    },
24507    on: {
24508      init: function init() {
24509        var swiper = this;
24510        if (swiper.params.mousewheel.enabled) { swiper.mousewheel.enable(); }
24511      },
24512      destroy: function destroy() {
24513        var swiper = this;
24514        if (swiper.mousewheel.enabled) { swiper.mousewheel.disable(); }
24515      },
24516    },
24517  };
24518
24519  var Navigation = {
24520    update: function update() {
24521      // Update Navigation Buttons
24522      var swiper = this;
24523      var params = swiper.params.navigation;
24524
24525      if (swiper.params.loop) { return; }
24526      var ref = swiper.navigation;
24527      var $nextEl = ref.$nextEl;
24528      var $prevEl = ref.$prevEl;
24529
24530      if ($prevEl && $prevEl.length > 0) {
24531        if (swiper.isBeginning) {
24532          $prevEl.addClass(params.disabledClass);
24533        } else {
24534          $prevEl.removeClass(params.disabledClass);
24535        }
24536        $prevEl[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
24537      }
24538      if ($nextEl && $nextEl.length > 0) {
24539        if (swiper.isEnd) {
24540          $nextEl.addClass(params.disabledClass);
24541        } else {
24542          $nextEl.removeClass(params.disabledClass);
24543        }
24544        $nextEl[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
24545      }
24546    },
24547    onPrevClick: function onPrevClick(e) {
24548      var swiper = this;
24549      e.preventDefault();
24550      if (swiper.isBeginning && !swiper.params.loop) { return; }
24551      swiper.slidePrev();
24552    },
24553    onNextClick: function onNextClick(e) {
24554      var swiper = this;
24555      e.preventDefault();
24556      if (swiper.isEnd && !swiper.params.loop) { return; }
24557      swiper.slideNext();
24558    },
24559    init: function init() {
24560      var swiper = this;
24561      var params = swiper.params.navigation;
24562      if (!(params.nextEl || params.prevEl)) { return; }
24563
24564      var $nextEl;
24565      var $prevEl;
24566      if (params.nextEl) {
24567        $nextEl = $(params.nextEl);
24568        if (
24569          swiper.params.uniqueNavElements
24570          && typeof params.nextEl === 'string'
24571          && $nextEl.length > 1
24572          && swiper.$el.find(params.nextEl).length === 1
24573        ) {
24574          $nextEl = swiper.$el.find(params.nextEl);
24575        }
24576      }
24577      if (params.prevEl) {
24578        $prevEl = $(params.prevEl);
24579        if (
24580          swiper.params.uniqueNavElements
24581          && typeof params.prevEl === 'string'
24582          && $prevEl.length > 1
24583          && swiper.$el.find(params.prevEl).length === 1
24584        ) {
24585          $prevEl = swiper.$el.find(params.prevEl);
24586        }
24587      }
24588
24589      if ($nextEl && $nextEl.length > 0) {
24590        $nextEl.on('click', swiper.navigation.onNextClick);
24591      }
24592      if ($prevEl && $prevEl.length > 0) {
24593        $prevEl.on('click', swiper.navigation.onPrevClick);
24594      }
24595
24596      Utils.extend(swiper.navigation, {
24597        $nextEl: $nextEl,
24598        nextEl: $nextEl && $nextEl[0],
24599        $prevEl: $prevEl,
24600        prevEl: $prevEl && $prevEl[0],
24601      });
24602    },
24603    destroy: function destroy() {
24604      var swiper = this;
24605      var ref = swiper.navigation;
24606      var $nextEl = ref.$nextEl;
24607      var $prevEl = ref.$prevEl;
24608      if ($nextEl && $nextEl.length) {
24609        $nextEl.off('click', swiper.navigation.onNextClick);
24610        $nextEl.removeClass(swiper.params.navigation.disabledClass);
24611      }
24612      if ($prevEl && $prevEl.length) {
24613        $prevEl.off('click', swiper.navigation.onPrevClick);
24614        $prevEl.removeClass(swiper.params.navigation.disabledClass);
24615      }
24616    },
24617  };
24618
24619  var Navigation$1 = {
24620    name: 'navigation',
24621    params: {
24622      navigation: {
24623        nextEl: null,
24624        prevEl: null,
24625
24626        hideOnClick: false,
24627        disabledClass: 'swiper-button-disabled',
24628        hiddenClass: 'swiper-button-hidden',
24629        lockClass: 'swiper-button-lock',
24630      },
24631    },
24632    create: function create() {
24633      var swiper = this;
24634      Utils.extend(swiper, {
24635        navigation: {
24636          init: Navigation.init.bind(swiper),
24637          update: Navigation.update.bind(swiper),
24638          destroy: Navigation.destroy.bind(swiper),
24639          onNextClick: Navigation.onNextClick.bind(swiper),
24640          onPrevClick: Navigation.onPrevClick.bind(swiper),
24641        },
24642      });
24643    },
24644    on: {
24645      init: function init() {
24646        var swiper = this;
24647        swiper.navigation.init();
24648        swiper.navigation.update();
24649      },
24650      toEdge: function toEdge() {
24651        var swiper = this;
24652        swiper.navigation.update();
24653      },
24654      fromEdge: function fromEdge() {
24655        var swiper = this;
24656        swiper.navigation.update();
24657      },
24658      destroy: function destroy() {
24659        var swiper = this;
24660        swiper.navigation.destroy();
24661      },
24662      click: function click(e) {
24663        var swiper = this;
24664        var ref = swiper.navigation;
24665        var $nextEl = ref.$nextEl;
24666        var $prevEl = ref.$prevEl;
24667        if (
24668          swiper.params.navigation.hideOnClick
24669          && !$(e.target).is($prevEl)
24670          && !$(e.target).is($nextEl)
24671        ) {
24672          var isHidden;
24673          if ($nextEl) {
24674            isHidden = $nextEl.hasClass(swiper.params.navigation.hiddenClass);
24675          } else if ($prevEl) {
24676            isHidden = $prevEl.hasClass(swiper.params.navigation.hiddenClass);
24677          }
24678          if (isHidden === true) {
24679            swiper.emit('navigationShow', swiper);
24680          } else {
24681            swiper.emit('navigationHide', swiper);
24682          }
24683          if ($nextEl) {
24684            $nextEl.toggleClass(swiper.params.navigation.hiddenClass);
24685          }
24686          if ($prevEl) {
24687            $prevEl.toggleClass(swiper.params.navigation.hiddenClass);
24688          }
24689        }
24690      },
24691    },
24692  };
24693
24694  var Pagination = {
24695    update: function update() {
24696      // Render || Update Pagination bullets/items
24697      var swiper = this;
24698      var rtl = swiper.rtl;
24699      var params = swiper.params.pagination;
24700      if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) { return; }
24701      var slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
24702      var $el = swiper.pagination.$el;
24703      // Current/Total
24704      var current;
24705      var total = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
24706      if (swiper.params.loop) {
24707        current = Math.ceil((swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup);
24708        if (current > slidesLength - 1 - (swiper.loopedSlides * 2)) {
24709          current -= (slidesLength - (swiper.loopedSlides * 2));
24710        }
24711        if (current > total - 1) { current -= total; }
24712        if (current < 0 && swiper.params.paginationType !== 'bullets') { current = total + current; }
24713      } else if (typeof swiper.snapIndex !== 'undefined') {
24714        current = swiper.snapIndex;
24715      } else {
24716        current = swiper.activeIndex || 0;
24717      }
24718      // Types
24719      if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {
24720        var bullets = swiper.pagination.bullets;
24721        var firstIndex;
24722        var lastIndex;
24723        var midIndex;
24724        if (params.dynamicBullets) {
24725          swiper.pagination.bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
24726          $el.css(swiper.isHorizontal() ? 'width' : 'height', ((swiper.pagination.bulletSize * (params.dynamicMainBullets + 4)) + "px"));
24727          if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
24728            swiper.pagination.dynamicBulletIndex += (current - swiper.previousIndex);
24729            if (swiper.pagination.dynamicBulletIndex > (params.dynamicMainBullets - 1)) {
24730              swiper.pagination.dynamicBulletIndex = params.dynamicMainBullets - 1;
24731            } else if (swiper.pagination.dynamicBulletIndex < 0) {
24732              swiper.pagination.dynamicBulletIndex = 0;
24733            }
24734          }
24735          firstIndex = current - swiper.pagination.dynamicBulletIndex;
24736          lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
24737          midIndex = (lastIndex + firstIndex) / 2;
24738        }
24739        bullets.removeClass(((params.bulletActiveClass) + " " + (params.bulletActiveClass) + "-next " + (params.bulletActiveClass) + "-next-next " + (params.bulletActiveClass) + "-prev " + (params.bulletActiveClass) + "-prev-prev " + (params.bulletActiveClass) + "-main"));
24740        if ($el.length > 1) {
24741          bullets.each(function (index, bullet) {
24742            var $bullet = $(bullet);
24743            var bulletIndex = $bullet.index();
24744            if (bulletIndex === current) {
24745              $bullet.addClass(params.bulletActiveClass);
24746            }
24747            if (params.dynamicBullets) {
24748              if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
24749                $bullet.addClass(((params.bulletActiveClass) + "-main"));
24750              }
24751              if (bulletIndex === firstIndex) {
24752                $bullet
24753                  .prev()
24754                  .addClass(((params.bulletActiveClass) + "-prev"))
24755                  .prev()
24756                  .addClass(((params.bulletActiveClass) + "-prev-prev"));
24757              }
24758              if (bulletIndex === lastIndex) {
24759                $bullet
24760                  .next()
24761                  .addClass(((params.bulletActiveClass) + "-next"))
24762                  .next()
24763                  .addClass(((params.bulletActiveClass) + "-next-next"));
24764              }
24765            }
24766          });
24767        } else {
24768          var $bullet = bullets.eq(current);
24769          $bullet.addClass(params.bulletActiveClass);
24770          if (params.dynamicBullets) {
24771            var $firstDisplayedBullet = bullets.eq(firstIndex);
24772            var $lastDisplayedBullet = bullets.eq(lastIndex);
24773            for (var i = firstIndex; i <= lastIndex; i += 1) {
24774              bullets.eq(i).addClass(((params.bulletActiveClass) + "-main"));
24775            }
24776            $firstDisplayedBullet
24777              .prev()
24778              .addClass(((params.bulletActiveClass) + "-prev"))
24779              .prev()
24780              .addClass(((params.bulletActiveClass) + "-prev-prev"));
24781            $lastDisplayedBullet
24782              .next()
24783              .addClass(((params.bulletActiveClass) + "-next"))
24784              .next()
24785              .addClass(((params.bulletActiveClass) + "-next-next"));
24786          }
24787        }
24788        if (params.dynamicBullets) {
24789          var dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
24790          var bulletsOffset = (((swiper.pagination.bulletSize * dynamicBulletsLength) - (swiper.pagination.bulletSize)) / 2) - (midIndex * swiper.pagination.bulletSize);
24791          var offsetProp = rtl ? 'right' : 'left';
24792          bullets.css(swiper.isHorizontal() ? offsetProp : 'top', (bulletsOffset + "px"));
24793        }
24794      }
24795      if (params.type === 'fraction') {
24796        $el.find(("." + (params.currentClass))).text(params.formatFractionCurrent(current + 1));
24797        $el.find(("." + (params.totalClass))).text(params.formatFractionTotal(total));
24798      }
24799      if (params.type === 'progressbar') {
24800        var progressbarDirection;
24801        if (params.progressbarOpposite) {
24802          progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
24803        } else {
24804          progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
24805        }
24806        var scale = (current + 1) / total;
24807        var scaleX = 1;
24808        var scaleY = 1;
24809        if (progressbarDirection === 'horizontal') {
24810          scaleX = scale;
24811        } else {
24812          scaleY = scale;
24813        }
24814        $el.find(("." + (params.progressbarFillClass))).transform(("translate3d(0,0,0) scaleX(" + scaleX + ") scaleY(" + scaleY + ")")).transition(swiper.params.speed);
24815      }
24816      if (params.type === 'custom' && params.renderCustom) {
24817        $el.html(params.renderCustom(swiper, current + 1, total));
24818        swiper.emit('paginationRender', swiper, $el[0]);
24819      } else {
24820        swiper.emit('paginationUpdate', swiper, $el[0]);
24821      }
24822      $el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
24823    },
24824    render: function render() {
24825      // Render Container
24826      var swiper = this;
24827      var params = swiper.params.pagination;
24828      if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) { return; }
24829      var slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
24830
24831      var $el = swiper.pagination.$el;
24832      var paginationHTML = '';
24833      if (params.type === 'bullets') {
24834        var numberOfBullets = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
24835        for (var i = 0; i < numberOfBullets; i += 1) {
24836          if (params.renderBullet) {
24837            paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
24838          } else {
24839            paginationHTML += "<" + (params.bulletElement) + " class=\"" + (params.bulletClass) + "\"></" + (params.bulletElement) + ">";
24840          }
24841        }
24842        $el.html(paginationHTML);
24843        swiper.pagination.bullets = $el.find(("." + (params.bulletClass)));
24844      }
24845      if (params.type === 'fraction') {
24846        if (params.renderFraction) {
24847          paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
24848        } else {
24849          paginationHTML = "<span class=\"" + (params.currentClass) + "\"></span>"
24850          + ' / '
24851          + "<span class=\"" + (params.totalClass) + "\"></span>";
24852        }
24853        $el.html(paginationHTML);
24854      }
24855      if (params.type === 'progressbar') {
24856        if (params.renderProgressbar) {
24857          paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
24858        } else {
24859          paginationHTML = "<span class=\"" + (params.progressbarFillClass) + "\"></span>";
24860        }
24861        $el.html(paginationHTML);
24862      }
24863      if (params.type !== 'custom') {
24864        swiper.emit('paginationRender', swiper.pagination.$el[0]);
24865      }
24866    },
24867    init: function init() {
24868      var swiper = this;
24869      var params = swiper.params.pagination;
24870      if (!params.el) { return; }
24871
24872      var $el = $(params.el);
24873      if ($el.length === 0) { return; }
24874
24875      if (
24876        swiper.params.uniqueNavElements
24877        && typeof params.el === 'string'
24878        && $el.length > 1
24879        && swiper.$el.find(params.el).length === 1
24880      ) {
24881        $el = swiper.$el.find(params.el);
24882      }
24883
24884      if (params.type === 'bullets' && params.clickable) {
24885        $el.addClass(params.clickableClass);
24886      }
24887
24888      $el.addClass(params.modifierClass + params.type);
24889
24890      if (params.type === 'bullets' && params.dynamicBullets) {
24891        $el.addClass(("" + (params.modifierClass) + (params.type) + "-dynamic"));
24892        swiper.pagination.dynamicBulletIndex = 0;
24893        if (params.dynamicMainBullets < 1) {
24894          params.dynamicMainBullets = 1;
24895        }
24896      }
24897      if (params.type === 'progressbar' && params.progressbarOpposite) {
24898        $el.addClass(params.progressbarOppositeClass);
24899      }
24900
24901      if (params.clickable) {
24902        $el.on('click', ("." + (params.bulletClass)), function onClick(e) {
24903          e.preventDefault();
24904          var index = $(this).index() * swiper.params.slidesPerGroup;
24905          if (swiper.params.loop) { index += swiper.loopedSlides; }
24906          swiper.slideTo(index);
24907        });
24908      }
24909
24910      Utils.extend(swiper.pagination, {
24911        $el: $el,
24912        el: $el[0],
24913      });
24914    },
24915    destroy: function destroy() {
24916      var swiper = this;
24917      var params = swiper.params.pagination;
24918      if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) { return; }
24919      var $el = swiper.pagination.$el;
24920
24921      $el.removeClass(params.hiddenClass);
24922      $el.removeClass(params.modifierClass + params.type);
24923      if (swiper.pagination.bullets) { swiper.pagination.bullets.removeClass(params.bulletActiveClass); }
24924      if (params.clickable) {
24925        $el.off('click', ("." + (params.bulletClass)));
24926      }
24927    },
24928  };
24929
24930  var Pagination$1 = {
24931    name: 'pagination',
24932    params: {
24933      pagination: {
24934        el: null,
24935        bulletElement: 'span',
24936        clickable: false,
24937        hideOnClick: false,
24938        renderBullet: null,
24939        renderProgressbar: null,
24940        renderFraction: null,
24941        renderCustom: null,
24942        progressbarOpposite: false,
24943        type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom'
24944        dynamicBullets: false,
24945        dynamicMainBullets: 1,
24946        formatFractionCurrent: function (number) { return number; },
24947        formatFractionTotal: function (number) { return number; },
24948        bulletClass: 'swiper-pagination-bullet',
24949        bulletActiveClass: 'swiper-pagination-bullet-active',
24950        modifierClass: 'swiper-pagination-', // NEW
24951        currentClass: 'swiper-pagination-current',
24952        totalClass: 'swiper-pagination-total',
24953        hiddenClass: 'swiper-pagination-hidden',
24954        progressbarFillClass: 'swiper-pagination-progressbar-fill',
24955        progressbarOppositeClass: 'swiper-pagination-progressbar-opposite',
24956        clickableClass: 'swiper-pagination-clickable', // NEW
24957        lockClass: 'swiper-pagination-lock',
24958      },
24959    },
24960    create: function create() {
24961      var swiper = this;
24962      Utils.extend(swiper, {
24963        pagination: {
24964          init: Pagination.init.bind(swiper),
24965          render: Pagination.render.bind(swiper),
24966          update: Pagination.update.bind(swiper),
24967          destroy: Pagination.destroy.bind(swiper),
24968          dynamicBulletIndex: 0,
24969        },
24970      });
24971    },
24972    on: {
24973      init: function init() {
24974        var swiper = this;
24975        swiper.pagination.init();
24976        swiper.pagination.render();
24977        swiper.pagination.update();
24978      },
24979      activeIndexChange: function activeIndexChange() {
24980        var swiper = this;
24981        if (swiper.params.loop) {
24982          swiper.pagination.update();
24983        } else if (typeof swiper.snapIndex === 'undefined') {
24984          swiper.pagination.update();
24985        }
24986      },
24987      snapIndexChange: function snapIndexChange() {
24988        var swiper = this;
24989        if (!swiper.params.loop) {
24990          swiper.pagination.update();
24991        }
24992      },
24993      slidesLengthChange: function slidesLengthChange() {
24994        var swiper = this;
24995        if (swiper.params.loop) {
24996          swiper.pagination.render();
24997          swiper.pagination.update();
24998        }
24999      },
25000      snapGridLengthChange: function snapGridLengthChange() {
25001        var swiper = this;
25002        if (!swiper.params.loop) {
25003          swiper.pagination.render();
25004          swiper.pagination.update();
25005        }
25006      },
25007      destroy: function destroy() {
25008        var swiper = this;
25009        swiper.pagination.destroy();
25010      },
25011      click: function click(e) {
25012        var swiper = this;
25013        if (
25014          swiper.params.pagination.el
25015          && swiper.params.pagination.hideOnClick
25016          && swiper.pagination.$el.length > 0
25017          && !$(e.target).hasClass(swiper.params.pagination.bulletClass)
25018        ) {
25019          var isHidden = swiper.pagination.$el.hasClass(swiper.params.pagination.hiddenClass);
25020          if (isHidden === true) {
25021            swiper.emit('paginationShow', swiper);
25022          } else {
25023            swiper.emit('paginationHide', swiper);
25024          }
25025          swiper.pagination.$el.toggleClass(swiper.params.pagination.hiddenClass);
25026        }
25027      },
25028    },
25029  };
25030
25031  var Scrollbar = {
25032    setTranslate: function setTranslate() {
25033      var swiper = this;
25034      if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) { return; }
25035      var scrollbar = swiper.scrollbar;
25036      var rtl = swiper.rtlTranslate;
25037      var progress = swiper.progress;
25038      var dragSize = scrollbar.dragSize;
25039      var trackSize = scrollbar.trackSize;
25040      var $dragEl = scrollbar.$dragEl;
25041      var $el = scrollbar.$el;
25042      var params = swiper.params.scrollbar;
25043
25044      var newSize = dragSize;
25045      var newPos = (trackSize - dragSize) * progress;
25046      if (rtl) {
25047        newPos = -newPos;
25048        if (newPos > 0) {
25049          newSize = dragSize - newPos;
25050          newPos = 0;
25051        } else if (-newPos + dragSize > trackSize) {
25052          newSize = trackSize + newPos;
25053        }
25054      } else if (newPos < 0) {
25055        newSize = dragSize + newPos;
25056        newPos = 0;
25057      } else if (newPos + dragSize > trackSize) {
25058        newSize = trackSize - newPos;
25059      }
25060      if (swiper.isHorizontal()) {
25061        if (Support.transforms3d) {
25062          $dragEl.transform(("translate3d(" + newPos + "px, 0, 0)"));
25063        } else {
25064          $dragEl.transform(("translateX(" + newPos + "px)"));
25065        }
25066        $dragEl[0].style.width = newSize + "px";
25067      } else {
25068        if (Support.transforms3d) {
25069          $dragEl.transform(("translate3d(0px, " + newPos + "px, 0)"));
25070        } else {
25071          $dragEl.transform(("translateY(" + newPos + "px)"));
25072        }
25073        $dragEl[0].style.height = newSize + "px";
25074      }
25075      if (params.hide) {
25076        clearTimeout(swiper.scrollbar.timeout);
25077        $el[0].style.opacity = 1;
25078        swiper.scrollbar.timeout = setTimeout(function () {
25079          $el[0].style.opacity = 0;
25080          $el.transition(400);
25081        }, 1000);
25082      }
25083    },
25084    setTransition: function setTransition(duration) {
25085      var swiper = this;
25086      if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) { return; }
25087      swiper.scrollbar.$dragEl.transition(duration);
25088    },
25089    updateSize: function updateSize() {
25090      var swiper = this;
25091      if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) { return; }
25092
25093      var scrollbar = swiper.scrollbar;
25094      var $dragEl = scrollbar.$dragEl;
25095      var $el = scrollbar.$el;
25096
25097      $dragEl[0].style.width = '';
25098      $dragEl[0].style.height = '';
25099      var trackSize = swiper.isHorizontal() ? $el[0].offsetWidth : $el[0].offsetHeight;
25100
25101      var divider = swiper.size / swiper.virtualSize;
25102      var moveDivider = divider * (trackSize / swiper.size);
25103      var dragSize;
25104      if (swiper.params.scrollbar.dragSize === 'auto') {
25105        dragSize = trackSize * divider;
25106      } else {
25107        dragSize = parseInt(swiper.params.scrollbar.dragSize, 10);
25108      }
25109
25110      if (swiper.isHorizontal()) {
25111        $dragEl[0].style.width = dragSize + "px";
25112      } else {
25113        $dragEl[0].style.height = dragSize + "px";
25114      }
25115
25116      if (divider >= 1) {
25117        $el[0].style.display = 'none';
25118      } else {
25119        $el[0].style.display = '';
25120      }
25121      if (swiper.params.scrollbar.hide) {
25122        $el[0].style.opacity = 0;
25123      }
25124      Utils.extend(scrollbar, {
25125        trackSize: trackSize,
25126        divider: divider,
25127        moveDivider: moveDivider,
25128        dragSize: dragSize,
25129      });
25130      scrollbar.$el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](swiper.params.scrollbar.lockClass);
25131    },
25132    
25132setDragPosition: function setDragPosition(e) {
25133      var swiper = this;
25134      var scrollbar = swiper.scrollbar;
25135      var rtl = swiper.rtlTranslate;
25136      var $el = scrollbar.$el;
25137      var dragSize = scrollbar.dragSize;
25138      var trackSize = scrollbar.trackSize;
25139
25140      var pointerPosition;
25141      if (swiper.isHorizontal()) {
25142        pointerPosition = ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageX : e.pageX || e.clientX);
25143      } else {
25144        pointerPosition = ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageY : e.pageY || e.clientY);
25145      }
25146      var positionRatio;
25147      positionRatio = ((pointerPosition) - $el.offset()[swiper.isHorizontal() ? 'left' : 'top'] - (dragSize / 2)) / (trackSize - dragSize);
25148      positionRatio = Math.max(Math.min(positionRatio, 1), 0);
25149      if (rtl) {
25150        positionRatio = 1 - positionRatio;
25151      }
25152
25153      var position = swiper.minTranslate() + ((swiper.maxTranslate() - swiper.minTranslate()) * positionRatio);
25154
25155      swiper.updateProgress(position);
25156      swiper.setTranslate(position);
25157      swiper.updateActiveIndex();
25158      swiper.updateSlidesClasses();
25159    },
25160    onDragStart: function onDragStart(e) {
25161      var swiper = this;
25162      var params = swiper.params.scrollbar;
25163      var scrollbar = swiper.scrollbar;
25164      var $wrapperEl = swiper.$wrapperEl;
25165      var $el = scrollbar.$el;
25166      var $dragEl = scrollbar.$dragEl;
25167      swiper.scrollbar.isTouched = true
vendor: 6,013 bytes, lines 25167-25322
25167;
25168      e.preventDefault();
25169      e.stopPropagation();
25170
25171      $wrapperEl.transition(100);
25172      $dragEl.transition(100);
25173      scrollbar.setDragPosition(e);
25174
25175      clearTimeout(swiper.scrollbar.dragTimeout);
25176
25177      $el.transition(0);
25178      if (params.hide) {
25179        $el.css('opacity', 1);
25180      }
25181      swiper.emit('scrollbarDragStart', e);
25182    },
25183    onDragMove: function onDragMove(e) {
25184      var swiper = this;
25185      var scrollbar = swiper.scrollbar;
25186      var $wrapperEl = swiper.$wrapperEl;
25187      var $el = scrollbar.$el;
25188      var $dragEl = scrollbar.$dragEl;
25189
25190      if (!swiper.scrollbar.isTouched) { return; }
25191      if (e.preventDefault) { e.preventDefault(); }
25192      else { e.returnValue = false; }
25193      scrollbar.setDragPosition(e);
25194      $wrapperEl.transition(0);
25195      $el.transition(0);
25196      $dragEl.transition(0);
25197      swiper.emit('scrollbarDragMove', e);
25198    },
25199    onDragEnd: function onDragEnd(e) {
25200      var swiper = this;
25201
25202      var params = swiper.params.scrollbar;
25203      var scrollbar = swiper.scrollbar;
25204      var $el = scrollbar.$el;
25205
25206      if (!swiper.scrollbar.isTouched) { return; }
25207      swiper.scrollbar.isTouched = false;
25208      if (params.hide) {
25209        clearTimeout(swiper.scrollbar.dragTimeout);
25210        swiper.scrollbar.dragTimeout = Utils.nextTick(function () {
25211          $el.css('opacity', 0);
25212          $el.transition(400);
25213        }, 1000);
25214      }
25215      swiper.emit('scrollbarDragEnd', e);
25216      if (params.snapOnRelease) {
25217        swiper.slideToClosest();
25218      }
25219    },
25220    enableDraggable: function enableDraggable() {
25221      var swiper = this;
25222      if (!swiper.params.scrollbar.el) { return; }
25223      var scrollbar = swiper.scrollbar;
25224      var touchEventsTouch = swiper.touchEventsTouch;
25225      var touchEventsDesktop = swiper.touchEventsDesktop;
25226      var params = swiper.params;
25227      var $el = scrollbar.$el;
25228      var target = $el[0];
25229      var activeListener = Support.passiveListener && params.passiveListeners ? { passive: false, capture: false } : false;
25230      var passiveListener = Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
25231      if (!Support.touch) {
25232        target.addEventListener(touchEventsDesktop.start, swiper.scrollbar.onDragStart, activeListener);
25233        doc.addEventListener(touchEventsDesktop.move, swiper.scrollbar.onDragMove, activeListener);
25234        doc.addEventListener(touchEventsDesktop.end, swiper.scrollbar.onDragEnd, passiveListener);
25235      } else {
25236        target.addEventListener(touchEventsTouch.start, swiper.scrollbar.onDragStart, activeListener);
25237        target.addEventListener(touchEventsTouch.move, swiper.scrollbar.onDragMove, activeListener);
25238        target.addEventListener(touchEventsTouch.end, swiper.scrollbar.onDragEnd, passiveListener);
25239      }
25240    },
25241    disableDraggable: function disableDraggable() {
25242      var swiper = this;
25243      if (!swiper.params.scrollbar.el) { return; }
25244      var scrollbar = swiper.scrollbar;
25245      var touchEventsTouch = swiper.touchEventsTouch;
25246      var touchEventsDesktop = swiper.touchEventsDesktop;
25247      var params = swiper.params;
25248      var $el = scrollbar.$el;
25249      var target = $el[0];
25250      var activeListener = Support.passiveListener && params.passiveListeners ? { passive: false, capture: false } : false;
25251      var passiveListener = Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
25252      if (!Support.touch) {
25253        target.removeEventListener(touchEventsDesktop.start, swiper.scrollbar.onDragStart, activeListener);
25254        doc.removeEventListener(touchEventsDesktop.move, swiper.scrollbar.onDragMove, activeListener);
25255        doc.removeEventListener(touchEventsDesktop.end, swiper.scrollbar.onDragEnd, passiveListener);
25256      } else {
25257        target.removeEventListener(touchEventsTouch.start, swiper.scrollbar.onDragStart, activeListener);
25258        target.removeEventListener(touchEventsTouch.move, swiper.scrollbar.onDragMove, activeListener);
25259        target.removeEventListener(touchEventsTouch.end, swiper.scrollbar.onDragEnd, passiveListener);
25260      }
25261    },
25262    init: function init() {
25263      var swiper = this;
25264      if (!swiper.params.scrollbar.el) { return; }
25265      var scrollbar = swiper.scrollbar;
25266      var $swiperEl = swiper.$el;
25267      var params = swiper.params.scrollbar;
25268
25269      var $el = $(params.el);
25270      if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1 && $swiperEl.find(params.el).length === 1) {
25271        $el = $swiperEl.find(params.el);
25272      }
25273
25274      var $dragEl = $el.find(("." + (swiper.params.scrollbar.dragClass)));
25275      if ($dragEl.length === 0) {
25276        $dragEl = $(("<div class=\"" + (swiper.params.scrollbar.dragClass) + "\"></div>"));
25277        $el.append($dragEl);
25278      }
25279
25280      Utils.extend(scrollbar, {
25281        $el: $el,
25282        el: $el[0],
25283        $dragEl: $dragEl,
25284        dragEl: $dragEl[0],
25285      });
25286
25287      if (params.draggable) {
25288        scrollbar.enableDraggable();
25289      }
25290    },
25291    destroy: function destroy() {
25292      var swiper = this;
25293      swiper.scrollbar.disableDraggable();
25294    },
25295  };
25296
25297  var Scrollbar$1 = {
25298    name: 'scrollbar',
25299    params: {
25300      scrollbar: {
25301        el: null,
25302        dragSize: 'auto',
25303        hide: false,
25304        draggable: false,
25305        snapOnRelease: true,
25306        lockClass: 'swiper-scrollbar-lock',
25307        dragClass: 'swiper-scrollbar-drag',
25308      },
25309    },
25310    create: function create() {
25311      var swiper = this;
25312      Utils.extend(swiper, {
25313        scrollbar: {
25314          init: Scrollbar.init.bind(swiper),
25315          destroy: Scrollbar.destroy.bind(swiper),
25316          updateSize: Scrollbar.updateSize.bind(swiper),
25317          setTranslate: Scrollbar.setTranslate.bind(swiper),
25318          setTransition: Scrollbar.setTransition.bind(swiper),
25319          enableDraggable: Scrollbar.enableDraggable.bind(swiper),
25320          disableDraggable: Scrollbar.disableDraggable.bind(swiper),
25321          setDragPosition: Scrollbar.setDragPosition.bind(swiper),
25322          
vendor: 3,940 bytes, lines 25322-25439
25322onDragStart: Scrollbar.onDragStart.bind(swiper),
25323          onDragMove: Scrollbar.onDragMove.bind(swiper),
25324          onDragEnd: Scrollbar.onDragEnd.bind(swiper),
25325          isTouched: false,
25326          timeout: null,
25327          dragTimeout: null,
25328        },
25329      });
25330    },
25331    on: {
25332      init: function init() {
25333        var swiper = this;
25334        swiper.scrollbar.init();
25335        swiper.scrollbar.updateSize();
25336        swiper.scrollbar.setTranslate();
25337      },
25338      update: function update() {
25339        var swiper = this;
25340        swiper.scrollbar.updateSize();
25341      },
25342      resize: function resize() {
25343        var swiper = this;
25344        swiper.scrollbar.updateSize();
25345      },
25346      observerUpdate: function observerUpdate() {
25347        var swiper = this;
25348        swiper.scrollbar.updateSize();
25349      },
25350      setTranslate: function setTranslate() {
25351        var swiper = this;
25352        swiper.scrollbar.setTranslate();
25353      },
25354      setTransition: function setTransition(duration) {
25355        var swiper = this;
25356        swiper.scrollbar.setTransition(duration);
25357      },
25358      destroy: function destroy() {
25359        var swiper = this;
25360        swiper.scrollbar.destroy();
25361      },
25362    },
25363  };
25364
25365  var Parallax = {
25366    setTransform: function setTransform(el, progress) {
25367      var swiper = this;
25368      var rtl = swiper.rtl;
25369
25370      var $el = $(el);
25371      var rtlFactor = rtl ? -1 : 1;
25372
25373      var p = $el.attr('data-swiper-parallax') || '0';
25374      var x = $el.attr('data-swiper-parallax-x');
25375      var y = $el.attr('data-swiper-parallax-y');
25376      var scale = $el.attr('data-swiper-parallax-scale');
25377      var opacity = $el.attr('data-swiper-parallax-opacity');
25378
25379      if (x || y) {
25380        x = x || '0';
25381        y = y || '0';
25382      } else if (swiper.isHorizontal()) {
25383        x = p;
25384        y = '0';
25385      } else {
25386        y = p;
25387        x = '0';
25388      }
25389
25390      if ((x).indexOf('%') >= 0) {
25391        x = (parseInt(x, 10) * progress * rtlFactor) + "%";
25392      } else {
25393        x = (x * progress * rtlFactor) + "px";
25394      }
25395      if ((y).indexOf('%') >= 0) {
25396        y = (parseInt(y, 10) * progress) + "%";
25397      } else {
25398        y = (y * progress) + "px";
25399      }
25400
25401      if (typeof opacity !== 'undefined' && opacity !== null) {
25402        var currentOpacity = opacity - ((opacity - 1) * (1 - Math.abs(progress)));
25403        $el[0].style.opacity = currentOpacity;
25404      }
25405      if (typeof scale === 'undefined' || scale === null) {
25406        $el.transform(("translate3d(" + x + ", " + y + ", 0px)"));
25407      } else {
25408        var currentScale = scale - ((scale - 1) * (1 - Math.abs(progress)));
25409        $el.transform(("translate3d(" + x + ", " + y + ", 0px) scale(" + currentScale + ")"));
25410      }
25411    },
25412    setTranslate: function setTranslate() {
25413      var swiper = this;
25414      var $el = swiper.$el;
25415      var slides = swiper.slides;
25416      var progress = swiper.progress;
25417      var snapGrid = swiper.snapGrid;
25418      $el.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]')
25419        .each(function (index, el) {
25420          swiper.parallax.setTransform(el, progress);
25421        });
25422      slides.each(function (slideIndex, slideEl) {
25423        var slideProgress = slideEl.progress;
25424        if (swiper.params.slidesPerGroup > 1 && swiper.params.slidesPerView !== 'auto') {
25425          slideProgress += Math.ceil(slideIndex / 2) - (progress * (snapGrid.length - 1));
25426        }
25427        slideProgress = Math.min(Math.max(slideProgress, -1), 1);
25428        $(slideEl).find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]')
25429          .each(function (index, el) {
25430            swiper.parallax.setTransform(el, slideProgress);
25431          });
25432      });
25433    },
25434    setTransition: function setTransition(duration) {
25435      if ( duration === void 0 ) duration = this.params.speed;
25436
25437      var swiper = this;
25438      var $el = swiper.$el;
25439      $el.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y
vendor: 80,743 bytes, lines 25439-27578
25439]')
25440        .each(function (index, parallaxEl) {
25441          var $parallaxEl = $(parallaxEl);
25442          var parallaxDuration = parseInt($parallaxEl.attr('data-swiper-parallax-duration'), 10) || duration;
25443          if (duration === 0) { parallaxDuration = 0; }
25444          $parallaxEl.transition(parallaxDuration);
25445        });
25446    },
25447  };
25448
25449  var Parallax$1 = {
25450    name: 'parallax',
25451    params: {
25452      parallax: {
25453        enabled: false,
25454      },
25455    },
25456    create: function create() {
25457      var swiper = this;
25458      Utils.extend(swiper, {
25459        parallax: {
25460          setTransform: Parallax.setTransform.bind(swiper),
25461          setTranslate: Parallax.setTranslate.bind(swiper),
25462          setTransition: Parallax.setTransition.bind(swiper),
25463        },
25464      });
25465    },
25466    on: {
25467      beforeInit: function beforeInit() {
25468        var swiper = this;
25469        if (!swiper.params.parallax.enabled) { return; }
25470        swiper.params.watchSlidesProgress = true;
25471        swiper.originalParams.watchSlidesProgress = true;
25472      },
25473      init: function init() {
25474        var swiper = this;
25475        if (!swiper.params.parallax.enabled) { return; }
25476        swiper.parallax.setTranslate();
25477      },
25478      setTranslate: function setTranslate() {
25479        var swiper = this;
25480        if (!swiper.params.parallax.enabled) { return; }
25481        swiper.parallax.setTranslate();
25482      },
25483      setTransition: function setTransition(duration) {
25484        var swiper = this;
25485        if (!swiper.params.parallax.enabled) { return; }
25486        swiper.parallax.setTransition(duration);
25487      },
25488    },
25489  };
25490
25491  var Zoom = {
25492    // Calc Scale From Multi-touches
25493    getDistanceBetweenTouches: function getDistanceBetweenTouches(e) {
25494      if (e.targetTouches.length < 2) { return 1; }
25495      var x1 = e.targetTouches[0].pageX;
25496      var y1 = e.targetTouches[0].pageY;
25497      var x2 = e.targetTouches[1].pageX;
25498      var y2 = e.targetTouches[1].pageY;
25499      var distance = Math.sqrt((Math.pow( (x2 - x1), 2 )) + (Math.pow( (y2 - y1), 2 )));
25500      return distance;
25501    },
25502    // Events
25503    onGestureStart: function onGestureStart(e) {
25504      var swiper = this;
25505      var params = swiper.params.zoom;
25506      var zoom = swiper.zoom;
25507      var gesture = zoom.gesture;
25508      zoom.fakeGestureTouched = false;
25509      zoom.fakeGestureMoved = false;
25510      if (!Support.gestures) {
25511        if (e.type !== 'touchstart' || (e.type === 'touchstart' && e.targetTouches.length < 2)) {
25512          return;
25513        }
25514        zoom.fakeGestureTouched = true;
25515        gesture.scaleStart = Zoom.getDistanceBetweenTouches(e);
25516      }
25517      if (!gesture.$slideEl || !gesture.$slideEl.length) {
25518        gesture.$slideEl = $(e.target).closest('.swiper-slide');
25519        if (gesture.$slideEl.length === 0) { gesture.$slideEl = swiper.slides.eq(swiper.activeIndex); }
25520        gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
25521        gesture.$imageWrapEl = gesture.$imageEl.parent(("." + (params.containerClass)));
25522        gesture.maxRatio = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
25523        if (gesture.$imageWrapEl.length === 0) {
25524          gesture.$imageEl = undefined;
25525          return;
25526        }
25527      }
25528      gesture.$imageEl.transition(0);
25529      swiper.zoom.isScaling = true;
25530    },
25531    onGestureChange: function onGestureChange(e) {
25532      var swiper = this;
25533      var params = swiper.params.zoom;
25534      var zoom = swiper.zoom;
25535      var gesture = zoom.gesture;
25536      if (!Support.gestures) {
25537        if (e.type !== 'touchmove' || (e.type === 'touchmove' && e.targetTouches.length < 2)) {
25538          return;
25539        }
25540        zoom.fakeGestureMoved = true;
25541        gesture.scaleMove = Zoom.getDistanceBetweenTouches(e);
25542      }
25543      if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25544      if (Support.gestures) {
25545        zoom.scale = e.scale * zoom.currentScale;
25546      } else {
25547        zoom.scale = (gesture.scaleMove / gesture.scaleStart) * zoom.currentScale;
25548      }
25549      if (zoom.scale > gesture.maxRatio) {
25550        zoom.scale = (gesture.maxRatio - 1) + (Math.pow( ((zoom.scale - gesture.maxRatio) + 1), 0.5 ));
25551      }
25552      if (zoom.scale < params.minRatio) {
25553        zoom.scale = (params.minRatio + 1) - (Math.pow( ((params.minRatio - zoom.scale) + 1), 0.5 ));
25554      }
25555      gesture.$imageEl.transform(("translate3d(0,0,0) scale(" + (zoom.scale) + ")"));
25556    },
25557    onGestureEnd: function onGestureEnd(e) {
25558      var swiper = this;
25559      var params = swiper.params.zoom;
25560      var zoom = swiper.zoom;
25561      var gesture = zoom.gesture;
25562      if (!Support.gestures) {
25563        if (!zoom.fakeGestureTouched || !zoom.fakeGestureMoved) {
25564          return;
25565        }
25566        if (e.type !== 'touchend' || (e.type === 'touchend' && e.changedTouches.length < 2 && !Device.android)) {
25567          return;
25568        }
25569        zoom.fakeGestureTouched = false;
25570        zoom.fakeGestureMoved = false;
25571      }
25572      if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25573      zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio);
25574      gesture.$imageEl.transition(swiper.params.speed).transform(("translate3d(0,0,0) scale(" + (zoom.scale) + ")"));
25575      zoom.currentScale = zoom.scale;
25576      zoom.isScaling = false;
25577      if (zoom.scale === 1) { gesture.$slideEl = undefined; }
25578    },
25579    onTouchStart: function onTouchStart(e) {
25580      var swiper = this;
25581      var zoom = swiper.zoom;
25582      var gesture = zoom.gesture;
25583      var image = zoom.image;
25584      if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25585      if (image.isTouched) { return; }
25586      if (Device.android) { e.preventDefault(); }
25587      image.isTouched = true;
25588      image.touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
25589      image.touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
25590    },
25591    onTouchMove: function onTouchMove(e) {
25592      var swiper = this;
25593      var zoom = swiper.zoom;
25594      var gesture = zoom.gesture;
25595      var image = zoom.image;
25596      var velocity = zoom.velocity;
25597      if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25598      swiper.allowClick = false;
25599      if (!image.isTouched || !gesture.$slideEl) { return; }
25600
25601      if (!image.isMoved) {
25602        image.width = gesture.$imageEl[0].offsetWidth;
25603        image.height = gesture.$imageEl[0].offsetHeight;
25604        image.startX = Utils.getTranslate(gesture.$imageWrapEl[0], 'x') || 0;
25605        image.startY = Utils.getTranslate(gesture.$imageWrapEl[0], 'y') || 0;
25606        gesture.slideWidth = gesture.$slideEl[0].offsetWidth;
25607        gesture.slideHeight = gesture.$slideEl[0].offsetHeight;
25608        gesture.$imageWrapEl.transition(0);
25609        if (swiper.rtl) {
25610          image.startX = -image.startX;
25611          image.startY = -image.startY;
25612        }
25613      }
25614      // Define if we need image drag
25615      var scaledWidth = image.width * zoom.scale;
25616      var scaledHeight = image.height * zoom.scale;
25617
25618      if (scaledWidth < gesture.slideWidth && scaledHeight < gesture.slideHeight) { return; }
25619
25620      image.minX = Math.min(((gesture.slideWidth / 2) - (scaledWidth / 2)), 0);
25621      image.maxX = -image.minX;
25622      image.minY = Math.min(((gesture.slideHeight / 2) - (scaledHeight / 2)), 0);
25623      image.maxY = -image.minY;
25624
25625      image.touchesCurrent.x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
25626      image.touchesCurrent.y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
25627
25628      if (!image.isMoved && !zoom.isScaling) {
25629        if (
25630          swiper.isHorizontal()
25631          && (
25632            (Math.floor(image.minX) === Math.floor(image.startX) && image.touchesCurrent.x < image.touchesStart.x)
25633            || (Math.floor(image.maxX) === Math.floor(image.startX) && image.touchesCurrent.x > image.touchesStart.x)
25634          )
25635        ) {
25636          image.isTouched = false;
25637          return;
25638        } if (
25639          !swiper.isHorizontal()
25640          && (
25641            (Math.floor(image.minY) === Math.floor(image.startY) && image.touchesCurrent.y < image.touchesStart.y)
25642            || (Math.floor(image.maxY) === Math.floor(image.startY) && image.touchesCurrent.y > image.touchesStart.y)
25643          )
25644        ) {
25645          image.isTouched = false;
25646          return;
25647        }
25648      }
25649      e.preventDefault();
25650      e.stopPropagation();
25651
25652      image.isMoved = true;
25653      image.currentX = (image.touchesCurrent.x - image.touchesStart.x) + image.startX;
25654      image.currentY = (image.touchesCurrent.y - image.touchesStart.y) + image.startY;
25655
25656      if (image.currentX < image.minX) {
25657        image.currentX = (image.minX + 1) - (Math.pow( ((image.minX - image.currentX) + 1), 0.8 ));
25658      }
25659      if (image.currentX > image.maxX) {
25660        image.currentX = (image.maxX - 1) + (Math.pow( ((image.currentX - image.maxX) + 1), 0.8 ));
25661      }
25662
25663      if (image.currentY < image.minY) {
25664        image.currentY = (image.minY + 1) - (Math.pow( ((image.minY - image.currentY) + 1), 0.8 ));
25665      }
25666      if (image.currentY > image.maxY) {
25667        image.currentY = (image.maxY - 1) + (Math.pow( ((image.currentY - image.maxY) + 1), 0.8 ));
25668      }
25669
25670      // Velocity
25671      if (!velocity.prevPositionX) { velocity.prevPositionX = image.touchesCurrent.x; }
25672      if (!velocity.prevPositionY) { velocity.prevPositionY = image.touchesCurrent.y; }
25673      if (!velocity.prevTime) { velocity.prevTime = Date.now(); }
25674      velocity.x = (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2;
25675      velocity.y = (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2;
25676      if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) { velocity.x = 0; }
25677      if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) { velocity.y = 0; }
25678      velocity.prevPositionX = image.touchesCurrent.x;
25679      velocity.prevPositionY = image.touchesCurrent.y;
25680      velocity.prevTime = Date.now();
25681
25682      gesture.$imageWrapEl.transform(("translate3d(" + (image.currentX) + "px, " + (image.currentY) + "px,0)"));
25683    },
25684    onTouchEnd: function onTouchEnd() {
25685      var swiper = this;
25686      var zoom = swiper.zoom;
25687      var gesture = zoom.gesture;
25688      var image = zoom.image;
25689      var velocity = zoom.velocity;
25690      if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25691      if (!image.isTouched || !image.isMoved) {
25692        image.isTouched = false;
25693        image.isMoved = false;
25694        return;
25695      }
25696      image.isTouched = false;
25697      image.isMoved = false;
25698      var momentumDurationX = 300;
25699      var momentumDurationY = 300;
25700      var momentumDistanceX = velocity.x * momentumDurationX;
25701      var newPositionX = image.currentX + momentumDistanceX;
25702      var momentumDistanceY = velocity.y * momentumDurationY;
25703      var newPositionY = image.currentY + momentumDistanceY;
25704
25705      // Fix duration
25706      if (velocity.x !== 0) { momentumDurationX = Math.abs((newPositionX - image.currentX) / velocity.x); }
25707      if (velocity.y !== 0) { momentumDurationY = Math.abs((newPositionY - image.currentY) / velocity.y); }
25708      var momentumDuration = Math.max(momentumDurationX, momentumDurationY);
25709
25710      image.currentX = newPositionX;
25711      image.currentY = newPositionY;
25712
25713      // Define if we need image drag
25714      var scaledWidth = image.width * zoom.scale;
25715      var scaledHeight = image.height * zoom.scale;
25716      image.minX = Math.min(((gesture.slideWidth / 2) - (scaledWidth / 2)), 0);
25717      image.maxX = -image.minX;
25718      image.minY = Math.min(((gesture.slideHeight / 2) - (scaledHeight / 2)), 0);
25719      image.maxY = -image.minY;
25720      image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX);
25721      image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY);
25722
25723      gesture.$imageWrapEl.transition(momentumDuration).transform(("translate3d(" + (image.currentX) + "px, " + (image.currentY) + "px,0)"));
25724    },
25725    onTransitionEnd: function onTransitionEnd() {
25726      var swiper = this;
25727      var zoom = swiper.zoom;
25728      var gesture = zoom.gesture;
25729      if (gesture.$slideEl && swiper.previousIndex !== swiper.activeIndex) {
25730        gesture.$imageEl.transform('translate3d(0,0,0) scale(1)');
25731        gesture.$imageWrapEl.transform('translate3d(0,0,0)');
25732
25733        zoom.scale = 1;
25734        zoom.currentScale = 1;
25735
25736        gesture.$slideEl = undefined;
25737        gesture.$imageEl = undefined;
25738        gesture.$imageWrapEl = undefined;
25739      }
25740    },
25741    // Toggle Zoom
25742    toggle: function toggle(e) {
25743      var swiper = this;
25744      var zoom = swiper.zoom;
25745
25746      if (zoom.scale && zoom.scale !== 1) {
25747        // Zoom Out
25748        zoom.out();
25749      } else {
25750        // Zoom In
25751        zoom.in(e);
25752      }
25753    },
25754    in: function in$1(e) {
25755      var swiper = this;
25756
25757      var zoom = swiper.zoom;
25758      var params = swiper.params.zoom;
25759      var gesture = zoom.gesture;
25760      var image = zoom.image;
25761
25762      if (!gesture.$slideEl) {
25763        gesture.$slideEl = swiper.clickedSlide ? $(swiper.clickedSlide) : swiper.slides.eq(swiper.activeIndex);
25764        gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
25765        gesture.$imageWrapEl = gesture.$imageEl.parent(("." + (params.containerClass)));
25766      }
25767      if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25768
25769      gesture.$slideEl.addClass(("" + (params.zoomedSlideClass)));
25770
25771      var touchX;
25772      var touchY;
25773      var offsetX;
25774      var offsetY;
25775      var diffX;
25776      var diffY;
25777      var translateX;
25778      var translateY;
25779      var imageWidth;
25780      var imageHeight;
25781      var scaledWidth;
25782      var scaledHeight;
25783      var translateMinX;
25784      var translateMinY;
25785      var translateMaxX;
25786      var translateMaxY;
25787      var slideWidth;
25788      var slideHeight;
25789
25790      if (typeof image.touchesStart.x === 'undefined' && e) {
25791        touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX;
25792        touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY;
25793      } else {
25794        touchX = image.touchesStart.x;
25795        touchY = image.touchesStart.y;
25796      }
25797
25798      zoom.scale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
25799      zoom.currentScale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
25800      if (e) {
25801        slideWidth = gesture.$slideEl[0].offsetWidth;
25802        slideHeight = gesture.$slideEl[0].offsetHeight;
25803        offsetX = gesture.$slideEl.offset().left;
25804        offsetY = gesture.$slideEl.offset().top;
25805        diffX = (offsetX + (slideWidth / 2)) - touchX;
25806        diffY = (offsetY + (slideHeight / 2)) - touchY;
25807
25808        imageWidth = gesture.$imageEl[0].offsetWidth;
25809        imageHeight = gesture.$imageEl[0].offsetHeight;
25810        scaledWidth = imageWidth * zoom.scale;
25811        scaledHeight = imageHeight * zoom.scale;
25812
25813        translateMinX = Math.min(((slideWidth / 2) - (scaledWidth / 2)), 0);
25814        translateMinY = Math.min(((slideHeight / 2) - (scaledHeight / 2)), 0);
25815        translateMaxX = -translateMinX;
25816        translateMaxY = -translateMinY;
25817
25818        translateX = diffX * zoom.scale;
25819        translateY = diffY * zoom.scale;
25820
25821        if (translateX < translateMinX) {
25822          translateX = translateMinX;
25823        }
25824        if (translateX > translateMaxX) {
25825          translateX = translateMaxX;
25826        }
25827
25828        if (translateY < translateMinY) {
25829          translateY = translateMinY;
25830        }
25831        if (translateY > translateMaxY) {
25832          translateY = translateMaxY;
25833        }
25834      } else {
25835        translateX = 0;
25836        translateY = 0;
25837      }
25838      gesture.$imageWrapEl.transition(300).transform(("translate3d(" + translateX + "px, " + translateY + "px,0)"));
25839      gesture.$imageEl.transition(300).transform(("translate3d(0,0,0) scale(" + (zoom.scale) + ")"));
25840    },
25841    out: function out() {
25842      var swiper = this;
25843
25844      var zoom = swiper.zoom;
25845      var params = swiper.params.zoom;
25846      var gesture = zoom.gesture;
25847
25848      if (!gesture.$slideEl) {
25849        gesture.$slideEl = swiper.clickedSlide ? $(swiper.clickedSlide) : swiper.slides.eq(swiper.activeIndex);
25850        gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
25851        gesture.$imageWrapEl = gesture.$imageEl.parent(("." + (params.containerClass)));
25852      }
25853      if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25854
25855      zoom.scale = 1;
25856      zoom.currentScale = 1;
25857      gesture.$imageWrapEl.transition(300).transform('translate3d(0,0,0)');
25858      gesture.$imageEl.transition(300).transform('translate3d(0,0,0) scale(1)');
25859      gesture.$slideEl.removeClass(("" + (params.zoomedSlideClass)));
25860      gesture.$slideEl = undefined;
25861    },
25862    // Attach/Detach Events
25863    enable: function enable() {
25864      var swiper = this;
25865      var zoom = swiper.zoom;
25866      if (zoom.enabled) { return; }
25867      zoom.enabled = true;
25868
25869      var passiveListener = swiper.touchEvents.start === 'touchstart' && Support.passiveListener && swiper.params.passiveListeners ? { passive: true, capture: false } : false;
25870
25871      // Scale image
25872      if (Support.gestures) {
25873        swiper.$wrapperEl.on('gesturestart', '.swiper-slide', zoom.onGestureStart, passiveListener);
25874        swiper.$wrapperEl.on('gesturechange', '.swiper-slide', zoom.onGestureChange, passiveListener);
25875        swiper.$wrapperEl.on('gestureend', '.swiper-slide', zoom.onGestureEnd, passiveListener);
25876      } else if (swiper.touchEvents.start === 'touchstart') {
25877        swiper.$wrapperEl.on(swiper.touchEvents.start, '.swiper-slide', zoom.onGestureStart, passiveListener);
25878        swiper.$wrapperEl.on(swiper.touchEvents.move, '.swiper-slide', zoom.onGestureChange, passiveListener);
25879        swiper.$wrapperEl.on(swiper.touchEvents.end, '.swiper-slide', zoom.onGestureEnd, passiveListener);
25880      }
25881
25882      // Move image
25883      swiper.$wrapperEl.on(swiper.touchEvents.move, ("." + (swiper.params.zoom.containerClass)), zoom.onTouchMove);
25884    },
25885    disable: function disable() {
25886      var swiper = this;
25887      var zoom = swiper.zoom;
25888      if (!zoom.enabled) { return; }
25889
25890      swiper.zoom.enabled = false;
25891
25892      var passiveListener = swiper.touchEvents.start === 'touchstart' && Support.passiveListener && swiper.params.passiveListeners ? { passive: true, capture: false } : false;
25893
25894      // Scale image
25895      if (Support.gestures) {
25896        swiper.$wrapperEl.off('gesturestart', '.swiper-slide', zoom.onGestureStart, passiveListener);
25897        swiper.$wrapperEl.off('gesturechange', '.swiper-slide', zoom.onGestureChange, passiveListener);
25898        swiper.$wrapperEl.off('gestureend', '.swiper-slide', zoom.onGestureEnd, passiveListener);
25899      } else if (swiper.touchEvents.start === 'touchstart') {
25900        swiper.$wrapperEl.off(swiper.touchEvents.start, '.swiper-slide', zoom.onGestureStart, passiveListener);
25901        swiper.$wrapperEl.off(swiper.touchEvents.move, '.swiper-slide', zoom.onGestureChange, passiveListener);
25902        swiper.$wrapperEl.off(swiper.touchEvents.end, '.swiper-slide', zoom.onGestureEnd, passiveListener);
25903      }
25904
25905      // Move image
25906      swiper.$wrapperEl.off(swiper.touchEvents.move, ("." + (swiper.params.zoom.containerClass)), zoom.onTouchMove);
25907    },
25908  };
25909
25910  var Zoom$1 = {
25911    name: 'zoom',
25912    params: {
25913      zoom: {
25914        enabled: false,
25915        maxRatio: 3,
25916        minRatio: 1,
25917        toggle: true,
25918        containerClass: 'swiper-zoom-container',
25919        zoomedSlideClass: 'swiper-slide-zoomed',
25920      },
25921    },
25922    create: function create() {
25923      var swiper = this;
25924      var zoom = {
25925        enabled: false,
25926        scale: 1,
25927        currentScale: 1,
25928        isScaling: false,
25929        gesture: {
25930          $slideEl: undefined,
25931          slideWidth: undefined,
25932          slideHeight: undefined,
25933          $imageEl: undefined,
25934          $imageWrapEl: undefined,
25935          maxRatio: 3,
25936        },
25937        image: {
25938          isTouched: undefined,
25939          isMoved: undefined,
25940          currentX: undefined,
25941          currentY: undefined,
25942          minX: undefined,
25943          minY: undefined,
25944          maxX: undefined,
25945          maxY: undefined,
25946          width: undefined,
25947          height: undefined,
25948          startX: undefined,
25949          startY: undefined,
25950          touchesStart: {},
25951          touchesCurrent: {},
25952        },
25953        velocity: {
25954          x: undefined,
25955          y: undefined,
25956          prevPositionX: undefined,
25957          prevPositionY: undefined,
25958          prevTime: undefined,
25959        },
25960      };
25961
25962      ('onGestureStart onGestureChange onGestureEnd onTouchStart onTouchMove onTouchEnd onTransitionEnd toggle enable disable in out').split(' ').forEach(function (methodName) {
25963        zoom[methodName] = Zoom[methodName].bind(swiper);
25964      });
25965      Utils.extend(swiper, {
25966        zoom: zoom,
25967      });
25968
25969      var scale = 1;
25970      Object.defineProperty(swiper.zoom, 'scale', {
25971        get: function get() {
25972          return scale;
25973        },
25974        set: function set(value) {
25975          if (scale !== value) {
25976            var imageEl = swiper.zoom.gesture.$imageEl ? swiper.zoom.gesture.$imageEl[0] : undefined;
25977            var slideEl = swiper.zoom.gesture.$slideEl ? swiper.zoom.gesture.$slideEl[0] : undefined;
25978            swiper.emit('zoomChange', value, imageEl, slideEl);
25979          }
25980          scale = value;
25981        },
25982      });
25983    },
25984    on: {
25985      init: function init() {
25986        var swiper = this;
25987        if (swiper.params.zoom.enabled) {
25988          swiper.zoom.enable();
25989        }
25990      },
25991      destroy: function destroy() {
25992        var swiper = this;
25993        swiper.zoom.disable();
25994      },
25995      touchStart: function touchStart(e) {
25996        var swiper = this;
25997        if (!swiper.zoom.enabled) { return; }
25998        swiper.zoom.onTouchStart(e);
25999      },
26000      touchEnd: function touchEnd(e) {
26001        var swiper = this;
26002        if (!swiper.zoom.enabled) { return; }
26003        swiper.zoom.onTouchEnd(e);
26004      },
26005      doubleTap: function doubleTap(e) {
26006        var swiper = this;
26007        if (swiper.params.zoom.enabled && swiper.zoom.enabled && swiper.params.zoom.toggle) {
26008          swiper.zoom.toggle(e);
26009        }
26010      },
26011      transitionEnd: function transitionEnd() {
26012        var swiper = this;
26013        if (swiper.zoom.enabled && swiper.params.zoom.enabled) {
26014          swiper.zoom.onTransitionEnd();
26015        }
26016      },
26017    },
26018  };
26019
26020  var Lazy = {
26021    loadInSlide: function loadInSlide(index, loadInDuplicate) {
26022      if ( loadInDuplicate === void 0 ) loadInDuplicate = true;
26023
26024      var swiper = this;
26025      var params = swiper.params.lazy;
26026      if (typeof index === 'undefined') { return; }
26027      if (swiper.slides.length === 0) { return; }
26028      var isVirtual = swiper.virtual && swiper.params.virtual.enabled;
26029
26030      var $slideEl = isVirtual
26031        ? swiper.$wrapperEl.children(("." + (swiper.params.slideClass) + "[data-swiper-slide-index=\"" + index + "\"]"))
26032        : swiper.slides.eq(index);
26033
26034      var $images = $slideEl.find(("." + (params.elementClass) + ":not(." + (params.loadedClass) + "):not(." + (params.loadingClass) + ")"));
26035      if ($slideEl.hasClass(params.elementClass) && !$slideEl.hasClass(params.loadedClass) && !$slideEl.hasClass(params.loadingClass)) {
26036        $images = $images.add($slideEl[0]);
26037      }
26038      if ($images.length === 0) { return; }
26039
26040      $images.each(function (imageIndex, imageEl) {
26041        var $imageEl = $(imageEl);
26042        $imageEl.addClass(params.loadingClass);
26043
26044        var background = $imageEl.attr('data-background');
26045        var src = $imageEl.attr('data-src');
26046        var srcset = $imageEl.attr('data-srcset');
26047        var sizes = $imageEl.attr('data-sizes');
26048
26049        swiper.loadImage($imageEl[0], (src || background), srcset, sizes, false, function () {
26050          if (typeof swiper === 'undefined' || swiper === null || !swiper || (swiper && !swiper.params) || swiper.destroyed) { return; }
26051          if (background) {
26052            $imageEl.css('background-image', ("url(\"" + background + "\")"));
26053            $imageEl.removeAttr('data-background');
26054          } else {
26055            if (srcset) {
26056              $imageEl.attr('srcset', srcset);
26057              $imageEl.removeAttr('data-srcset');
26058            }
26059            if (sizes) {
26060              $imageEl.attr('sizes', sizes);
26061              $imageEl.removeAttr('data-sizes');
26062            }
26063            if (src) {
26064              $imageEl.attr('src', src);
26065              $imageEl.removeAttr('data-src');
26066            }
26067          }
26068
26069          $imageEl.addClass(params.loadedClass).removeClass(params.loadingClass);
26070          $slideEl.find(("." + (params.preloaderClass))).remove();
26071          if (swiper.params.loop && loadInDuplicate) {
26072            var slideOriginalIndex = $slideEl.attr('data-swiper-slide-index');
26073            if ($slideEl.hasClass(swiper.params.slideDuplicateClass)) {
26074              var originalSlide = swiper.$wrapperEl.children(("[data-swiper-slide-index=\"" + slideOriginalIndex + "\"]:not(." + (swiper.params.slideDuplicateClass) + ")"));
26075              swiper.lazy.loadInSlide(originalSlide.index(), false);
26076            } else {
26077              var duplicatedSlide = swiper.$wrapperEl.children(("." + (swiper.params.slideDuplicateClass) + "[data-swiper-slide-index=\"" + slideOriginalIndex + "\"]"));
26078              swiper.lazy.loadInSlide(duplicatedSlide.index(), false);
26079            }
26080          }
26081          swiper.emit('lazyImageReady', $slideEl[0], $imageEl[0]);
26082        });
26083
26084        swiper.emit('lazyImageLoad', $slideEl[0], $imageEl[0]);
26085      });
26086    },
26087    load: function load() {
26088      var swiper = this;
26089      var $wrapperEl = swiper.$wrapperEl;
26090      var swiperParams = swiper.params;
26091      var slides = swiper.slides;
26092      var activeIndex = swiper.activeIndex;
26093      var isVirtual = swiper.virtual && swiperParams.virtual.enabled;
26094      var params = swiperParams.lazy;
26095
26096      var slidesPerView = swiperParams.slidesPerView;
26097      if (slidesPerView === 'auto') {
26098        slidesPerView = 0;
26099      }
26100
26101      function slideExist(index) {
26102        if (isVirtual) {
26103          if ($wrapperEl.children(("." + (swiperParams.slideClass) + "[data-swiper-slide-index=\"" + index + "\"]")).length) {
26104            return true;
26105          }
26106        } else if (slides[index]) { return true; }
26107        return false;
26108      }
26109      function slideIndex(slideEl) {
26110        if (isVirtual) {
26111          return $(slideEl).attr('data-swiper-slide-index');
26112        }
26113        return $(slideEl).index();
26114      }
26115
26116      if (!swiper.lazy.initialImageLoaded) { swiper.lazy.initialImageLoaded = true; }
26117      if (swiper.params.watchSlidesVisibility) {
26118        $wrapperEl.children(("." + (swiperParams.slideVisibleClass))).each(function (elIndex, slideEl) {
26119          var index = isVirtual ? $(slideEl).attr('data-swiper-slide-index') : $(slideEl).index();
26120          swiper.lazy.loadInSlide(index);
26121        });
26122      } else if (slidesPerView > 1) {
26123        for (var i = activeIndex; i < activeIndex + slidesPerView; i += 1) {
26124          if (slideExist(i)) { swiper.lazy.loadInSlide(i); }
26125        }
26126      } else {
26127        swiper.lazy.loadInSlide(activeIndex);
26128      }
26129      if (params.loadPrevNext) {
26130        if (slidesPerView > 1 || (params.loadPrevNextAmount && params.loadPrevNextAmount > 1)) {
26131          var amount = params.loadPrevNextAmount;
26132          var spv = slidesPerView;
26133          var maxIndex = Math.min(activeIndex + spv + Math.max(amount, spv), slides.length);
26134          var minIndex = Math.max(activeIndex - Math.max(spv, amount), 0);
26135          // Next Slides
26136          for (var i$1 = activeIndex + slidesPerView; i$1 < maxIndex; i$1 += 1) {
26137            if (slideExist(i$1)) { swiper.lazy.loadInSlide(i$1); }
26138          }
26139          // Prev Slides
26140          for (var i$2 = minIndex; i$2 < activeIndex; i$2 += 1) {
26141            if (slideExist(i$2)) { swiper.lazy.loadInSlide(i$2); }
26142          }
26143        } else {
26144          var nextSlide = $wrapperEl.children(("." + (swiperParams.slideNextClass)));
26145          if (nextSlide.length > 0) { swiper.lazy.loadInSlide(slideIndex(nextSlide)); }
26146
26147          var prevSlide = $wrapperEl.children(("." + (swiperParams.slidePrevClass)));
26148          if (prevSlide.length > 0) { swiper.lazy.loadInSlide(slideIndex(prevSlide)); }
26149        }
26150      }
26151    },
26152  };
26153
26154  var Lazy$1 = {
26155    name: 'lazy',
26156    params: {
26157      lazy: {
26158        enabled: false,
26159        loadPrevNext: false,
26160        loadPrevNextAmount: 1,
26161        loadOnTransitionStart: false,
26162
26163        elementClass: 'swiper-lazy',
26164        loadingClass: 'swiper-lazy-loading',
26165        loadedClass: 'swiper-lazy-loaded',
26166        preloaderClass: 'swiper-lazy-preloader',
26167      },
26168    },
26169    create: function create() {
26170      var swiper = this;
26171      Utils.extend(swiper, {
26172        lazy: {
26173          initialImageLoaded: false,
26174          load: Lazy.load.bind(swiper),
26175          loadInSlide: Lazy.loadInSlide.bind(swiper),
26176        },
26177      });
26178    },
26179    on: {
26180      beforeInit: function beforeInit() {
26181        var swiper = this;
26182        if (swiper.params.lazy.enabled && swiper.params.preloadImages) {
26183          swiper.params.preloadImages = false;
26184        }
26185      },
26186      init: function init() {
26187        var swiper = this;
26188        if (swiper.params.lazy.enabled && !swiper.params.loop && swiper.params.initialSlide === 0) {
26189          swiper.lazy.load();
26190        }
26191      },
26192      scroll: function scroll() {
26193        var swiper = this;
26194        if (swiper.params.freeMode && !swiper.params.freeModeSticky) {
26195          swiper.lazy.load();
26196        }
26197      },
26198      resize: function resize() {
26199        var swiper = this;
26200        if (swiper.params.lazy.enabled) {
26201          swiper.lazy.load();
26202        }
26203      },
26204      scrollbarDragMove: function scrollbarDragMove() {
26205        var swiper = this;
26206        if (swiper.params.lazy.enabled) {
26207          swiper.lazy.load();
26208        }
26209      },
26210      transitionStart: function transitionStart() {
26211        var swiper = this;
26212        if (swiper.params.lazy.enabled) {
26213          if (swiper.params.lazy.loadOnTransitionStart || (!swiper.params.lazy.loadOnTransitionStart && !swiper.lazy.initialImageLoaded)) {
26214            swiper.lazy.load();
26215          }
26216        }
26217      },
26218      transitionEnd: function transitionEnd() {
26219        var swiper = this;
26220        if (swiper.params.lazy.enabled && !swiper.params.lazy.loadOnTransitionStart) {
26221          swiper.lazy.load();
26222        }
26223      },
26224    },
26225  };
26226
26227  /* eslint no-bitwise: ["error", { "allow": [">>"] }] */
26228
26229  var Controller = {
26230    LinearSpline: function LinearSpline(x, y) {
26231      var binarySearch = (function search() {
26232        var maxIndex;
26233        var minIndex;
26234        var guess;
26235        return function (array, val) {
26236          minIndex = -1;
26237          maxIndex = array.length;
26238          while (maxIndex - minIndex > 1) {
26239            guess = maxIndex + minIndex >> 1;
26240            if (array[guess] <= val) {
26241              minIndex = guess;
26242            } else {
26243              maxIndex = guess;
26244            }
26245          }
26246          return maxIndex;
26247        };
26248      }());
26249      this.x = x;
26250      this.y = y;
26251      this.lastIndex = x.length - 1;
26252      // Given an x value (x2), return the expected y2 value:
26253      // (x1,y1) is the known point before given value,
26254      // (x3,y3) is the known point after given value.
26255      var i1;
26256      var i3;
26257
26258      this.interpolate = function interpolate(x2) {
26259        if (!x2) { return 0; }
26260
26261        // Get the indexes of x1 and x3 (the array indexes before and after given x2):
26262        i3 = binarySearch(this.x, x2);
26263        i1 = i3 - 1;
26264
26265        // We have our indexes i1 & i3, so we can calculate already:
26266        // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1
26267        return (((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1])) + this.y[i1];
26268      };
26269      return this;
26270    },
26271    // xxx: for now i will just save one spline function to to
26272    getInterpolateFunction: function getInterpolateFunction(c) {
26273      var swiper = this;
26274      if (!swiper.controller.spline) {
26275        swiper.controller.spline = swiper.params.loop
26276          ? new Controller.LinearSpline(swiper.slidesGrid, c.slidesGrid)
26277          : new Controller.LinearSpline(swiper.snapGrid, c.snapGrid);
26278      }
26279    },
26280    setTranslate: function setTranslate(setTranslate$1, byController) {
26281      var swiper = this;
26282      var controlled = swiper.controller.control;
26283      var multiplier;
26284      var controlledTranslate;
26285      function setControlledTranslate(c) {
26286        // this will create an Interpolate function based on the snapGrids
26287        // x is the Grid of the scrolled scroller and y will be the controlled scroller
26288        // it makes sense to create this only once and recall it for the interpolation
26289        // the function does a lot of value caching for performance
26290        var translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate;
26291        if (swiper.params.controller.by === 'slide') {
26292          swiper.controller.getInterpolateFunction(c);
26293          // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid
26294          // but it did not work out
26295          controlledTranslate = -swiper.controller.spline.interpolate(-translate);
26296        }
26297
26298        if (!controlledTranslate || swiper.params.controller.by === 'container') {
26299          multiplier = (c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate());
26300          controlledTranslate = ((translate - swiper.minTranslate()) * multiplier) + c.minTranslate();
26301        }
26302
26303        if (swiper.params.controller.inverse) {
26304          controlledTranslate = c.maxTranslate() - controlledTranslate;
26305        }
26306        c.updateProgress(controlledTranslate);
26307        c.setTranslate(controlledTranslate, swiper);
26308        c.updateActiveIndex();
26309        c.updateSlidesClasses();
26310      }
26311      if (Array.isArray(controlled)) {
26312        for (var i = 0; i < controlled.length; i += 1) {
26313          if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
26314            setControlledTranslate(controlled[i]);
26315          }
26316        }
26317      } else if (controlled instanceof Swiper && byController !== controlled) {
26318        setControlledTranslate(controlled);
26319      }
26320    },
26321    setTransition: function setTransition(duration, byController) {
26322      var swiper = this;
26323      var controlled = swiper.controller.control;
26324      var i;
26325      function setControlledTransition(c) {
26326        c.setTransition(duration, swiper);
26327        if (duration !== 0) {
26328          c.transitionStart();
26329          if (c.params.autoHeight) {
26330            Utils.nextTick(function () {
26331              c.updateAutoHeight();
26332            });
26333          }
26334          c.$wrapperEl.transitionEnd(function () {
26335            if (!controlled) { return; }
26336            if (c.params.loop && swiper.params.controller.by === 'slide') {
26337              c.loopFix();
26338            }
26339            c.transitionEnd();
26340          });
26341        }
26342      }
26343      if (Array.isArray(controlled)) {
26344        for (i = 0; i < controlled.length; i += 1) {
26345          if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
26346            setControlledTransition(controlled[i]);
26347          }
26348        }
26349      } else if (controlled instanceof Swiper && byController !== controlled) {
26350        setControlledTransition(controlled);
26351      }
26352    },
26353  };
26354  var Controller$1 = {
26355    name: 'controller',
26356    params: {
26357      controller: {
26358        control: undefined,
26359        inverse: false,
26360        by: 'slide', // or 'container'
26361      },
26362    },
26363    create: function create() {
26364      var swiper = this;
26365      Utils.extend(swiper, {
26366        controller: {
26367          control: swiper.params.controller.control,
26368          getInterpolateFunction: Controller.getInterpolateFunction.bind(swiper),
26369          setTranslate: Controller.setTranslate.bind(swiper),
26370          setTransition: Controller.setTransition.bind(swiper),
26371        },
26372      });
26373    },
26374    on: {
26375      update: function update() {
26376        var swiper = this;
26377        if (!swiper.controller.control) { return; }
26378        if (swiper.controller.spline) {
26379          swiper.controller.spline = undefined;
26380          delete swiper.controller.spline;
26381        }
26382      },
26383      resize: function resize() {
26384        var swiper = this;
26385        if (!swiper.controller.control) { return; }
26386        if (swiper.controller.spline) {
26387          swiper.controller.spline = undefined;
26388          delete swiper.controller.spline;
26389        }
26390      },
26391      observerUpdate: function observerUpdate() {
26392        var swiper = this;
26393        if (!swiper.controller.control) { return; }
26394        if (swiper.controller.spline) {
26395          swiper.controller.spline = undefined;
26396          delete swiper.controller.spline;
26397        }
26398      },
26399      setTranslate: function setTranslate(translate, byController) {
26400        var swiper = this;
26401        if (!swiper.controller.control) { return; }
26402        swiper.controller.setTranslate(translate, byController);
26403      },
26404      setTransition: function setTransition(duration, byController) {
26405        var swiper = this;
26406        if (!swiper.controller.control) { return; }
26407        swiper.controller.setTransition(duration, byController);
26408      },
26409    },
26410  };
26411
26412  var a11y = {
26413    makeElFocusable: function makeElFocusable($el) {
26414      $el.attr('tabIndex', '0');
26415      return $el;
26416    },
26417    addElRole: function addElRole($el, role) {
26418      $el.attr('role', role);
26419      return $el;
26420    },
26421    addElLabel: function addElLabel($el, label) {
26422      $el.attr('aria-label', label);
26423      return $el;
26424    },
26425    disableEl: function disableEl($el) {
26426      $el.attr('aria-disabled', true);
26427      return $el;
26428    },
26429    enableEl: function enableEl($el) {
26430      $el.attr('aria-disabled', false);
26431      return $el;
26432    },
26433    onEnterKey: function onEnterKey(e) {
26434      var swiper = this;
26435      var params = swiper.params.a11y;
26436      if (e.keyCode !== 13) { return; }
26437      var $targetEl = $(e.target);
26438      if (swiper.navigation && swiper.navigation.$nextEl && $targetEl.is(swiper.navigation.$nextEl)) {
26439        if (!(swiper.isEnd && !swiper.params.loop)) {
26440          swiper.slideNext();
26441        }
26442        if (swiper.isEnd) {
26443          swiper.a11y.notify(params.lastSlideMessage);
26444        } else {
26445          swiper.a11y.notify(params.nextSlideMessage);
26446        }
26447      }
26448      if (swiper.navigation && swiper.navigation.$prevEl && $targetEl.is(swiper.navigation.$prevEl)) {
26449        if (!(swiper.isBeginning && !swiper.params.loop)) {
26450          swiper.slidePrev();
26451        }
26452        if (swiper.isBeginning) {
26453          swiper.a11y.notify(params.firstSlideMessage);
26454        } else {
26455          swiper.a11y.notify(params.prevSlideMessage);
26456        }
26457      }
26458      if (swiper.pagination && $targetEl.is(("." + (swiper.params.pagination.bulletClass)))) {
26459        $targetEl[0].click();
26460      }
26461    },
26462    notify: function notify(message) {
26463      var swiper = this;
26464      var notification = swiper.a11y.liveRegion;
26465      if (notification.length === 0) { return; }
26466      notification.html('');
26467      notification.html(message);
26468    },
26469    updateNavigation: function updateNavigation() {
26470      var swiper = this;
26471
26472      if (swiper.params.loop) { return; }
26473      var ref = swiper.navigation;
26474      var $nextEl = ref.$nextEl;
26475      var $prevEl = ref.$prevEl;
26476
26477      if ($prevEl && $prevEl.length > 0) {
26478        if (swiper.isBeginning) {
26479          swiper.a11y.disableEl($prevEl);
26480        } else {
26481          swiper.a11y.enableEl($prevEl);
26482        }
26483      }
26484      if ($nextEl && $nextEl.length > 0) {
26485        if (swiper.isEnd) {
26486          swiper.a11y.disableEl($nextEl);
26487        } else {
26488          swiper.a11y.enableEl($nextEl);
26489        }
26490      }
26491    },
26492    updatePagination: function updatePagination() {
26493      var swiper = this;
26494      var params = swiper.params.a11y;
26495      if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
26496        swiper.pagination.bullets.each(function (bulletIndex, bulletEl) {
26497          var $bulletEl = $(bulletEl);
26498          swiper.a11y.makeElFocusable($bulletEl);
26499          swiper.a11y.addElRole($bulletEl, 'button');
26500          swiper.a11y.addElLabel($bulletEl, params.paginationBulletMessage.replace(/{{index}}/, $bulletEl.index() + 1));
26501        });
26502      }
26503    },
26504    init: function init() {
26505      var swiper = this;
26506
26507      swiper.$el.append(swiper.a11y.liveRegion);
26508
26509      // Navigation
26510      var params = swiper.params.a11y;
26511      var $nextEl;
26512      var $prevEl;
26513      if (swiper.navigation && swiper.navigation.$nextEl) {
26514        $nextEl = swiper.navigation.$nextEl;
26515      }
26516      if (swiper.navigation && swiper.navigation.$prevEl) {
26517        $prevEl = swiper.navigation.$prevEl;
26518      }
26519      if ($nextEl) {
26520        swiper.a11y.makeElFocusable($nextEl);
26521        swiper.a11y.addElRole($nextEl, 'button');
26522        swiper.a11y.addElLabel($nextEl, params.nextSlideMessage);
26523        $nextEl.on('keydown', swiper.a11y.onEnterKey);
26524      }
26525      if ($prevEl) {
26526        swiper.a11y.makeElFocusable($prevEl);
26527        swiper.a11y.addElRole($prevEl, 'button');
26528        swiper.a11y.addElLabel($prevEl, params.prevSlideMessage);
26529        $prevEl.on('keydown', swiper.a11y.onEnterKey);
26530      }
26531
26532      // Pagination
26533      if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
26534        swiper.pagination.$el.on('keydown', ("." + (swiper.params.pagination.bulletClass)), swiper.a11y.onEnterKey);
26535      }
26536    },
26537    destroy: function destroy() {
26538      var swiper = this;
26539      if (swiper.a11y.liveRegion && swiper.a11y.liveRegion.length > 0) { swiper.a11y.liveRegion.remove(); }
26540
26541      var $nextEl;
26542      var $prevEl;
26543      if (swiper.navigation && swiper.navigation.$nextEl) {
26544        $nextEl = swiper.navigation.$nextEl;
26545      }
26546      if (swiper.navigation && swiper.navigation.$prevEl) {
26547        $prevEl = swiper.navigation.$prevEl;
26548      }
26549      if ($nextEl) {
26550        $nextEl.off('keydown', swiper.a11y.onEnterKey);
26551      }
26552      if ($prevEl) {
26553        $prevEl.off('keydown', swiper.a11y.onEnterKey);
26554      }
26555
26556      // Pagination
26557      if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
26558        swiper.pagination.$el.off('keydown', ("." + (swiper.params.pagination.bulletClass)), swiper.a11y.onEnterKey);
26559      }
26560    },
26561  };
26562  var A11y = {
26563    name: 'a11y',
26564    params: {
26565      a11y: {
26566        enabled: true,
26567        notificationClass: 'swiper-notification',
26568        prevSlideMessage: 'Previous slide',
26569        nextSlideMessage: 'Next slide',
26570        firstSlideMessage: 'This is the first slide',
26571        lastSlideMessage: 'This is the last slide',
26572        paginationBulletMessage: 'Go to slide {{index}}',
26573      },
26574    },
26575    create: function create() {
26576      var swiper = this;
26577      Utils.extend(swiper, {
26578        a11y: {
26579          liveRegion: $(("<span class=\"" + (swiper.params.a11y.notificationClass) + "\" aria-live=\"assertive\" aria-atomic=\"true\"></span>")),
26580        },
26581      });
26582      Object.keys(a11y).forEach(function (methodName) {
26583        swiper.a11y[methodName] = a11y[methodName].bind(swiper);
26584      });
26585    },
26586    on: {
26587      init: function init() {
26588        var swiper = this;
26589        if (!swiper.params.a11y.enabled) { return; }
26590        swiper.a11y.init();
26591        swiper.a11y.updateNavigation();
26592      },
26593      toEdge: function toEdge() {
26594        var swiper = this;
26595        if (!swiper.params.a11y.enabled) { return; }
26596        swiper.a11y.updateNavigation();
26597      },
26598      fromEdge: function fromEdge() {
26599        var swiper = this;
26600        if (!swiper.params.a11y.enabled) { return; }
26601        swiper.a11y.updateNavigation();
26602      },
26603      paginationUpdate: function paginationUpdate() {
26604        var swiper = this;
26605        if (!swiper.params.a11y.enabled) { return; }
26606        swiper.a11y.updatePagination();
26607      },
26608      destroy: function destroy() {
26609        var swiper = this;
26610        if (!swiper.params.a11y.enabled) { return; }
26611        swiper.a11y.destroy();
26612      },
26613    },
26614  };
26615
26616  var History = {
26617    init: function init() {
26618      var swiper = this;
26619      if (!swiper.params.history) { return; }
26620      if (!win.history || !win.history.pushState) {
26621        swiper.params.history.enabled = false;
26622        swiper.params.hashNavigation.enabled = true;
26623        return;
26624      }
26625      var history = swiper.history;
26626      history.initialized = true;
26627      history.paths = History.getPathValues();
26628      if (!history.paths.key && !history.paths.value) { return; }
26629      history.scrollToSlide(0, history.paths.value, swiper.params.runCallbacksOnInit);
26630      if (!swiper.params.history.replaceState) {
26631        win.addEventListener('popstate', swiper.history.setHistoryPopState);
26632      }
26633    },
26634    destroy: function destroy() {
26635      var swiper = this;
26636      if (!swiper.params.history.replaceState) {
26637        win.removeEventListener('popstate', swiper.history.setHistoryPopState);
26638      }
26639    },
26640    setHistoryPopState: function setHistoryPopState() {
26641      var swiper = this;
26642      swiper.history.paths = History.getPathValues();
26643      swiper.history.scrollToSlide(swiper.params.speed, swiper.history.paths.value, false);
26644    },
26645    getPathValues: function getPathValues() {
26646      var pathArray = win.location.pathname.slice(1).split('/').filter(function (part) { return part !== ''; });
26647      var total = pathArray.length;
26648      var key = pathArray[total - 2];
26649      var value = pathArray[total - 1];
26650      return { key: key, value: value };
26651    },
26652    setHistory: function setHistory(key, index) {
26653      var swiper = this;
26654      if (!swiper.history.initialized || !swiper.params.history.enabled) { return; }
26655      var slide = swiper.slides.eq(index);
26656      var value = History.slugify(slide.attr('data-history'));
26657      if (!win.location.pathname.includes(key)) {
26658        value = key + "/" + value;
26659      }
26660      var currentState = win.history.state;
26661      if (currentState && currentState.value === value) {
26662        return;
26663      }
26664      if (swiper.params.history.replaceState) {
26665        win.history.replaceState({ value: value }, null, value);
26666      } else {
26667        win.history.pushState({ value: value }, null, value);
26668      }
26669    },
26670    slugify: function slugify(text) {
26671      return text.toString()
26672        .replace(/\s+/g, '-')
26673        .replace(/[^\w-]+/g, '')
26674        .replace(/--+/g, '-')
26675        .replace(/^-+/, '')
26676        .replace(/-+$/, '');
26677    },
26678    scrollToSlide: function scrollToSlide(speed, value, runCallbacks) {
26679      var swiper = this;
26680      if (value) {
26681        for (var i = 0, length = swiper.slides.length; i < length; i += 1) {
26682          var slide = swiper.slides.eq(i);
26683          var slideHistory = History.slugify(slide.attr('data-history'));
26684          if (slideHistory === value && !slide.hasClass(swiper.params.slideDuplicateClass)) {
26685            var index = slide.index();
26686            swiper.slideTo(index, speed, runCallbacks);
26687          }
26688        }
26689      } else {
26690        swiper.slideTo(0, speed, runCallbacks);
26691      }
26692    },
26693  };
26694
26695  var History$1 = {
26696    name: 'history',
26697    params: {
26698      history: {
26699        enabled: false,
26700        replaceState: false,
26701        key: 'slides',
26702      },
26703    },
26704    create: function create() {
26705      var swiper = this;
26706      Utils.extend(swiper, {
26707        history: {
26708          init: History.init.bind(swiper),
26709          setHistory: History.setHistory.bind(swiper),
26710          setHistoryPopState: History.setHistoryPopState.bind(swiper),
26711          scrollToSlide: History.scrollToSlide.bind(swiper),
26712          destroy: History.destroy.bind(swiper),
26713        },
26714      });
26715    },
26716    on: {
26717      init: function init() {
26718        var swiper = this;
26719        if (swiper.params.history.enabled) {
26720          swiper.history.init();
26721        }
26722      },
26723      destroy: function destroy() {
26724        var swiper = this;
26725        if (swiper.params.history.enabled) {
26726          swiper.history.destroy();
26727        }
26728      },
26729      transitionEnd: function transitionEnd() {
26730        var swiper = this;
26731        if (swiper.history.initialized) {
26732          swiper.history.setHistory(swiper.params.history.key, swiper.activeIndex);
26733        }
26734      },
26735    },
26736  };
26737
26738  var HashNavigation = {
26739    onHashCange: function onHashCange() {
26740      var swiper = this;
26741      var newHash = doc.location.hash.replace('#', '');
26742      var activeSlideHash = swiper.slides.eq(swiper.activeIndex).attr('data-hash');
26743      if (newHash !== activeSlideHash) {
26744        var newIndex = swiper.$wrapperEl.children(("." + (swiper.params.slideClass) + "[data-hash=\"" + newHash + "\"]")).index();
26745        if (typeof newIndex === 'undefined') { return; }
26746        swiper.slideTo(newIndex);
26747      }
26748    },
26749    setHash: function setHash() {
26750      var swiper = this;
26751      if (!swiper.hashNavigation.initialized || !swiper.params.hashNavigation.enabled) { return; }
26752      if (swiper.params.hashNavigation.replaceState && win.history && win.history.replaceState) {
26753        win.history.replaceState(null, null, (("#" + (swiper.slides.eq(swiper.activeIndex).attr('data-hash'))) || ''));
26754      } else {
26755        var slide = swiper.slides.eq(swiper.activeIndex);
26756        var hash = slide.attr('data-hash') || slide.attr('data-history');
26757        doc.location.hash = hash || '';
26758      }
26759    },
26760    init: function init() {
26761      var swiper = this;
26762      if (!swiper.params.hashNavigation.enabled || (swiper.params.history && swiper.params.history.enabled)) { return; }
26763      swiper.hashNavigation.initialized = true;
26764      var hash = doc.location.hash.replace('#', '');
26765      if (hash) {
26766        var speed = 0;
26767        for (var i = 0, length = swiper.slides.length; i < length; i += 1) {
26768          var slide = swiper.slides.eq(i);
26769          var slideHash = slide.attr('data-hash') || slide.attr('data-history');
26770          if (slideHash === hash && !slide.hasClass(swiper.params.slideDuplicateClass)) {
26771            var index = slide.index();
26772            swiper.slideTo(index, speed, swiper.params.runCallbacksOnInit, true);
26773          }
26774        }
26775      }
26776      if (swiper.params.hashNavigation.watchState) {
26777        $(win).on('hashchange', swiper.hashNavigation.onHashCange);
26778      }
26779    },
26780    destroy: function destroy() {
26781      var swiper = this;
26782      if (swiper.params.hashNavigation.watchState) {
26783        $(win).off('hashchange', swiper.hashNavigation.onHashCange);
26784      }
26785    },
26786  };
26787  var HashNavigation$1 = {
26788    name: 'hash-navigation',
26789    params: {
26790      hashNavigation: {
26791        enabled: false,
26792        replaceState: false,
26793        watchState: false,
26794      },
26795    },
26796    create: function create() {
26797      var swiper = this;
26798      Utils.extend(swiper, {
26799        hashNavigation: {
26800          initialized: false,
26801          init: HashNavigation.init.bind(swiper),
26802          destroy: HashNavigation.destroy.bind(swiper),
26803          setHash: HashNavigation.setHash.bind(swiper),
26804          onHashCange: HashNavigation.onHashCange.bind(swiper),
26805        },
26806      });
26807    },
26808    on: {
26809      init: function init() {
26810        var swiper = this;
26811        if (swiper.params.hashNavigation.enabled) {
26812          swiper.hashNavigation.init();
26813        }
26814      },
26815      destroy: function destroy() {
26816        var swiper = this;
26817        if (swiper.params.hashNavigation.enabled) {
26818          swiper.hashNavigation.destroy();
26819        }
26820      },
26821      transitionEnd: function transitionEnd() {
26822        var swiper = this;
26823        if (swiper.hashNavigation.initialized) {
26824          swiper.hashNavigation.setHash();
26825        }
26826      },
26827    },
26828  };
26829
26830  /* eslint no-underscore-dangle: "off" */
26831
26832  var Autoplay = {
26833    run: function run() {
26834      var swiper = this;
26835      var $activeSlideEl = swiper.slides.eq(swiper.activeIndex);
26836      var delay = swiper.params.autoplay.delay;
26837      if ($activeSlideEl.attr('data-swiper-autoplay')) {
26838        delay = $activeSlideEl.attr('data-swiper-autoplay') || swiper.params.autoplay.delay;
26839      }
26840      swiper.autoplay.timeout = Utils.nextTick(function () {
26841        if (swiper.params.autoplay.reverseDirection) {
26842          if (swiper.params.loop) {
26843            swiper.loopFix();
26844            swiper.slidePrev(swiper.params.speed, true, true);
26845            swiper.emit('autoplay');
26846          } else if (!swiper.isBeginning) {
26847            swiper.slidePrev(swiper.params.speed, true, true);
26848            swiper.emit('autoplay');
26849          } else if (!swiper.params.autoplay.stopOnLastSlide) {
26850            swiper.slideTo(swiper.slides.length - 1, swiper.params.speed, true, true);
26851            swiper.emit('autoplay');
26852          } else {
26853            swiper.autoplay.stop();
26854          }
26855        } else if (swiper.params.loop) {
26856          swiper.loopFix();
26857          swiper.slideNext(swiper.params.speed, true, true);
26858          swiper.emit('autoplay');
26859        } else if (!swiper.isEnd) {
26860          swiper.slideNext(swiper.params.speed, true, true);
26861          swiper.emit('autoplay');
26862        } else if (!swiper.params.autoplay.stopOnLastSlide) {
26863          swiper.slideTo(0, swiper.params.speed, true, true);
26864          swiper.emit('autoplay');
26865        } else {
26866          swiper.autoplay.stop();
26867        }
26868      }, delay);
26869    },
26870    start: function start() {
26871      var swiper = this;
26872      if (typeof swiper.autoplay.timeout !== 'undefined') { return false; }
26873      if (swiper.autoplay.running) { return false; }
26874      swiper.autoplay.running = true;
26875      swiper.emit('autoplayStart');
26876      swiper.autoplay.run();
26877      return true;
26878    },
26879    stop: function stop() {
26880      var swiper = this;
26881      if (!swiper.autoplay.running) { return false; }
26882      if (typeof swiper.autoplay.timeout === 'undefined') { return false; }
26883
26884      if (swiper.autoplay.timeout) {
26885        clearTimeout(swiper.autoplay.timeout);
26886        swiper.autoplay.timeout = undefined;
26887      }
26888      swiper.autoplay.running = false;
26889      swiper.emit('autoplayStop');
26890      return true;
26891    },
26892    pause: function pause(speed) {
26893      var swiper = this;
26894      if (!swiper.autoplay.running) { return; }
26895      if (swiper.autoplay.paused) { return; }
26896      if (swiper.autoplay.timeout) { clearTimeout(swiper.autoplay.timeout); }
26897      swiper.autoplay.paused = true;
26898      if (speed === 0 || !swiper.params.autoplay.waitForTransition) {
26899        swiper.autoplay.paused = false;
26900        swiper.autoplay.run();
26901      } else {
26902        swiper.$wrapperEl[0].addEventListener('transitionend', swiper.autoplay.onTransitionEnd);
26903        swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.autoplay.onTransitionEnd);
26904      }
26905    },
26906  };
26907
26908  var Autoplay$1 = {
26909    name: 'autoplay',
26910    params: {
26911      autoplay: {
26912        enabled: false,
26913        delay: 3000,
26914        waitForTransition: true,
26915        disableOnInteraction: true,
26916        stopOnLastSlide: false,
26917        reverseDirection: false,
26918      },
26919    },
26920    create: function create() {
26921      var swiper = this;
26922      Utils.extend(swiper, {
26923        autoplay: {
26924          running: false,
26925          paused: false,
26926          run: Autoplay.run.bind(swiper),
26927          start: Autoplay.start.bind(swiper),
26928          stop: Autoplay.stop.bind(swiper),
26929          pause: Autoplay.pause.bind(swiper),
26930          onTransitionEnd: function onTransitionEnd(e) {
26931            if (!swiper || swiper.destroyed || !swiper.$wrapperEl) { return; }
26932            if (e.target !== this) { return; }
26933            swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.autoplay.onTransitionEnd);
26934            swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.autoplay.onTransitionEnd);
26935            swiper.autoplay.paused = false;
26936            if (!swiper.autoplay.running) {
26937              swiper.autoplay.stop();
26938            } else {
26939              swiper.autoplay.run();
26940            }
26941          },
26942        },
26943      });
26944    },
26945    on: {
26946      init: function init() {
26947        var swiper = this;
26948        if (swiper.params.autoplay.enabled) {
26949          swiper.autoplay.start();
26950        }
26951      },
26952      beforeTransitionStart: function beforeTransitionStart(speed, internal) {
26953        var swiper = this;
26954        if (swiper.autoplay.running) {
26955          if (internal || !swiper.params.autoplay.disableOnInteraction) {
26956            swiper.autoplay.pause(speed);
26957          } else {
26958            swiper.autoplay.stop();
26959          }
26960        }
26961      },
26962      sliderFirstMove: function sliderFirstMove() {
26963        var swiper = this;
26964        if (swiper.autoplay.running) {
26965          if (swiper.params.autoplay.disableOnInteraction) {
26966            swiper.autoplay.stop();
26967          } else {
26968            swiper.autoplay.pause();
26969          }
26970        }
26971      },
26972      destroy: function destroy() {
26973        var swiper = this;
26974        if (swiper.autoplay.running) {
26975          swiper.autoplay.stop();
26976        }
26977      },
26978    },
26979  };
26980
26981  var Fade = {
26982    setTranslate: function setTranslate() {
26983      var swiper = this;
26984      var slides = swiper.slides;
26985      for (var i = 0; i < slides.length; i += 1) {
26986        var $slideEl = swiper.slides.eq(i);
26987        var offset = $slideEl[0].swiperSlideOffset;
26988        var tx = -offset;
26989        if (!swiper.params.virtualTranslate) { tx -= swiper.translate; }
26990        var ty = 0;
26991        if (!swiper.isHorizontal()) {
26992          ty = tx;
26993          tx = 0;
26994        }
26995        var slideOpacity = swiper.params.fadeEffect.crossFade
26996          ? Math.max(1 - Math.abs($slideEl[0].progress), 0)
26997          : 1 + Math.min(Math.max($slideEl[0].progress, -1), 0);
26998        $slideEl
26999          .css({
27000            opacity: slideOpacity,
27001          })
27002          .transform(("translate3d(" + tx + "px, " + ty + "px, 0px)"));
27003      }
27004    },
27005    setTransition: function setTransition(duration) {
27006      var swiper = this;
27007      var slides = swiper.slides;
27008      var $wrapperEl = swiper.$wrapperEl;
27009      slides.transition(duration);
27010      if (swiper.params.virtualTranslate && duration !== 0) {
27011        var eventTriggered = false;
27012        slides.transitionEnd(function () {
27013          if (eventTriggered) { return; }
27014          if (!swiper || swiper.destroyed) { return; }
27015          eventTriggered = true;
27016          swiper.animating = false;
27017          var triggerEvents = ['webkitTransitionEnd', 'transitionend'];
27018          for (var i = 0; i < triggerEvents.length; i += 1) {
27019            $wrapperEl.trigger(triggerEvents[i]);
27020          }
27021        });
27022      }
27023    },
27024  };
27025
27026  var EffectFade = {
27027    name: 'effect-fade',
27028    params: {
27029      fadeEffect: {
27030        crossFade: false,
27031      },
27032    },
27033    create: function create() {
27034      var swiper = this;
27035      Utils.extend(swiper, {
27036        fadeEffect: {
27037          setTranslate: Fade.setTranslate.bind(swiper),
27038          setTransition: Fade.setTransition.bind(swiper),
27039        },
27040      });
27041    },
27042    on: {
27043      beforeInit: function beforeInit() {
27044        var swiper = this;
27045        if (swiper.params.effect !== 'fade') { return; }
27046        swiper.classNames.push(((swiper.params.containerModifierClass) + "fade"));
27047        var overwriteParams = {
27048          slidesPerView: 1,
27049          slidesPerColumn: 1,
27050          slidesPerGroup: 1,
27051          watchSlidesProgress: true,
27052          spaceBetween: 0,
27053          virtualTranslate: true,
27054        };
27055        Utils.extend(swiper.params, overwriteParams);
27056        Utils.extend(swiper.originalParams, overwriteParams);
27057      },
27058      setTranslate: function setTranslate() {
27059        var swiper = this;
27060        if (swiper.params.effect !== 'fade') { return; }
27061        swiper.fadeEffect.setTranslate();
27062      },
27063      setTransition: function setTransition(duration) {
27064        var swiper = this;
27065        if (swiper.params.effect !== 'fade') { return; }
27066        swiper.fadeEffect.setTransition(duration);
27067      },
27068    },
27069  };
27070
27071  var Cube = {
27072    setTranslate: function setTranslate() {
27073      var swiper = this;
27074      var $el = swiper.$el;
27075      var $wrapperEl = swiper.$wrapperEl;
27076      var slides = swiper.slides;
27077      var swiperWidth = swiper.width;
27078      var swiperHeight = swiper.height;
27079      var rtl = swiper.rtlTranslate;
27080      var swiperSize = swiper.size;
27081      var params = swiper.params.cubeEffect;
27082      var isHorizontal = swiper.isHorizontal();
27083      var isVirtual = swiper.virtual && swiper.params.virtual.enabled;
27084      var wrapperRotate = 0;
27085      var $cubeShadowEl;
27086      if (params.shadow) {
27087        if (isHorizontal) {
27088          $cubeShadowEl = $wrapperEl.find('.swiper-cube-shadow');
27089          if ($cubeShadowEl.length === 0) {
27090            $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
27091            $wrapperEl.append($cubeShadowEl);
27092          }
27093          $cubeShadowEl.css({ height: (swiperWidth + "px") });
27094        } else {
27095          $cubeShadowEl = $el.find('.swiper-cube-shadow');
27096          if ($cubeShadowEl.length === 0) {
27097            $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
27098            $el.append($cubeShadowEl);
27099          }
27100        }
27101      }
27102      for (var i = 0; i < slides.length; i += 1) {
27103        var $slideEl = slides.eq(i);
27104        var slideIndex = i;
27105        if (isVirtual) {
27106          slideIndex = parseInt($slideEl.attr('data-swiper-slide-index'), 10);
27107        }
27108        var slideAngle = slideIndex * 90;
27109        var round = Math.floor(slideAngle / 360);
27110        if (rtl) {
27111          slideAngle = -slideAngle;
27112          round = Math.floor(-slideAngle / 360);
27113        }
27114        var progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
27115        var tx = 0;
27116        var ty = 0;
27117        var tz = 0;
27118        if (slideIndex % 4 === 0) {
27119          tx = -round * 4 * swiperSize;
27120          tz = 0;
27121        } else if ((slideIndex - 1) % 4 === 0) {
27122          tx = 0;
27123          tz = -round * 4 * swiperSize;
27124        } else if ((slideIndex - 2) % 4 === 0) {
27125          tx = swiperSize + (round * 4 * swiperSize);
27126          tz = swiperSize;
27127        } else if ((slideIndex - 3) % 4 === 0) {
27128          tx = -swiperSize;
27129          tz = (3 * swiperSize) + (swiperSize * 4 * round);
27130        }
27131        if (rtl) {
27132          tx = -tx;
27133        }
27134
27135        if (!isHorizontal) {
27136          ty = tx;
27137          tx = 0;
27138        }
27139
27140        var transform = "rotateX(" + (isHorizontal ? 0 : -slideAngle) + "deg) rotateY(" + (isHorizontal ? slideAngle : 0) + "deg) translate3d(" + tx + "px, " + ty + "px, " + tz + "px)";
27141        if (progress <= 1 && progress > -1) {
27142          wrapperRotate = (slideIndex * 90) + (progress * 90);
27143          if (rtl) { wrapperRotate = (-slideIndex * 90) - (progress * 90); }
27144        }
27145        $slideEl.transform(transform);
27146        if (params.slideShadows) {
27147          // Set shadows
27148          var shadowBefore = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
27149          var shadowAfter = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
27150          if (shadowBefore.length === 0) {
27151            shadowBefore = $(("<div class=\"swiper-slide-shadow-" + (isHorizontal ? 'left' : 'top') + "\"></div>"));
27152            $slideEl.append(shadowBefore);
27153          }
27154          if (shadowAfter.length === 0) {
27155            shadowAfter = $(("<div class=\"swiper-slide-shadow-" + (isHorizontal ? 'right' : 'bottom') + "\"></div>"));
27156            $slideEl.append(shadowAfter);
27157          }
27158          if (shadowBefore.length) { shadowBefore[0].style.opacity = Math.max(-progress, 0); }
27159          if (shadowAfter.length) { shadowAfter[0].style.opacity = Math.max(progress, 0); }
27160        }
27161      }
27162      $wrapperEl.css({
27163        '-webkit-transform-origin': ("50% 50% -" + (swiperSize / 2) + "px"),
27164        '-moz-transform-origin': ("50% 50% -" + (swiperSize / 2) + "px"),
27165        '-ms-transform-origin': ("50% 50% -" + (swiperSize / 2) + "px"),
27166        'transform-origin': ("50% 50% -" + (swiperSize / 2) + "px"),
27167      });
27168
27169      if (params.shadow) {
27170        if (isHorizontal) {
27171          $cubeShadowEl.transform(("translate3d(0px, " + ((swiperWidth / 2) + params.shadowOffset) + "px, " + (-swiperWidth / 2) + "px) rotateX(90deg) rotateZ(0deg) scale(" + (params.shadowScale) + ")"));
27172        } else {
27173          var shadowAngle = Math.abs(wrapperRotate) - (Math.floor(Math.abs(wrapperRotate) / 90) * 90);
27174          var multiplier = 1.5 - (
27175            (Math.sin((shadowAngle * 2 * Math.PI) / 360) / 2)
27176            + (Math.cos((shadowAngle * 2 * Math.PI) / 360) / 2)
27177          );
27178          var scale1 = params.shadowScale;
27179          var scale2 = params.shadowScale / multiplier;
27180          var offset = params.shadowOffset;
27181          $cubeShadowEl.transform(("scale3d(" + scale1 + ", 1, " + scale2 + ") translate3d(0px, " + ((swiperHeight / 2) + offset) + "px, " + (-swiperHeight / 2 / scale2) + "px) rotateX(-90deg)"));
27182        }
27183      }
27184      var zFactor = (Browser.isSafari || Browser.isUiWebView) ? (-swiperSize / 2) : 0;
27185      $wrapperEl
27186        .transform(("translate3d(0px,0," + zFactor + "px) rotateX(" + (swiper.isHorizontal() ? 0 : wrapperRotate) + "deg) rotateY(" + (swiper.isHorizontal() ? -wrapperRotate : 0) + "deg)"));
27187    },
27188    setTransition: function setTransition(duration) {
27189      var swiper = this;
27190      var $el = swiper.$el;
27191      var slides = swiper.slides;
27192      slides
27193        .transition(duration)
27194        .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
27195        .transition(duration);
27196      if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) {
27197        $el.find('.swiper-cube-shadow').transition(duration);
27198      }
27199    },
27200  };
27201
27202  var EffectCube = {
27203    name: 'effect-cube',
27204    params: {
27205      cubeEffect: {
27206        slideShadows: true,
27207        shadow: true,
27208        shadowOffset: 20,
27209        shadowScale: 0.94,
27210      },
27211    },
27212    create: function create() {
27213      var swiper = this;
27214      Utils.extend(swiper, {
27215        cubeEffect: {
27216          setTranslate: Cube.setTranslate.bind(swiper),
27217          setTransition: Cube.setTransition.bind(swiper),
27218        },
27219      });
27220    },
27221    on: {
27222      beforeInit: function beforeInit() {
27223        var swiper = this;
27224        if (swiper.params.effect !== 'cube') { return; }
27225        swiper.classNames.push(((swiper.params.containerModifierClass) + "cube"));
27226        swiper.classNames.push(((swiper.params.containerModifierClass) + "3d"));
27227        var overwriteParams = {
27228          slidesPerView: 1,
27229          slidesPerColumn: 1,
27230          slidesPerGroup: 1,
27231          watchSlidesProgress: true,
27232          resistanceRatio: 0,
27233          spaceBetween: 0,
27234          centeredSlides: false,
27235          virtualTranslate: true,
27236        };
27237        Utils.extend(swiper.params, overwriteParams);
27238        Utils.extend(swiper.originalParams, overwriteParams);
27239      },
27240      setTranslate: function setTranslate() {
27241        var swiper = this;
27242        if (swiper.params.effect !== 'cube') { return; }
27243        swiper.cubeEffect.setTranslate();
27244      },
27245      setTransition: function setTransition(duration) {
27246        var swiper = this;
27247        if (swiper.params.effect !== 'cube') { return; }
27248        swiper.cubeEffect.setTransition(duration);
27249      },
27250    },
27251  };
27252
27253  var Flip = {
27254    setTranslate: function setTranslate() {
27255      var swiper = this;
27256      var slides = swiper.slides;
27257      var rtl = swiper.rtlTranslate;
27258      for (var i = 0; i < slides.length; i += 1) {
27259        var $slideEl = slides.eq(i);
27260        var progress = $slideEl[0].progress;
27261        if (swiper.params.flipEffect.limitRotation) {
27262          progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
27263        }
27264        var offset = $slideEl[0].swiperSlideOffset;
27265        var rotate = -180 * progress;
27266        var rotateY = rotate;
27267        var rotateX = 0;
27268        var tx = -offset;
27269        var ty = 0;
27270        if (!swiper.isHorizontal()) {
27271          ty = tx;
27272          tx = 0;
27273          rotateX = -rotateY;
27274          rotateY = 0;
27275        } else if (rtl) {
27276          rotateY = -rotateY;
27277        }
27278
27279        $slideEl[0].style.zIndex = -Math.abs(Math.round(progress)) + slides.length;
27280
27281        if (swiper.params.flipEffect.slideShadows) {
27282          // Set shadows
27283          var shadowBefore = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
27284          var shadowAfter = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
27285          if (shadowBefore.length === 0) {
27286            shadowBefore = $(("<div class=\"swiper-slide-shadow-" + (swiper.isHorizontal() ? 'left' : 'top') + "\"></div>"));
27287            $slideEl.append(shadowBefore);
27288          }
27289          if (shadowAfter.length === 0) {
27290            shadowAfter = $(("<div class=\"swiper-slide-shadow-" + (swiper.isHorizontal() ? 'right' : 'bottom') + "\"></div>"));
27291            $slideEl.append(shadowAfter);
27292          }
27293          if (shadowBefore.length) { shadowBefore[0].style.opacity = Math.max(-progress, 0); }
27294          if (shadowAfter.length) { shadowAfter[0].style.opacity = Math.max(progress, 0); }
27295        }
27296        $slideEl
27297          .transform(("translate3d(" + tx + "px, " + ty + "px, 0px) rotateX(" + rotateX + "deg) rotateY(" + rotateY + "deg)"));
27298      }
27299    },
27300    setTransition: function setTransition(duration) {
27301      var swiper = this;
27302      var slides = swiper.slides;
27303      var activeIndex = swiper.activeIndex;
27304      var $wrapperEl = swiper.$wrapperEl;
27305      slides
27306        .transition(duration)
27307        .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
27308        .transition(duration);
27309      if (swiper.params.virtualTranslate && duration !== 0) {
27310        var eventTriggered = false;
27311        // eslint-disable-next-line
27312        slides.eq(activeIndex).transitionEnd(function onTransitionEnd() {
27313          if (eventTriggered) { return; }
27314          if (!swiper || swiper.destroyed) { return; }
27315          // if (!$(this).hasClass(swiper.params.slideActiveClass)) return;
27316          eventTriggered = true;
27317          swiper.animating = false;
27318          var triggerEvents = ['webkitTransitionEnd', 'transitionend'];
27319          for (var i = 0; i < triggerEvents.length; i += 1) {
27320            $wrapperEl.trigger(triggerEvents[i]);
27321          }
27322        });
27323      }
27324    },
27325  };
27326
27327  var EffectFlip = {
27328    name: 'effect-flip',
27329    params: {
27330      flipEffect: {
27331        slideShadows: true,
27332        limitRotation: true,
27333      },
27334    },
27335    create: function create() {
27336      var swiper = this;
27337      Utils.extend(swiper, {
27338        flipEffect: {
27339          setTranslate: Flip.setTranslate.bind(swiper),
27340          setTransition: Flip.setTransition.bind(swiper),
27341        },
27342      });
27343    },
27344    on: {
27345      beforeInit: function beforeInit() {
27346        var swiper = this;
27347        if (swiper.params.effect !== 'flip') { return; }
27348        swiper.classNames.push(((swiper.params.containerModifierClass) + "flip"));
27349        swiper.classNames.push(((swiper.params.containerModifierClass) + "3d"));
27350        var overwriteParams = {
27351          slidesPerView: 1,
27352          slidesPerColumn: 1,
27353          slidesPerGroup: 1,
27354          watchSlidesProgress: true,
27355          spaceBetween: 0,
27356          virtualTranslate: true,
27357        };
27358        Utils.extend(swiper.params, overwriteParams);
27359        Utils.extend(swiper.originalParams, overwriteParams);
27360      },
27361      setTranslate: function setTranslate() {
27362        var swiper = this;
27363        if (swiper.params.effect !== 'flip') { return; }
27364        swiper.flipEffect.setTranslate();
27365      },
27366      setTransition: function setTransition(duration) {
27367        var swiper = this;
27368        if (swiper.params.effect !== 'flip') { return; }
27369        swiper.flipEffect.setTransition(duration);
27370      },
27371    },
27372  };
27373
27374  var Coverflow = {
27375    setTranslate: function setTranslate() {
27376      var swiper = this;
27377      var swiperWidth = swiper.width;
27378      var swiperHeight = swiper.height;
27379      var slides = swiper.slides;
27380      var $wrapperEl = swiper.$wrapperEl;
27381      var slidesSizesGrid = swiper.slidesSizesGrid;
27382      var params = swiper.params.coverflowEffect;
27383      var isHorizontal = swiper.isHorizontal();
27384      var transform = swiper.translate;
27385      var center = isHorizontal ? -transform + (swiperWidth / 2) : -transform + (swiperHeight / 2);
27386      var rotate = isHorizontal ? params.rotate : -params.rotate;
27387      var translate = params.depth;
27388      // Each slide offset from center
27389      for (var i = 0, length = slides.length; i < length; i += 1) {
27390        var $slideEl = slides.eq(i);
27391        var slideSize = slidesSizesGrid[i];
27392        var slideOffset = $slideEl[0].swiperSlideOffset;
27393        var offsetMultiplier = ((center - slideOffset - (slideSize / 2)) / slideSize) * params.modifier;
27394
27395        var rotateY = isHorizontal ? rotate * offsetMultiplier : 0;
27396        var rotateX = isHorizontal ? 0 : rotate * offsetMultiplier;
27397        // var rotateZ = 0
27398        var translateZ = -translate * Math.abs(offsetMultiplier);
27399
27400        var translateY = isHorizontal ? 0 : params.stretch * (offsetMultiplier);
27401        var translateX = isHorizontal ? params.stretch * (offsetMultiplier) : 0;
27402
27403        // Fix for ultra small values
27404        if (Math.abs(translateX) < 0.001) { translateX = 0; }
27405        if (Math.abs(translateY) < 0.001) { translateY = 0; }
27406        if (Math.abs(translateZ) < 0.001) { translateZ = 0; }
27407        if (Math.abs(rotateY) < 0.001) { rotateY = 0; }
27408        if (Math.abs(rotateX) < 0.001) { rotateX = 0; }
27409
27410        var slideTransform = "translate3d(" + translateX + "px," + translateY + "px," + translateZ + "px)  rotateX(" + rotateX + "deg) rotateY(" + rotateY + "deg)";
27411
27412        $slideEl.transform(slideTransform);
27413        $slideEl[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
27414        if (params.slideShadows) {
27415          // Set shadows
27416          var $shadowBeforeEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
27417          var $shadowAfterEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
27418          if ($shadowBeforeEl.length === 0) {
27419            $shadowBeforeEl = $(("<div class=\"swiper-slide-shadow-" + (isHorizontal ? 'left' : 'top') + "\"></div>"));
27420            $slideEl.append($shadowBeforeEl);
27421          }
27422          if ($shadowAfterEl.length === 0) {
27423            $shadowAfterEl = $(("<div class=\"swiper-slide-shadow-" + (isHorizontal ? 'right' : 'bottom') + "\"></div>"));
27424            $slideEl.append($shadowAfterEl);
27425          }
27426          if ($shadowBeforeEl.length) { $shadowBeforeEl[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0; }
27427          if ($shadowAfterEl.length) { $shadowAfterEl[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0; }
27428        }
27429      }
27430
27431      // Set correct perspective for IE10
27432      if (Support.pointerEvents || Support.prefixedPointerEvents) {
27433        var ws = $wrapperEl[0].style;
27434        ws.perspectiveOrigin = center + "px 50%";
27435      }
27436    },
27437    setTransition: function setTransition(duration) {
27438      var swiper = this;
27439      swiper.slides
27440        .transition(duration)
27441        .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
27442        .transition(duration);
27443    },
27444  };
27445
27446  var EffectCoverflow = {
27447    name: 'effect-coverflow',
27448    params: {
27449      coverflowEffect: {
27450        rotate: 50,
27451        stretch: 0,
27452        depth: 100,
27453        modifier: 1,
27454        slideShadows: true,
27455      },
27456    },
27457    create: function create() {
27458      var swiper = this;
27459      Utils.extend(swiper, {
27460        coverflowEffect: {
27461          setTranslate: Coverflow.setTranslate.bind(swiper),
27462          setTransition: Coverflow.setTransition.bind(swiper),
27463        },
27464      });
27465    },
27466    on: {
27467      beforeInit: function beforeInit() {
27468        var swiper = this;
27469        if (swiper.params.effect !== 'coverflow') { return; }
27470
27471        swiper.classNames.push(((swiper.params.containerModifierClass) + "coverflow"));
27472        swiper.classNames.push(((swiper.params.containerModifierClass) + "3d"));
27473
27474        swiper.params.watchSlidesProgress = true;
27475        swiper.originalParams.watchSlidesProgress = true;
27476      },
27477      setTranslate: function setTranslate() {
27478        var swiper = this;
27479        if (swiper.params.effect !== 'coverflow') { return; }
27480        swiper.coverflowEffect.setTranslate();
27481      },
27482      setTransition: function setTransition(duration) {
27483        var swiper = this;
27484        if (swiper.params.effect !== 'coverflow') { return; }
27485        swiper.coverflowEffect.setTransition(duration);
27486      },
27487    },
27488  };
27489
27490  var Thumbs = {
27491    init: function init() {
27492      var swiper = this;
27493      var ref = swiper.params;
27494      var thumbsParams = ref.thumbs;
27495      var SwiperClass = swiper.constructor;
27496      if (thumbsParams.swiper instanceof SwiperClass) {
27497        swiper.thumbs.swiper = thumbsParams.swiper;
27498        Utils.extend(swiper.thumbs.swiper.originalParams, {
27499          watchSlidesProgress: true,
27500          slideToClickedSlide: false,
27501        });
27502        Utils.extend(swiper.thumbs.swiper.params, {
27503          watchSlidesProgress: true,
27504          slideToClickedSlide: false,
27505        });
27506      } else if (Utils.isObject(thumbsParams.swiper)) {
27507        swiper.thumbs.swiper = new SwiperClass(Utils.extend({}, thumbsParams.swiper, {
27508          watchSlidesVisibility: true,
27509          watchSlidesProgress: true,
27510          slideToClickedSlide: false,
27511        }));
27512        swiper.thumbs.swiperCreated = true;
27513      }
27514      swiper.thumbs.swiper.$el.addClass(swiper.params.thumbs.thumbsContainerClass);
27515      swiper.thumbs.swiper.on('tap', swiper.thumbs.onThumbClick);
27516    },
27517    onThumbClick: function onThumbClick() {
27518      var swiper = this;
27519      var thumbsSwiper = swiper.thumbs.swiper;
27520      if (!thumbsSwiper) { return; }
27521      var clickedIndex = thumbsSwiper.clickedIndex;
27522      var clickedSlide = thumbsSwiper.clickedSlide;
27523      if (clickedSlide && $(clickedSlide).hasClass(swiper.params.thumbs.slideThumbActiveClass)) { return; }
27524      if (typeof clickedIndex === 'undefined' || clickedIndex === null) { return; }
27525      var slideToIndex;
27526      if (thumbsSwiper.params.loop) {
27527        slideToIndex = parseInt($(thumbsSwiper.clickedSlide).attr('data-swiper-slide-index'), 10);
27528      } else {
27529        slideToIndex = clickedIndex;
27530      }
27531      if (swiper.params.loop) {
27532        var currentIndex = swiper.activeIndex;
27533        if (swiper.slides.eq(currentIndex).hasClass(swiper.params.slideDuplicateClass)) {
27534          swiper.loopFix();
27535          // eslint-disable-next-line
27536          swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
27537          currentIndex = swiper.activeIndex;
27538        }
27539        var prevIndex = swiper.slides.eq(currentIndex).prevAll(("[data-swiper-slide-index=\"" + slideToIndex + "\"]")).eq(0).index();
27540        var nextIndex = swiper.slides.eq(currentIndex).nextAll(("[data-swiper-slide-index=\"" + slideToIndex + "\"]")).eq(0).index();
27541        if (typeof prevIndex === 'undefined') { slideToIndex = nextIndex; }
27542        else if (typeof nextIndex === 'undefined') { slideToIndex = prevIndex; }
27543        else if (nextIndex - currentIndex < currentIndex - prevIndex) { slideToIndex = nextIndex; }
27544        else { slideToIndex = prevIndex; }
27545      }
27546      swiper.slideTo(slideToIndex);
27547    },
27548    update: function update(initial) {
27549      var swiper = this;
27550      var thumbsSwiper = swiper.thumbs.swiper;
27551      if (!thumbsSwiper) { return; }
27552
27553      var slidesPerView = thumbsSwiper.params.slidesPerView === 'auto'
27554        ? thumbsSwiper.slidesPerViewDynamic()
27555        : thumbsSwiper.params.slidesPerView;
27556
27557      if (swiper.realIndex !== thumbsSwiper.realIndex) {
27558        var currentThumbsIndex = thumbsSwiper.activeIndex;
27559        var newThumbsIndex;
27560        if (thumbsSwiper.params.loop) {
27561          if (thumbsSwiper.slides.eq(currentThumbsIndex).hasClass(thumbsSwiper.params.slideDuplicateClass)) {
27562            thumbsSwiper.loopFix();
27563            // eslint-disable-next-line
27564            thumbsSwiper._clientLeft = thumbsSwiper.$wrapperEl[0].clientLeft;
27565            currentThumbsIndex = thumbsSwiper.activeIndex;
27566          }
27567          // Find actual thumbs index to slide to
27568          var prevThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).prevAll(("[data-swiper-slide-index=\"" + (swiper.realIndex) + "\"]")).eq(0).index();
27569          var nextThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).nextAll(("[data-swiper-slide-index=\"" + (swiper.realIndex) + "\"]")).eq(0).index();
27570          if (typeof prevThumbsIndex === 'undefined') { newThumbsIndex = nextThumbsIndex; }
27571          else if (typeof nextThumbsIndex === 'undefined') { newThumbsIndex = prevThumbsIndex; }
27572          else if (nextThumbsIndex - currentThumbsIndex === currentThumbsIndex - prevThumbsIndex) { newThumbsIndex = currentThumbsIndex; }
27573          else if (nextThumbsIndex - currentThumbsIndex < currentThumbsIndex - prevThumbsIndex) { newThumbsIndex = nextThumbsIndex; }
27574          else { newThumbsIndex = prevThumbsIndex; }
27575        } else {
27576          newThumbsIndex = swiper.realIndex;
27577        }
27578        if (thumbsSwiper.visibleSlidesIndexes
vendor: 5,487 bytes, lines 27578-27803
27578.indexOf(newThumbsIndex) < 0) {
27579          if (thumbsSwiper.params.centeredSlides) {
27580            if (newThumbsIndex > currentThumbsIndex) {
27581              newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1;
27582            } else {
27583              newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1;
27584            }
27585          } else if (newThumbsIndex > currentThumbsIndex) {
27586            newThumbsIndex = newThumbsIndex - slidesPerView + 1;
27587          }
27588          thumbsSwiper.slideTo(newThumbsIndex, initial ? 0 : undefined);
27589        }
27590      }
27591
27592      // Activate thumbs
27593      var thumbsToActivate = 1;
27594      var thumbActiveClass = swiper.params.thumbs.slideThumbActiveClass;
27595
27596      if (swiper.params.slidesPerView > 1 && !swiper.params.centeredSlides) {
27597        thumbsToActivate = swiper.params.slidesPerView;
27598      }
27599
27600      thumbsSwiper.slides.removeClass(thumbActiveClass);
27601      if (thumbsSwiper.params.loop) {
27602        for (var i = 0; i < thumbsToActivate; i += 1) {
27603          thumbsSwiper.$wrapperEl.children(("[data-swiper-slide-index=\"" + (swiper.realIndex + i) + "\"]")).addClass(thumbActiveClass);
27604        }
27605      } else {
27606        for (var i$1 = 0; i$1 < thumbsToActivate; i$1 += 1) {
27607          thumbsSwiper.slides.eq(swiper.realIndex + i$1).addClass(thumbActiveClass);
27608        }
27609      }
27610    },
27611  };
27612  var Thumbs$1 = {
27613    name: 'thumbs',
27614    params: {
27615      thumbs: {
27616        swiper: null,
27617        slideThumbActiveClass: 'swiper-slide-thumb-active',
27618        thumbsContainerClass: 'swiper-container-thumbs',
27619      },
27620    },
27621    create: function create() {
27622      var swiper = this;
27623      Utils.extend(swiper, {
27624        thumbs: {
27625          swiper: null,
27626          init: Thumbs.init.bind(swiper),
27627          update: Thumbs.update.bind(swiper),
27628          onThumbClick: Thumbs.onThumbClick.bind(swiper),
27629        },
27630      });
27631    },
27632    on: {
27633      beforeInit: function beforeInit() {
27634        var swiper = this;
27635        var ref = swiper.params;
27636        var thumbs = ref.thumbs;
27637        if (!thumbs || !thumbs.swiper) { return; }
27638        swiper.thumbs.init();
27639        swiper.thumbs.update(true);
27640      },
27641      slideChange: function slideChange() {
27642        var swiper = this;
27643        if (!swiper.thumbs.swiper) { return; }
27644        swiper.thumbs.update();
27645      },
27646      update: function update() {
27647        var swiper = this;
27648        if (!swiper.thumbs.swiper) { return; }
27649        swiper.thumbs.update();
27650      },
27651      resize: function resize() {
27652        var swiper = this;
27653        if (!swiper.thumbs.swiper) { return; }
27654        swiper.thumbs.update();
27655      },
27656      observerUpdate: function observerUpdate() {
27657        var swiper = this;
27658        if (!swiper.thumbs.swiper) { return; }
27659        swiper.thumbs.update();
27660      },
27661      setTransition: function setTransition(duration) {
27662        var swiper = this;
27663        var thumbsSwiper = swiper.thumbs.swiper;
27664        if (!thumbsSwiper) { return; }
27665        thumbsSwiper.setTransition(duration);
27666      },
27667      beforeDestroy: function beforeDestroy() {
27668        var swiper = this;
27669        var thumbsSwiper = swiper.thumbs.swiper;
27670        if (!thumbsSwiper) { return; }
27671        if (swiper.thumbs.swiperCreated && thumbsSwiper) {
27672          thumbsSwiper.destroy();
27673        }
27674      },
27675    },
27676  };
27677
27678  // Swiper Class
27679
27680  var components = [
27681    Device$1,
27682    Support$1,
27683    Browser$1,
27684    Resize,
27685    Observer$1,
27686    Virtual$1,
27687    Keyboard$1,
27688    Mousewheel$1,
27689    Navigation$1,
27690    Pagination$1,
27691    Scrollbar$1,
27692    Parallax$1,
27693    Zoom$1,
27694    Lazy$1,
27695    Controller$1,
27696    A11y,
27697    History$1,
27698    HashNavigation$1,
27699    Autoplay$1,
27700    EffectFade,
27701    EffectCube,
27702    EffectFlip,
27703    EffectCoverflow,
27704    Thumbs$1
27705  ];
27706
27707  if (typeof Swiper.use === 'undefined') {
27708    Swiper.use = Swiper.Class.use;
27709    Swiper.installModule = Swiper.Class.installModule;
27710  }
27711
27712  Swiper.use(components);
27713
27714  return Swiper;
27715
27716}));
27717
27718
27719/**
27720 * Main Javascript file
27721 *
27722 *
27723 */
27724
27725/**
27726 * Bootstrap4 components
27727 *
27728 *
27729 * Available components
27730 *
27731 * alert.js
27732 * button.js
27733 * carousel.js
27734 * collapse.js
27735 * dropdown.js
27736 * modal.js
27737 * popover.js
27738 * scrollspy.js
27739 * tab.js
27740 * toast.js
27741 * tooltip.js
27742 *
27743 * @see https://jquery.com/
27744 * @see https://getbootstrap.com/docs/4.0/getting-started/introduction/
27745 */
27746
27747// Required by all
27748// @codekit-prepend "../bower_components/jquery/dist/jquery.js";
27749// @codekit-prepend "../bower_components/popper.js/dist/umd/popper.js";
27750// @codekit-prepend "../bower_components/bootstrap4/js/dist/index.js
27751// @codekit-prepend "../bower_components/bootstrap4/js/dist/util.js
27752
27753// components
27754// @codekit-prepend "../bower_components/bootstrap4/js/dist/tab.js
27755// @codekit-prepend "../bower_components/bootstrap4/js/dist/alert.js
27756// @codekit-prepend "../bower_components/bootstrap4/js/dist/collapse.js
27757// @codekit-prepend "../bower_components/bootstrap4/js/dist/modal.js
27758// @codekit-prepend "../bower_components/bootstrap4/js/dist/toast.js
27759
27760/**
27761 * PhotoSwipe
27762 *
27763 * @see https://photoswipe.com/
27764 *
27765 */
27766// @codekit-prepend "../bower_components/photoswipe/dist/photoswipe-ui-default.js
27767// @codekit-prepend "../bower_components/photoswipe/dist/photoswipe.js
27768
27769
27770/**
27771 * Swiper
27772 *
27773 * @see http://idangero.us/swiper/
27774 *
27775 */
27776// @codekit-prepend "../bower_components/swiper/dist/js/swiper.js
27777
27778
27779/**
27780 * Custom Javascript
27781 *
27782 */
27783// @codekit-append "utils.js";
27784
27785
27786
27787
27788
27789/*global
27790$ jQuery window jsConfig console NodeList
27791*/
27792
27793
27794
27795var utils;
27796
27797(function () {
27798	"use strict";
27799
27800	utils = {
27801		// Object to query string
27802		serialize: function (obj) {
27803			var str = [];
27804			Object.keys(obj).forEach(function (key) {
27805				str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
27806			});
27807			return str.join("&");
27808		},
27809		// @param DomElement form
27810		formToObject: function (form) {
27811			var elements = form.elements;
27812			var o = {};
27813			var i;
27814			var key;
27815			var item;
27816			for (i = 0; i < elements.length; i += 1) {
27817				item = elements.item(i);
27818				key = item.name || item.id;
27819				if (key && item.type !== "submit") {
27820					o[key] = item.value;
27821				}
27822			}
27823			return o;
27824		},
27825		// @param DomElement form
27826		serializeForm: function (form) {
27827			return this.serialize(this.formToObject(form));
27828		},
27829		isObject: function(val) {
27830			return typeof val === 'object' && val !== null;
27831		},
27832		isEmptyObject: function (obj) {
27833			Object.keys(obj).forEach(function () {
27834				return false;
27835			});
27836			return JSON.stringify(obj) === JSON.stringify({});
27837		},
27838		// Is it a stringyfied Object?
27839		isStringified: function (string) {
27840			try {
27841				return typeof JSON.parse(string) === 'object';
27842			} catch (ignore) {
27843				return false;
27844			}
27845		},
27846		objFromUrl: function (url) {
27847			var obj = {};
27848			if (url.indexOf("?") > -1) {
27849				url = url.split("?")[1];
27850			}
27851
27852			url.replace(/([^=&]+)=([^&]*)/g, function (ignore, key, value) {
27853				obj[decodeURIComponent(key)] = decodeURIComponent(value);
27854			});
27855			return obj;
27856
27857		},
27858		// @param NodeList
27859		nodesToArray: function (nodeList) {
27860			return Array.prototype.slice.call(nodeList, 0);
27861		},
27862		walkDom: function (node, callback) {
27863			callback(node);
27864			node = node.firstChild;
27865			while (node) {
27866				utils.walkDom(node, callback);
27867				node = node.nextSibling;
27868			}
27869		},
27870		setCookie: function (cname, cvalue, exdays) {
27871			if (!cname) {
27872				return false;
27873			}
27874			var days = exdays || 1;
27875			var d = new Date();
27876			d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));
27877			var expires = "expires=" + d.toUTCString();
27878			if (days === -1) {
27879				expires = "expires=Thu, 01 Jan 1970 00:00:01 GMT";
27880			}
27881
27882			if (this.isObject(cvalue)) {
27883				cvalue = JSON.stringify(cvalue);
27884			}
27885
27886			document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
27887		},
27888		getCookie: function (cname) {
27889			var name = cname + "=";
27890			var decodedCookie = decodeURIComponent(document.cookie);
27891			var ca = decodedCookie.split(";");
27892			var i;
27893			var c;
27894			var s;
27895			for (i = 0; i < ca.length; i += 1) {
27896				c = ca[i];
27897				while (c.charAt(0) === " ") {
27898					c = c.substring(1);
27899				}
27900				if (c.indexOf(name) === 0) {
27901					s = c.substring(name.length, c.length);
27902					if(this.isStringified(s)) {
27903						return JSON.parse(s);
27904					} else {
27905						return s;
27906					}
27907				}
27908			}
27909			return "";
27910		},
27911		deleteCookie: function (cname) {
27912			this.setCookie(cname, "", -1);
27913		},
27914		// Specify true when element complete in viewport
27915		inViewPort: function (el, bool) {
27916			bool = bool || false;
27917			var rect = el.getBoundingClientRect();
27918			var rectHtml = document.documentElement.getBoundingClientRect();
27919			var bottom = bool ? rectHtml.height : 0;
27920			var top = bool ? 0 : rectHtml.height;
27921
27922			return rect.bottom > bottom &&
27923				rect.right > 0 &&
27924				rect.left < rectHtml.width &&
27925				rect.top < top;
27926		},
27927		grow: function (textarea) {
27928			var rows = textarea.rows;
27929			textarea.addEventListener("input", function () {
27930				(function (el) {
27931					el.style.height = 0;
27932					el.style.height = 'auto';
27933					el.rows = rows;
27934					while (el.scrollHeight > el.offsetHeight) {
27935						el.rows +=1;
27936					}
27937				}(this));
27938			});
27939		}
27940	};
27941}());

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.