PageSourceSearch

https://www.kimberlydivad.com/assets/portfolio-5d14a9ecb8bfbc4b8b0060a89488e12d.js

js kimberlydivad.com collected 2026-09-28 13:19:30 UTC 459,352 bytes, 15,258 lines download raw bytes

vendor: 11,242 bytes, lines 1-432
1/*!
2 * jQuery JavaScript Library v1.10.2
3 * http://jquery.com/
4 *
5 * Includes Sizzle.js
6 * http://sizzlejs.com/
7 *
8 * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
9 * Released under the MIT license
10 * http://jquery.org/license
11 *
12 * Date: 2013-07-03T13:48Z
13 */
14
15(function( window, undefined ) {
16
17// Can't do this because several apps including ASP.NET trace
18// the stack via arguments.caller.callee and Firefox dies if
19// you try to trace through "use strict" call chains. (#13335)
20// Support: Firefox 18+
21//"use strict";
22var
23	// The deferred used on DOM ready
24	readyList,
25
26	// A central reference to the root jQuery(document)
27	rootjQuery,
28
29	// Support: IE<10
30	// For `typeof xmlNode.method` instead of `xmlNode.method !== undefined`
31	core_strundefined = typeof undefined,
32
33	// Use the correct document accordingly with window argument (sandbox)
34	location = window.location,
35	document = window.document,
36	docElem = document.documentElement,
37
38	// Map over jQuery in case of overwrite
39	_jQuery = window.jQuery,
40
41	// Map over the $ in case of overwrite
42	_$ = window.$,
43
44	// [[Class]] -> type pairs
45	class2type = {},
46
47	// List of deleted data cache ids, so we can reuse them
48	core_deletedIds = [],
49
50	core_version = "1.10.2",
51
52	// Save a reference to some core methods
53	core_concat = core_deletedIds.concat,
54	core_push = core_deletedIds.push,
55	core_slice = core_deletedIds.slice,
56	core_indexOf = core_deletedIds.indexOf,
57	core_toString = class2type.toString,
58	core_hasOwn = class2type.hasOwnProperty,
59	core_trim = core_version.trim,
60
61	// Define a local copy of jQuery
62	jQuery = function( selector, context ) {
63		// The jQuery object is actually just the init constructor 'enhanced'
64		return new jQuery.fn.init( selector, context, rootjQuery );
65	},
66
67	// Used for matching numbers
68	core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
69
70	// Used for splitting on whitespace
71	core_rnotwhite = /\S+/g,
72
73	// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
74	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
75
76	// A simple way to check for HTML strings
77	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
78	// Strict HTML recognition (#11290: must start with <)
79	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
80
81	// Match a standalone tag
82	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
83
84	// JSON RegExp
85	rvalidchars = /^[\],:{}\s]*$/,
86	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
87	rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
88	rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
89
90	// Matches dashed string for camelizing
91	rmsPrefix = /^-ms-/,
92	rdashAlpha = /-([\da-z])/gi,
93
94	// Used by jQuery.camelCase as callback to replace()
95	fcamelCase = function( all, letter ) {
96		return letter.toUpperCase();
97	},
98
99	// The ready event handler
100	completed = function( event ) {
101
102		// readyState === "complete" is good enough for us to call the dom ready in oldIE
103		if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
104			detach();
105			jQuery.ready();
106		}
107	},
108	// Clean-up method for dom ready events
109	detach = function() {
110		if ( document.addEventListener ) {
111			document.removeEventListener( "DOMContentLoaded", completed, false );
112			window.removeEventListener( "load", completed, false );
113
114		} else {
115			document.detachEvent( "onreadystatechange", completed );
116			window.detachEvent( "onload", completed );
117		}
118	};
119
120jQuery.fn = jQuery.prototype = {
121	// The current version of jQuery being used
122	jquery: core_version,
123
124	constructor: jQuery,
125	init: function( selector, context, rootjQuery ) {
126		var match, elem;
127
128		// HANDLE: $(""), $(null), $(undefined), $(false)
129		if ( !selector ) {
130			return this;
131		}
132
133		// Handle HTML strings
134		if ( typeof selector === "string" ) {
135			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
136				// Assume that strings that start and end with <> are HTML and skip the regex check
137				match = [ null, selector, null ];
138
139			} else {
140				match = rquickExpr.exec( selector );
141			}
142
143			// Match html or make sure no context is specified for #id
144			if ( match && (match[1] || !context) ) {
145
146				// HANDLE: $(html) -> $(array)
147				if ( match[1] ) {
148					context = context instanceof jQuery ? context[0] : context;
149
150					// scripts is true for back-compat
151					jQuery.merge( this, jQuery.parseHTML(
152						match[1],
153						context && context.nodeType ? context.ownerDocument || context : document,
154						true
155					) );
156
157					// HANDLE: $(html, props)
158					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
159						for ( match in context ) {
160							// Properties of context are called as methods if possible
161							if ( jQuery.isFunction( this[ match ] ) ) {
162								this[ match ]( context[ match ] );
163
164							// ...and otherwise set as attributes
165							} else {
166								this.attr( match, context[ match ] );
167							}
168						}
169					}
170
171					return this;
172
173				// HANDLE: $(#id)
174				} else {
175					elem = document.getElementById( match[2] );
176
177					// Check parentNode to catch when Blackberry 4.6 returns
178					// nodes that are no longer in the document #6963
179					if ( elem && elem.parentNode ) {
180						// Handle the case where IE and Opera return items
181						// by name instead of ID
182						if ( elem.id !== match[2] ) {
183							return rootjQuery.find( selector );
184						}
185
186						// Otherwise, we inject the element directly into the jQuery object
187						this.length = 1;
188						this[0] = elem;
189					}
190
191					this.context = document;
192					this.selector = selector;
193					return this;
194				}
195
196			// HANDLE: $(expr, $(...))
197			} else if ( !context || context.jquery ) {
198				return ( context || rootjQuery ).find( selector );
199
200			// HANDLE: $(expr, context)
201			// (which is just equivalent to: $(context).find(expr)
202			} else {
203				return this.constructor( context ).find( selector );
204			}
205
206		// HANDLE: $(DOMElement)
207		} else if ( selector.nodeType ) {
208			this.context = this[0] = selector;
209			this.length = 1;
210			return this;
211
212		// HANDLE: $(function)
213		// Shortcut for document ready
214		} else if ( jQuery.isFunction( selector ) ) {
215			return rootjQuery.ready( selector );
216		}
217
218		if ( selector.selector !== undefined ) {
219			this.selector = selector.selector;
220			this.context = selector.context;
221		}
222
223		return jQuery.makeArray( selector, this );
224	},
225
226	// Start with an empty selector
227	selector: "",
228
229	// The default length of a jQuery object is 0
230	length: 0,
231
232	toArray: function() {
233		return core_slice.call( this );
234	},
235
236	// Get the Nth element in the matched element set OR
237	// Get the whole matched element set as a clean array
238	get: function( num ) {
239		return num == null ?
240
241			// Return a 'clean' array
242			this.toArray() :
243
244			// Return just the object
245			( num < 0 ? this[ this.length + num ] : this[ num ] );
246	},
247
248	// Take an array of elements and push it onto the stack
249	// (returning the new matched element set)
250	pushStack: function( elems ) {
251
252		// Build a new jQuery matched element set
253		var ret = jQuery.merge( this.constructor(), elems );
254
255		// Add the old object onto the stack (as a reference)
256		ret.prevObject = this;
257		ret.context = this.context;
258
259		// Return the newly-formed element set
260		return ret;
261	},
262
263	// Execute a callback for every element in the matched set.
264	// (You can seed the arguments with an array of args, but this is
265	// only used internally.)
266	each: function( callback, args ) {
267		return jQuery.each( this, callback, args );
268	},
269
270	ready: function( fn ) {
271		// Add the callback
272		jQuery.ready.promise().done( fn );
273
274		return this;
275	},
276
277	slice: function() {
278		return this.pushStack( core_slice.apply( this, arguments ) );
279	},
280
281	first: function() {
282		return this.eq( 0 );
283	},
284
285	last: function() {
286		return this.eq( -1 );
287	},
288
289	eq: function( i ) {
290		var len = this.length,
291			j = +i + ( i < 0 ? len : 0 );
292		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
293	},
294
295	map: function( callback ) {
296		return this.pushStack( jQuery.map(this, function( elem, i ) {
297			return callback.call( elem, i, elem );
298		}));
299	},
300
301	end: function() {
302		return this.prevObject || this.constructor(null);
303	},
304
305	// For internal use only.
306	// Behaves like an Array's method, not like a jQuery method.
307	push: core_push,
308	sort: [].sort,
309	splice: [].splice
310};
311
312// Give the init function the jQuery prototype for later instantiation
313jQuery.fn.init.prototype = jQuery.fn;
314
315jQuery.extend = jQuery.fn.extend = function() {
316	var src, copyIsArray, copy, name, options, clone,
317		target = arguments[0] || {},
318		i = 1,
319		length = arguments.length,
320		deep = false;
321
322	// Handle a deep copy situation
323	if ( typeof target === "boolean" ) {
324		deep = target;
325		target = arguments[1] || {};
326		// skip the boolean and the target
327		i = 2;
328	}
329
330	// Handle case when target is a string or something (possible in deep copy)
331	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
332		target = {};
333	}
334
335	// extend jQuery itself if only one argument is passed
336	if ( length === i ) {
337		target = this;
338		--i;
339	}
340
341	for ( ; i < length; i++ ) {
342		// Only deal with non-null/undefined values
343		if ( (options = arguments[ i ]) != null ) {
344			// Extend the base object
345			for ( name in options ) {
346				src = target[ name ];
347				copy = options[ name ];
348
349				// Prevent never-ending loop
350				if ( target === copy ) {
351					continue;
352				}
353
354				// Recurse if we're merging plain objects or arrays
355				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
356					if ( copyIsArray ) {
357						copyIsArray = false;
358						clone = src && jQuery.isArray(src) ? src : [];
359
360					} else {
361						clone = src && jQuery.isPlainObject(src) ? src : {};
362					}
363
364					// Never move original objects, clone them
365					target[ name ] = jQuery.extend( deep, clone, copy );
366
367				// Don't bring in undefined values
368				} else if ( copy !== undefined ) {
369					target[ name ] = copy;
370				}
371			}
372		}
373	}
374
375	// Return the modified object
376	return target;
377};
378
379jQuery.extend({
380	// Unique for each copy of jQuery on the page
381	// Non-digits removed to match rinlinejQuery
382	expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
383
384	noConflict: function( deep ) {
385		if ( window.$ === jQuery ) {
386			window.$ = _$;
387		}
388
389		if ( deep && window.jQuery === jQuery ) {
390			window.jQuery = _jQuery;
391		}
392
393		return jQuery;
394	},
395
396	// Is the DOM ready to be used? Set to true once it occurs.
397	isReady: false,
398
399	// A counter to track how many items to wait for before
400	// the ready event fires. See #6781
401	readyWait: 1,
402
403	// Hold (or release) the ready event
404	holdReady: function( hold ) {
405		if ( hold ) {
406			jQuery.readyWait++;
407		} else {
408			jQuery.ready( true );
409		}
410	},
411
412	// Handle when the DOM is ready
413	ready: function( wait ) {
414
415		// Abort if there are pending holds or we're already ready
416		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
417			return;
418		}
419
420		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
421		if ( !document.body ) {
422			return setTimeout( jQuery.ready );
423		}
424
425		// Remember that the DOM is ready
426		jQuery.isReady = true;
427
428		// If a normal DOM Ready event fired, decrement, and wait if need be
429		if ( wait !== true && --jQuery.readyWait > 0 ) {
430			return;
431		}
432
433		// If there are functions bound, to execute
434		readyList.resolveWith( document, [ jQuery ] );
435
436		// Trigger any bound ready events
437		if ( jQuery.fn.trigger ) {
438			jQuery( document ).trigger("ready").off("ready");
439		}
440	},
441
442	// See test/unit/core.js for details concerning isFunction.
443	// Since version 1.3, DOM methods and functions like alert
444	// aren't supported. They return false on IE (#2968).
445	isFunction: function( obj ) {
446		return jQuery.type(obj) === "function";
447	},
448
449	isArray: Array.isArray || function( obj ) {
450		return jQuery.type(obj) === "array";
451	},
452
453	isWindow: function( obj ) {
454		/* jshint eqeqeq: false */
455		return obj != null && obj == obj.window;
456	},
457
458	isNumeric: function( obj ) {
459		return !isNaN( parseFloat(obj) ) && isFinite( obj );
460	},
461
462	type: function( obj ) {
463		if ( obj == null ) {
464			return String( obj );
465		}
466		return typeof obj === "object" || typeof obj === "function" ?
467			class2type[ core_toString.call(obj) ] || "object" :
468			typeof obj;
469	},
470
471	isPlainObject: function( obj ) {
472		var key;
473
474		// Must be an Object.
475		// Because of IE, we also have to check the presence of the constructor property.
476		// Make sure that DOM nodes and window objects don't pass through, as well
477		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
478			return false;
479		}
480
481		try {
482			// Not own constructor property must be Object
483			if ( obj.constructor &&
484				!core_hasOwn.call(obj, "constructor") &&
485				!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
486				return false;
487			}
488		} catch ( e ) {
489			// IE8,9 Will throw exceptions on certain host objects #9897
490			return false;
491		}
492
493		// Support: IE<9
494		// Handle iteration over inherited properties before own properties.
495		if ( jQuery.support.ownLast ) {
496			for ( key in obj ) {
497				return core_hasOwn.call( obj, key );
498			}
499		}
500
501		// Own properties are enumerated firstly, so to speed up,
502		// if last one is own, then all properties are own.
503		for ( key in obj ) {}
504
505		return key === undefined || core_hasOwn.call( obj, key );
506	},
507
508	isEmptyObject: function( obj ) {
509		var name;
510		for ( name in obj ) {
511			return false;
512		}
513		return true;
514	},
515
516	error: function( msg ) {
517		throw new Error( msg );
518	},
519
520	// data: string of html
521	// context (optional): If specified, the fragment will be created in this context, defaults to document
522	// keepScripts (optional): If true, will include scripts passed in the html string
523	parseHTML: function( data, context, keepScripts ) {
524		if ( !data || typeof data !== "string" ) {
525			return null;
526		}
527		if ( typeof context === "boolean" ) {
528			keepScripts = context;
529			context = false;
530		}
531		context = context || document;
532
533		var parsed = rsingleTag.exec( data ),
534			scripts = !keepScripts && [];
535
536		// Single tag
537		if ( parsed ) {
538			return [ context.createElement( parsed[1] ) ];
539		}
540
541		parsed = jQuery.buildFragment( [ data ], context, scripts );
542		if ( scripts ) {
543			jQuery( scripts ).remove();
544		}
545		return jQuery.merge( [], parsed.childNodes );
546	},
547
548	parseJSON: function( data ) {
549		// Attempt to parse using the native JSON parser first
550		if ( window.JSON && window.JSON.parse ) {
551			return window.JSON.parse( data );
552		}
553
554		if ( data === null ) {
555			return data;
556		}
557
558		if ( typeof data === "string" ) {
559
560			// Make sure leading/trailing whitespace is removed (IE can't handle it)
561			data = jQuery.trim( data );
562
563			if ( data ) {
564				// Make sure the incoming data is actual JSON
565				// Logic borrowed from http://json.org/json2.js
566				if ( rvalidchars.test( data.replace( rvalidescape, "@" )
567					.replace( rvalidtokens, "]" )
568					.replace( rvalidbraces, "")) ) {
569
570					return ( new Function( "return " + data ) )();
571				}
572			}
573		}
574
575		jQuery.error( "Invalid JSON: " + data );
576	},
577
578	// Cross-browser xml parsing
579	parseXML: function( data ) {
580		var xml, tmp;
581		if ( !data || typeof data !== "string" ) {
582			return null;
583		}
584		try {
585			if ( window.DOMParser ) { // Standard
586				tmp = new DOMParser();
587				xml = tmp.parseFromString( data , "text/xml" );
588			} else { // IE
589				xml = new ActiveXObject( "Microsoft.XMLDOM" );
590				xml.async = "false";
591				xml.loadXML( data );
592			}
593		} catch( e ) {
594			xml = undefined;
595		}
596		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
597			jQuery.error( "Invalid XML: " + data );
598		}
599		return xml;
600	},
601
602	noop: function() {},
603
604	// Evaluates a script in a global context
605	// Workarounds based on findings by Jim Driscoll
606	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
607	globalEval: function( data ) {
608		if ( data && jQuery.trim( data ) ) {
609			// We use execScript on Internet Explorer
610			// We use an anonymous function so that context is window
611			// rather than jQuery in Firefox
612			( window.execScript || function( data ) {
613				window[ "eval" ].call( window, data );
614			} )( data );
615		}
616	},
617
618	// Convert dashed to camelCase; used by the css and data modules
619	// Microsoft forgot to hump their vendor prefix (#9572)
620	camelCase: function( string ) {
621		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
622	},
623
624	nodeName: function( elem, name ) {
625		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
626	},
627
628	// args is for internal usage only
629	each: function( obj, callback, args ) {
630		var value,
631			i = 0,
632			length = obj.length,
633			isArray = isArraylike( obj );
634
635		if ( args ) {
636			if ( isArray ) {
637				for ( ; i < length; i++ ) {
638					value = callback.apply( obj[ i ], args );
639
640					if ( value === false ) {
641						break;
642					}
643				}
644			} else {
645				for ( i in obj ) {
646					value = callback.apply( obj[ i ], args );
647
648					if ( value === false ) {
649						break;
650					}
651				}
652			}
653
654		// A special, fast, case for the most common use of each
655		} else {
656			if ( isArray ) {
657				for ( ; i < length; i++ ) {
658					value = callback.call( obj[ i ], i, obj[ i ] );
659
660					if ( value === false ) {
661						break;
662					}
663				}
664			} else {
665				for ( i in obj ) {
666					value = callback.call( obj[ i ], i, obj[ i ] );
667
668					if ( value === false ) {
669						break;
670					}
671				}
672			}
673		}
674
675		return obj;
676	},
677
678	// Use native String.trim function wherever possible
679	trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
680		function( text ) {
681			return text == null ?
682				"" :
683				core_trim.call( text );
684		} :
685
686		// Otherwise use our own trimming functionality
687		function( text ) {
688			return text == null ?
689				"" :
690				( text + "" ).replace( rtrim, "" );
691		},
692
693	// results is for internal usage only
694	makeArray: function( arr, results ) {
695		var ret = results || [];
696
697		if ( arr != null ) {
698			if ( isArraylike( Object(arr) ) ) {
699				jQuery.merge( ret,
700					typeof arr === "string" ?
701					[ arr ] : arr
702				);
703			} else {
704				core_push.call( ret, arr );
705			}
706		}
707
708		return ret;
709	},
710
711	inArray: function( elem, arr, i ) {
712		var len;
713
714		if ( arr ) {
715			if ( core_indexOf ) {
716				return core_indexOf.call( arr, elem, i );
717			}
718
719			len = arr.length;
720			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
721
722			for ( ; i < len; i++ ) {
723				// Skip accessing in sparse arrays
724				if ( i in arr && arr[ i ] === elem ) {
725					return i;
726				}
727			}
728		}
729
730		return -1;
731	},
732
733	merge: function( first, second ) {
734		var l = second.length,
735			i = first.length,
736			j = 0;
737
738		if ( typeof l === "number" ) {
739			for ( ; j < l; j++ ) {
740				first[ i++ ] = second[ j ];
741			}
742		} else {
743			while ( second[j] !== undefined ) {
744				first[ i++ ] = second[ j++ ];
745			}
746		}
747
748		first.length = i;
749
750		return first;
751	},
752
753	grep: function( elems, callback, inv ) {
754		var retVal,
755			ret = [],
756			i = 0,
757			length = elems.length;
758		inv = !!inv;
759
760		// Go through the array, only saving the items
761		// that pass the validator function
762		for ( ; i < length; i++ ) {
763			retVal = !!callback( elems[ i ], i );
764			if ( inv !== retVal ) {
765				ret.push( elems[ i ] );
766			}
767		}
768
769		return ret;
770	},
771
772	// arg is for internal usage only
773	map: function( elems, callback, arg ) {
774		var value,
775			i = 0,
776			length = elems.length,
777			isArray = isArraylike( elems ),
778			ret = [];
779
780		// Go through the array, translating each of the items to their
781		if ( isArray ) {
782			for ( ; i < length; i++ ) {
783				value = callback( elems[ i ], i, arg );
784
785				if ( value != null ) {
786					ret[ ret.length ] = value;
787				}
788			}
789
790		// Go through every key on the object,
791		} else {
792			for ( i in elems ) {
793				value = callback( elems[ i ], i, arg );
794
795				if ( value != null ) {
796					ret[ ret.length ] = value;
797				}
798			}
799		}
800
801		// Flatten any nested arrays
802		return core_concat.apply( [], ret );
803	},
804
805	// A global GUID counter for objects
806	guid: 1,
807
808	// Bind a function to a context, optionally partially applying any
809	// arguments.
810	proxy: function( fn, context ) {
811		var args, proxy, tmp;
812
813		if ( typeof context === "string" ) {
814			tmp = fn[ context ];
815			context = fn;
816			fn = tmp;
817		}
818
819		// Quick check to determine if target is callable, in the spec
820		// this throws a TypeError, but we will just return undefined.
821		if ( !jQuery.isFunction( fn ) ) {
822			return undefined;
823		}
824
825		// Simulated bind
826		args = core_slice.call( arguments, 2 );
827		proxy = function() {
828			return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
829		};
830
831		// Set the guid of unique handler to the same of original handler, so it can be removed
832		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
833
834		return proxy;
835	},
836
837	// Multifunctional method to get and set values of a collection
838	// The value/s can optionally be executed if it's a function
839	access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
840		var i = 0,
841			length = elems.length,
842			bulk = key == null;
843
844		// Sets many values
845		if ( jQuery.type( key ) === "object" ) {
846			chainable = true;
847			for ( i in key ) {
848				jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
849			}
850
851		// Sets one value
852		} else if ( value !== undefined ) {
853			chainable = true;
854
855			if ( !jQuery.isFunction( value ) ) {
856				raw = true;
857			}
858
859			if ( bulk ) {
860				// Bulk operations run against the entire set
861				if ( raw ) {
862					fn.call( elems, value );
863					fn = null;
864
865				// ...except when executing function values
866				} else {
867					bulk = fn;
868					fn = function( elem, key, value ) {
869						return bulk.call( jQuery( elem ), value );
870					};
871				}
872			}
873
874			if ( fn ) {
875				for ( ; i < length; i++ ) {
876					fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
877				}
878			}
879		}
880
881		return chainable ?
882			elems :
883
884			// Gets
885			bulk ?
886				fn.call( elems ) :
887				length ? fn( elems[0], key ) : emptyGet;
888	},
889
890	now: function() {
891		return ( new Date() ).getTime();
892	},
893
894	// A method for quickly swapping in/out CSS properties to get correct calculations.
895	// Note: this method belongs to the css module but it's needed here for the support module.
896	// If support gets modularized, this method should be moved back to the css module.
897	swap: function( elem, options, callback, args ) {
898		var ret, name,
899			old = {};
900
901		// Remember the old values, and insert the new ones
902		for ( name in options ) {
903			old[ name ] = elem.style[ name ];
904			elem.style[ name ] = options[ name ];
905		}
906
907		ret = callback.apply( elem, args || [] );
908
909		// Revert the old values
910		for ( name in options ) {
911			elem.style[ name ] = old[ name ];
912		}
913
914		return ret;
915	}
916});
917
918jQuery.ready.promise = function( obj ) {
919	if ( !readyList ) {
920
921		readyList = jQuery.Deferred();
922
923		// Catch cases where $(document).ready() is called after the browser event has already occurred.
924		// we once tried to use readyState "interactive" here, but it caused issues like the one
925		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
926		if ( document.readyState === "complete" ) {
927			// Handle it asynchronously to allow scripts the opportunity to delay ready
928			setTimeout( jQuery.ready );
929
930		// Standards-based browsers support DOMContentLoaded
931		} else if ( document.addEventListener ) {
932			// Use the handy event callback
933			document.addEventListener( "DOMContentLoaded", completed, false );
934
935			// A fallback to window.onload, that will always work
936			window.addEventListener( "load", completed, false );
937
938		// If IE event model is used
939		} else {
940			// Ensure firing before onload, maybe late but safe also for iframes
941			document.attachEvent( "onreadystatechange", completed );
942
943			// A fallback to window.onload, that will always work
944			window.attachEvent( "onload", completed );
945
946			// If IE and not a frame
947			// continually check to see if the document is ready
948			var top = false;
949
950			try {
951				top = window.frameElement == null && document.documentElement;
952			} catch(e) {}
953
954			if ( top && top.doScroll ) {
955				(function doScrollCheck() {
956					if ( !jQuery.isReady ) {
957
958						try {
959							// Use the trick by Diego Perini
960							// http://javascript.nwbox.com/IEContentLoaded/
961							top.doScroll("left");
962						} catch(e) {
963							return setTimeout( doScrollCheck, 50 );
964						}
965
966						// detach all dom ready events
967						detach();
968
969						// and execute any waiting functions
970						jQuery.ready();
971					}
972				})();
973			}
974		}
975	}
976	return readyList.promise( obj );
977};
978
979// Populate the class2type map
980jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
981	class2type[ "[object " + name + "]" ] = name.toLowerCase();
982});
983
984function isArraylike( obj ) {
985	var length = obj.length,
986		type = jQuery.type( obj );
987
988	if ( jQuery.isWindow( obj ) ) {
989		return false;
990	}
991
992	if ( obj.nodeType === 1 && length ) {
993		return true;
994	}
995
996	return type === "array" || type !== "function" &&
997		( length === 0 ||
998		typeof length === "number" && length > 0 && ( length - 1 ) in obj );
999}
1000
1001// All jQuery objects should point back to these
1002rootjQuery = jQuery(document);
1003/*!
1004 * Sizzle CSS Selector Engine v1.10.2
1005 * http://sizzlejs.com/
1006 *
1007 * Copyright 2013 jQuery Foundation, Inc. and other contributors
1008 * Released under the MIT license
1009 * http://jquery.org/license
1010 *
1011 * Date: 2013-07-03
1012 */
1013(function( window, undefined ) {
1014
1015var i,
1016	support,
1017	cachedruns,
1018	Expr,
1019	getText,
1020	isXML,
1021	compile,
1022	outermostContext,
1023	sortInput,
1024
1025	// Local document vars
1026	setDocument,
1027	document,
1028	docElem,
1029	documentIsHTML,
1030	rbuggyQSA,
1031	rbuggyMatches,
1032	matches,
1033	contains,
1034
1035	// Instance-specific data
1036	expando = "sizzle" + -(new Date()),
1037	preferredDoc = window.document,
1038	dirruns = 0,
1039	done = 0,
1040	classCache = createCache(),
1041	tokenCache = createCache(),
1042	compilerCache = createCache(),
1043	hasDuplicate = false,
1044	sortOrder = function( a, b ) {
1045		if ( a === b ) {
1046			hasDuplicate = true;
1047			return 0;
1048		}
1049		return 0;
1050	},
1051
1052	// General-purpose constants
1053	strundefined = typeof undefined,
1054	MAX_NEGATIVE = 1 << 31,
1055
1056	// Instance methods
1057	hasOwn = ({}).hasOwnProperty,
1058	arr = [],
1059	pop = arr.pop,
1060	push_native = arr.push,
1061	push = arr.push,
1062	slice = arr.slice,
1063	// Use a stripped-down indexOf if we can't use a native one
1064	indexOf = arr.indexOf || function( elem ) {
1065		var i = 0,
1066			len = this.length;
1067		for ( ; i < len; i++ ) {
1068			if ( this[i] === elem ) {
1069				return i;
1070			}
1071		}
1072		return -1;
1073	},
1074
1075	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
1076
1077	// Regular expressions
1078
1079	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
1080	whitespace = "[\\x20\\t\\r\\n\\f]",
1081	// http://www.w3.org/TR/css3-syntax/#characters
1082	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
1083
1084	// Loosely modeled on CSS identifier characters
1085	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
1086	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
1087	identifier = characterEncoding.replace( "w", "w#" ),
1088
1089	// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
1090	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
1091		"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
1092
1093	// Prefer arguments quoted,
1094	//   then not containing pseudos/brackets,
1095	//   then attribute selectors/non-parenthetical expressions,
1096	//   then anything else
1097	// These preferences are here to reduce the number of selectors
1098	//   needing tokenize in the PSEUDO preFilter
1099	pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
1100
1101	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
1102	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
1103
1104	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
1105	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
1106
1107	rsibling = new RegExp( whitespace + "*[+~]" ),
1108	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ),
1109
1110	rpseudo = new RegExp( pseudos ),
1111	ridentifier = new RegExp( "^" + identifier + "$" ),
1112
1113	matchExpr = {
1114		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
1115		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
1116		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
1117		"ATTR": new RegExp( "^" + attributes ),
1118		"PSEUDO": new RegExp( "^" + pseudos ),
1119		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
1120			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
1121			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
1122		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
1123		// For use in libraries implementing .is()
1124		// We use this for POS matching in `select`
1125		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
1126			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
1127	},
1128
1129	rnative = /^[^{]+\{\s*\[native \w/,
1130
vendor: 21,121 bytes, lines 1131-1895
1131	// Easily-parseable/retrievable ID or TAG or CLASS selectors
1132	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
1133
1134	rinputs = /^(?:input|select|textarea|button)$/i,
1135	rheader = /^h\d$/i,
1136
1137	rescape = /'|\\/g,
1138
1139	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
1140	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
1141	funescape = function( _, escaped, escapedWhitespace ) {
1142		var high = "0x" + escaped - 0x10000;
1143		// NaN means non-codepoint
1144		// Support: Firefox
1145		// Workaround erroneous numeric interpretation of +"0x"
1146		return high !== high || escapedWhitespace ?
1147			escaped :
1148			// BMP codepoint
1149			high < 0 ?
1150				String.fromCharCode( high + 0x10000 ) :
1151				// Supplemental Plane codepoint (surrogate pair)
1152				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
1153	};
1154
1155// Optimize for push.apply( _, NodeList )
1156try {
1157	push.apply(
1158		(arr = slice.call( preferredDoc.childNodes )),
1159		preferredDoc.childNodes
1160	);
1161	// Support: Android<4.0
1162	// Detect silently failing push.apply
1163	arr[ preferredDoc.childNodes.length ].nodeType;
1164} catch ( e ) {
1165	push = { apply: arr.length ?
1166
1167		// Leverage slice if possible
1168		function( target, els ) {
1169			push_native.apply( target, slice.call(els) );
1170		} :
1171
1172		// Support: IE<9
1173		// Otherwise append directly
1174		function( target, els ) {
1175			var j = target.length,
1176				i = 0;
1177			// Can't trust NodeList.length
1178			while ( (target[j++] = els[i++]) ) {}
1179			target.length = j - 1;
1180		}
1181	};
1182}
1183
1184function Sizzle( selector, context, results, seed ) {
1185	var match, elem, m, nodeType,
1186		// QSA vars
1187		i, groups, old, nid, newContext, newSelector;
1188
1189	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
1190		setDocument( context );
1191	}
1192
1193	context = context || document;
1194	results = results || [];
1195
1196	if ( !selector || typeof selector !== "string" ) {
1197		return results;
1198	}
1199
1200	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
1201		return [];
1202	}
1203
1204	if ( documentIsHTML && !seed ) {
1205
1206		// Shortcuts
1207		if ( (match = rquickExpr.exec( selector )) ) {
1208			// Speed-up: Sizzle("#ID")
1209			if ( (m = match[1]) ) {
1210				if ( nodeType === 9 ) {
1211					elem = context.getElementById( m );
1212					// Check parentNode to catch when Blackberry 4.6 returns
1213					// nodes that are no longer in the document #6963
1214					if ( elem && elem.parentNode ) {
1215						// Handle the case where IE, Opera, and Webkit return items
1216						// by name instead of ID
1217						if ( elem.id === m ) {
1218							results.push( elem );
1219							return results;
1220						}
1221					} else {
1222						return results;
1223					}
1224				} else {
1225					// Context is not a document
1226					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
1227						contains( context, elem ) && elem.id === m ) {
1228						results.push( elem );
1229						return results;
1230					}
1231				}
1232
1233			// Speed-up: Sizzle("TAG")
1234			} else if ( match[2] ) {
1235				push.apply( results, context.getElementsByTagName( selector ) );
1236				return results;
1237
1238			// Speed-up: Sizzle(".CLASS")
1239			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
1240				push.apply( results, context.getElementsByClassName( m ) );
1241				return results;
1242			}
1243		}
1244
1245		// QSA path
1246		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
1247			nid = old = expando;
1248			newContext = context;
1249			newSelector = nodeType === 9 && selector;
1250
1251			// qSA works strangely on Element-rooted queries
1252			// We can work around this by specifying an extra ID on the root
1253			// and working up from there (Thanks to Andrew Dupont for the technique)
1254			// IE 8 doesn't work on object elements
1255			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
1256				groups = tokenize( selector );
1257
1258				if ( (old = context.getAttribute("id")) ) {
1259					nid = old.replace( rescape, "\\$&" );
1260				} else {
1261					context.setAttribute( "id", nid );
1262				}
1263				nid = "[id='" + nid + "'] ";
1264
1265				i = groups.length;
1266				while ( i-- ) {
1267					groups[i] = nid + toSelector( groups[i] );
1268				}
1269				newContext = rsibling.test( selector ) && context.parentNode || context;
1270				newSelector = groups.join(",");
1271			}
1272
1273			if ( newSelector ) {
1274				try {
1275					push.apply( results,
1276						newContext.querySelectorAll( newSelector )
1277					);
1278					return results;
1279				} catch(qsaError) {
1280				} finally {
1281					if ( !old ) {
1282						context.removeAttribute("id");
1283					}
1284				}
1285			}
1286		}
1287	}
1288
1289	// All others
1290	return select( selector.replace( rtrim, "$1" ), context, results, seed );
1291}
1292
1293/**
1294 * Create key-value caches of limited size
1295 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
1296 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
1297 *	deleting the oldest entry
1298 */
1299function createCache() {
1300	var keys = [];
1301
1302	function cache( key, value ) {
1303		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
1304		if ( keys.push( key += " " ) > Expr.cacheLength ) {
1305			// Only keep the most recent entries
1306			delete cache[ keys.shift() ];
1307		}
1308		return (cache[ key ] = value);
1309	}
1310	return cache;
1311}
1312
1313/**
1314 * Mark a function for special use by Sizzle
1315 * @param {Function} fn The function to mark
1316 */
1317function markFunction( fn ) {
1318	fn[ expando ] = true;
1319	return fn;
1320}
1321
1322/**
1323 * Support testing using an element
1324 * @param {Function} fn Passed the created div and expects a boolean result
1325 */
1326function assert( fn ) {
1327	var div = document.createElement("div");
1328
1329	try {
1330		return !!fn( div );
1331	} catch (e) {
1332		return false;
1333	} finally {
1334		// Remove from its parent by default
1335		if ( div.parentNode ) {
1336			div.parentNode.removeChild( div );
1337		}
1338		// release memory in IE
1339		div = null;
1340	}
1341}
1342
1343/**
1344 * Adds the same handler for all of the specified attrs
1345 * @param {String} attrs Pipe-separated list of attributes
1346 * @param {Function} handler The method that will be applied
1347 */
1348function addHandle( attrs, handler ) {
1349	var arr = attrs.split("|"),
1350		i = attrs.length;
1351
1352	while ( i-- ) {
1353		Expr.attrHandle[ arr[i] ] = handler;
1354	}
1355}
1356
1357/**
1358 * Checks document order of two siblings
1359 * @param {Element} a
1360 * @param {Element} b
1361 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
1362 */
1363function siblingCheck( a, b ) {
1364	var cur = b && a,
1365		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
1366			( ~b.sourceIndex || MAX_NEGATIVE ) -
1367			( ~a.sourceIndex || MAX_NEGATIVE );
1368
1369	// Use IE sourceIndex if available on both nodes
1370	if ( diff ) {
1371		return diff;
1372	}
1373
1374	// Check if b follows a
1375	if ( cur ) {
1376		while ( (cur = cur.nextSibling) ) {
1377			if ( cur === b ) {
1378				return -1;
1379			}
1380		}
1381	}
1382
1383	return a ? 1 : -1;
1384}
1385
1386/**
1387 * Returns a function to use in pseudos for input types
1388 * @param {String} type
1389 */
1390function createInputPseudo( type ) {
1391	return function( elem ) {
1392		var name = elem.nodeName.toLowerCase();
1393		return name === "input" && elem.type === type;
1394	};
1395}
1396
1397/**
1398 * Returns a function to use in pseudos for buttons
1399 * @param {String} type
1400 */
1401function createButtonPseudo( type ) {
1402	return function( elem ) {
1403		var name = elem.nodeName.toLowerCase();
1404		return (name === "input" || name === "button") && elem.type === type;
1405	};
1406}
1407
1408/**
1409 * Returns a function to use in pseudos for positionals
1410 * @param {Function} fn
1411 */
1412function createPositionalPseudo( fn ) {
1413	return markFunction(function( argument ) {
1414		argument = +argument;
1415		return markFunction(function( seed, matches ) {
1416			var j,
1417				matchIndexes = fn( [], seed.length, argument ),
1418				i = matchIndexes.length;
1419
1420			// Match elements found at the specified indexes
1421			while ( i-- ) {
1422				if ( seed[ (j = matchIndexes[i]) ] ) {
1423					seed[j] = !(matches[j] = seed[j]);
1424				}
1425			}
1426		});
1427	});
1428}
1429
1430/**
1431 * Detect xml
1432 * @param {Element|Object} elem An element or a document
1433 */
1434isXML = Sizzle.isXML = function( elem ) {
1435	// documentElement is verified for cases where it doesn't yet exist
1436	// (such as loading iframes in IE - #4833)
1437	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1438	return documentElement ? documentElement.nodeName !== "HTML" : false;
1439};
1440
1441// Expose support vars for convenience
1442support = Sizzle.support = {};
1443
1444/**
1445 * Sets document-related variables once based on the current document
1446 * @param {Element|Object} [doc] An element or document object to use to set the document
1447 * @returns {Object} Returns the current document
1448 */
1449setDocument = Sizzle.setDocument = function( node ) {
1450	var doc = node ? node.ownerDocument || node : preferredDoc,
1451		parent = doc.defaultView;
1452
1453	// If no document and documentElement is available, return
1454	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1455		return document;
1456	}
1457
1458	// Set our document
1459	document = doc;
1460	docElem = doc.documentElement;
1461
1462	// Support tests
1463	documentIsHTML = !isXML( doc );
1464
1465	// Support: IE>8
1466	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
1467	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
1468	// IE6-8 do not support the defaultView property so parent will be undefined
1469	if ( parent && parent.attachEvent && parent !== parent.top ) {
1470		parent.attachEvent( "onbeforeunload", function() {
1471			setDocument();
1472		});
1473	}
1474
1475	/* Attributes
1476	---------------------------------------------------------------------- */
1477
1478	// Support: IE<8
1479	// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
1480	support.attributes = assert(function( div ) {
1481		div.className = "i";
1482		return !div.getAttribute("className");
1483	});
1484
1485	/* getElement(s)By*
1486	---------------------------------------------------------------------- */
1487
1488	// Check if getElementsByTagName("*") returns only elements
1489	support.getElementsByTagName = assert(function( div ) {
1490		div.appendChild( doc.createComment("") );
1491		return !div.getElementsByTagName("*").length;
1492	});
1493
1494	// Check if getElementsByClassName can be trusted
1495	support.getElementsByClassName = assert(function( div ) {
1496		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
1497
1498		// Support: Safari<4
1499		// Catch class over-caching
1500		div.firstChild.className = "i";
1501		// Support: Opera<10
1502		// Catch gEBCN failure to find non-leading classes
1503		return div.getElementsByClassName("i").length === 2;
1504	});
1505
1506	// Support: IE<10
1507	// Check if getElementById returns elements by name
1508	// The broken getElementById methods don't pick up programatically-set names,
1509	// so use a roundabout getElementsByName test
1510	support.getById = assert(function( div ) {
1511		docElem.appendChild( div ).id = expando;
1512		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
1513	});
1514
1515	// ID find and filter
1516	if ( support.getById ) {
1517		Expr.find["ID"] = function( id, context ) {
1518			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
1519				var m = context.getElementById( id );
1520				// Check parentNode to catch when Blackberry 4.6 returns
1521				// nodes that are no longer in the document #6963
1522				return m && m.parentNode ? [m] : [];
1523			}
1524		};
1525		Expr.filter["ID"] = function( id ) {
1526			var attrId = id.replace( runescape, funescape );
1527			return function( elem ) {
1528				return elem.getAttribute("id") === attrId;
1529			};
1530		};
1531	} else {
1532		// Support: IE6/7
1533		// getElementById is not reliable as a find shortcut
1534		delete Expr.find["ID"];
1535
1536		Expr.filter["ID"] =  function( id ) {
1537			var attrId = id.replace( runescape, funescape );
1538			return function( elem ) {
1539				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
1540				return node && node.value === attrId;
1541			};
1542		};
1543	}
1544
1545	// Tag
1546	Expr.find["TAG"] = support.getElementsByTagName ?
1547		function( tag, context ) {
1548			if ( typeof context.getElementsByTagName !== strundefined ) {
1549				return context.getElementsByTagName( tag );
1550			}
1551		} :
1552		function( tag, context ) {
1553			var elem,
1554				tmp = [],
1555				i = 0,
1556				results = context.getElementsByTagName( tag );
1557
1558			// Filter out possible comments
1559			if ( tag === "*" ) {
1560				while ( (elem = results[i++]) ) {
1561					if ( elem.nodeType === 1 ) {
1562						tmp.push( elem );
1563					}
1564				}
1565
1566				return tmp;
1567			}
1568			return results;
1569		};
1570
1571	// Class
1572	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1573		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
1574			return context.getElementsByClassName( className );
1575		}
1576	};
1577
1578	/* QSA/matchesSelector
1579	---------------------------------------------------------------------- */
1580
1581	// QSA and matchesSelector support
1582
1583	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1584	rbuggyMatches = [];
1585
1586	// qSa(:focus) reports false when true (Chrome 21)
1587	// We allow this because of a bug in IE8/9 that throws an error
1588	// whenever `document.activeElement` is accessed on an iframe
1589	// So, we allow :focus to pass through QSA all the time to avoid the IE error
1590	// See http://bugs.jquery.com/ticket/13378
1591	rbuggyQSA = [];
1592
1593	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
1594		// Build QSA regex
1595		// Regex strategy adopted from Diego Perini
1596		assert(function( div ) {
1597			// Select is set to empty string on purpose
1598			// This is to test IE's treatment of not explicitly
1599			// setting a boolean content attribute,
1600			// since its presence should be enough
1601			// http://bugs.jquery.com/ticket/12359
1602			div.innerHTML = "<select><option selected=''></option></select>";
1603
1604			// Support: IE8
1605			// Boolean attributes and "value" are not treated correctly
1606			if ( !div.querySelectorAll("[selected]").length ) {
1607				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1608			}
1609
1610			// Webkit/Opera - :checked should return selected option elements
1611			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1612			// IE8 throws error here and will not see later tests
1613			if ( !div.querySelectorAll(":checked").length ) {
1614				rbuggyQSA.push(":checked");
1615			}
1616		});
1617
1618		assert(function( div ) {
1619
1620			// Support: Opera 10-12/IE8
1621			// ^= $= *= and empty values
1622			// Should not select anything
1623			// Support: Windows 8 Native Apps
1624			// The type attribute is restricted during .innerHTML assignment
1625			var input = doc.createElement("input");
1626			input.setAttribute( "type", "hidden" );
1627			div.appendChild( input ).setAttribute( "t", "" );
1628
1629			if ( div.querySelectorAll("[t^='']").length ) {
1630				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1631			}
1632
1633			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1634			// IE8 throws error here and will not see later tests
1635			if ( !div.querySelectorAll(":enabled").length ) {
1636				rbuggyQSA.push( ":enabled", ":disabled" );
1637			}
1638
1639			// Opera 10-11 does not throw on post-comma invalid pseudos
1640			div.querySelectorAll("*,:x");
1641			rbuggyQSA.push(",.*:");
1642		});
1643	}
1644
1645	if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
1646		docElem.mozMatchesSelector ||
1647		docElem.oMatchesSelector ||
1648		docElem.msMatchesSelector) )) ) {
1649
1650		assert(function( div ) {
1651			// Check to see if it's possible to do matchesSelector
1652			// on a disconnected node (IE 9)
1653			support.disconnectedMatch = matches.call( div, "div" );
1654
1655			// This should fail with an exception
1656			// Gecko does not error, returns false instead
1657			matches.call( div, "[s!='']:x" );
1658			rbuggyMatches.push( "!=", pseudos );
1659		});
1660	}
1661
1662	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1663	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1664
1665	/* Contains
1666	---------------------------------------------------------------------- */
1667
1668	// Element contains another
1669	// Purposefully does not implement inclusive descendent
1670	// As in, an element does not contain itself
1671	contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ?
1672		function( a, b ) {
1673			var adown = a.nodeType === 9 ? a.documentElement : a,
1674				bup = b && b.parentNode;
1675			return a === bup || !!( bup && bup.nodeType === 1 && (
1676				adown.contains ?
1677					adown.contains( bup ) :
1678					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1679			));
1680		} :
1681		function( a, b ) {
1682			if ( b ) {
1683				while ( (b = b.parentNode) ) {
1684					if ( b === a ) {
1685						return true;
1686					}
1687				}
1688			}
1689			return false;
1690		};
1691
1692	/* Sorting
1693	---------------------------------------------------------------------- */
1694
1695	// Document order sorting
1696	sortOrder = docElem.compareDocumentPosition ?
1697	function( a, b ) {
1698
1699		// Flag for duplicate removal
1700		if ( a === b ) {
1701			hasDuplicate = true;
1702			return 0;
1703		}
1704
1705		var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );
1706
1707		if ( compare ) {
1708			// Disconnected nodes
1709			if ( compare & 1 ||
1710				(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1711
1712				// Choose the first element that is related to our preferred document
1713				if ( a === doc || contains(preferredDoc, a) ) {
1714					return -1;
1715				}
1716				if ( b === doc || contains(preferredDoc, b) ) {
1717					return 1;
1718				}
1719
1720				// Maintain original order
1721				return sortInput ?
1722					( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1723					0;
1724			}
1725
1726			return compare & 4 ? -1 : 1;
1727		}
1728
1729		// Not directly comparable, sort on existence of method
1730		return a.compareDocumentPosition ? -1 : 1;
1731	} :
1732	function( a, b ) {
1733		var cur,
1734			i = 0,
1735			aup = a.parentNode,
1736			bup = b.parentNode,
1737			ap = [ a ],
1738			bp = [ b ];
1739
1740		// Exit early if the nodes are identical
1741		if ( a === b ) {
1742			hasDuplicate = true;
1743			return 0;
1744
1745		// Parentless nodes are either documents or disconnected
1746		} else if ( !aup || !bup ) {
1747			return a === doc ? -1 :
1748				b === doc ? 1 :
1749				aup ? -1 :
1750				bup ? 1 :
1751				sortInput ?
1752				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1753				0;
1754
1755		// If the nodes are siblings, we can do a quick check
1756		} else if ( aup === bup ) {
1757			return siblingCheck( a, b );
1758		}
1759
1760		// Otherwise we need full lists of their ancestors for comparison
1761		cur = a;
1762		while ( (cur = cur.parentNode) ) {
1763			ap.unshift( cur );
1764		}
1765		cur = b;
1766		while ( (cur = cur.parentNode) ) {
1767			bp.unshift( cur );
1768		}
1769
1770		// Walk down the tree looking for a discrepancy
1771		while ( ap[i] === bp[i] ) {
1772			i++;
1773		}
1774
1775		return i ?
1776			// Do a sibling check if the nodes have a common ancestor
1777			siblingCheck( ap[i], bp[i] ) :
1778
1779			// Otherwise nodes in our document sort first
1780			ap[i] === preferredDoc ? -1 :
1781			bp[i] === preferredDoc ? 1 :
1782			0;
1783	};
1784
1785	return doc;
1786};
1787
1788Sizzle.matches = function( expr, elements ) {
1789	return Sizzle( expr, null, null, elements );
1790};
1791
1792Sizzle.matchesSelector = function( elem, expr ) {
1793	// Set document vars if needed
1794	if ( ( elem.ownerDocument || elem ) !== document ) {
1795		setDocument( elem );
1796	}
1797
1798	// Make sure that attribute selectors are quoted
1799	expr = expr.replace( rattributeQuotes, "='$1']" );
1800
1801	if ( support.matchesSelector && documentIsHTML &&
1802		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1803		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
1804
1805		try {
1806			var ret = matches.call( elem, expr );
1807
1808			// IE 9's matchesSelector returns false on disconnected nodes
1809			if ( ret || support.disconnectedMatch ||
1810					// As well, disconnected nodes are said to be in a document
1811					// fragment in IE 9
1812					elem.document && elem.document.nodeType !== 11 ) {
1813				return ret;
1814			}
1815		} catch(e) {}
1816	}
1817
1818	return Sizzle( expr, document, null, [elem] ).length > 0;
1819};
1820
1821Sizzle.contains = function( context, elem ) {
1822	// Set document vars if needed
1823	if ( ( context.ownerDocument || context ) !== document ) {
1824		setDocument( context );
1825	}
1826	return contains( context, elem );
1827};
1828
1829Sizzle.attr = function( elem, name ) {
1830	// Set document vars if needed
1831	if ( ( elem.ownerDocument || elem ) !== document ) {
1832		setDocument( elem );
1833	}
1834
1835	var fn = Expr.attrHandle[ name.toLowerCase() ],
1836		// Don't get fooled by Object.prototype properties (jQuery #13807)
1837		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1838			fn( elem, name, !documentIsHTML ) :
1839			undefined;
1840
1841	return val === undefined ?
1842		support.attributes || !documentIsHTML ?
1843			elem.getAttribute( name ) :
1844			(val = elem.getAttributeNode(name)) && val.specified ?
1845				val.value :
1846				null :
1847		val;
1848};
1849
1850Sizzle.error = function( msg ) {
1851	throw new Error( "Syntax error, unrecognized expression: " + msg );
1852};
1853
1854/**
1855 * Document sorting and removing duplicates
1856 * @param {ArrayLike} results
1857 */
1858Sizzle.uniqueSort = function( results ) {
1859	var elem,
1860		duplicates = [],
1861		j = 0,
1862		i = 0;
1863
1864	// Unless we *know* we can detect duplicates, assume their presence
1865	hasDuplicate = !support.detectDuplicates;
1866	sortInput = !support.sortStable && results.slice( 0 );
1867	results.sort( sortOrder );
1868
1869	if ( hasDuplicate ) {
1870		while ( (elem = results[i++]) ) {
1871			if ( elem === results[ i ] ) {
1872				j = duplicates.push( i );
1873			}
1874		}
1875		while ( j-- ) {
1876			results.splice( duplicates[ j ], 1 );
1877		}
1878	}
1879
1880	return results;
1881};
1882
1883/**
1884 * Utility function for retrieving the text value of an array of DOM nodes
1885 * @param {Array|Element} elem
1886 */
1887getText = Sizzle.getText = function( elem ) {
1888	var node,
1889		ret = "",
1890		i = 0,
1891		nodeType = elem.nodeType;
1892
1893	if ( !nodeType ) {
1894		// If no nodeType, this is expected to be an array
1895		for ( ; (node = elem[i]); i++ ) {
vendor: 2,485 bytes, lines 1896-1994
1896			// Do not traverse comment nodes
1897			ret += getText( node );
1898		}
1899	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1900		// Use textContent for elements
1901		// innerText usage removed for consistency of new lines (see #11153)
1902		if ( typeof elem.textContent === "string" ) {
1903			return elem.textContent;
1904		} else {
1905			// Traverse its children
1906			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1907				ret += getText( elem );
1908			}
1909		}
1910	} else if ( nodeType === 3 || nodeType === 4 ) {
1911		return elem.nodeValue;
1912	}
1913	// Do not include comment or processing instruction nodes
1914
1915	return ret;
1916};
1917
1918Expr = Sizzle.selectors = {
1919
1920	// Can be adjusted by the user
1921	cacheLength: 50,
1922
1923	createPseudo: markFunction,
1924
1925	match: matchExpr,
1926
1927	attrHandle: {},
1928
1929	find: {},
1930
1931	relative: {
1932		">": { dir: "parentNode", first: true },
1933		" ": { dir: "parentNode" },
1934		"+": { dir: "previousSibling", first: true },
1935		"~": { dir: "previousSibling" }
1936	},
1937
1938	preFilter: {
1939		"ATTR": function( match ) {
1940			match[1] = match[1].replace( runescape, funescape );
1941
1942			// Move the given value to match[3] whether quoted or unquoted
1943			match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
1944
1945			if ( match[2] === "~=" ) {
1946				match[3] = " " + match[3] + " ";
1947			}
1948
1949			return match.slice( 0, 4 );
1950		},
1951
1952		"CHILD": function( match ) {
1953			/* matches from matchExpr["CHILD"]
1954				1 type (only|nth|...)
1955				2 what (child|of-type)
1956				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1957				4 xn-component of xn+y argument ([+-]?\d*n|)
1958				5 sign of xn-component
1959				6 x of xn-component
1960				7 sign of y-component
1961				8 y of y-component
1962			*/
1963			match[1] = match[1].toLowerCase();
1964
1965			if ( match[1].slice( 0, 3 ) === "nth" ) {
1966				// nth-* requires argument
1967				if ( !match[3] ) {
1968					Sizzle.error( match[0] );
1969				}
1970
1971				// numeric x and y parameters for Expr.filter.CHILD
1972				// remember that false/true cast respectively to 0/1
1973				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1974				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1975
1976			// other types prohibit arguments
1977			} else if ( match[3] ) {
1978				Sizzle.error( match[0] );
1979			}
1980
1981			return match;
1982		},
1983
1984		"PSEUDO": function( match ) {
1985			var excess,
1986				unquoted = !match[5] && match[2];
1987
1988			if ( matchExpr["CHILD"].test( match[0] ) ) {
1989				return null;
1990			}
1991
1992			// Accept quoted arguments as-is
1993			if ( match[3] && match[4] !== undefined ) {
1994				match[2] = match[4]
vendor: 9,637 bytes, lines 1994-2298
1994;
1995
1996			// Strip excess characters from unquoted arguments
1997			} else if ( unquoted && rpseudo.test( unquoted ) &&
1998				// Get excess from tokenize (recursively)
1999				(excess = tokenize( unquoted, true )) &&
2000				// advance to the next closing parenthesis
2001				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
2002
2003				// excess is a negative index
2004				match[0] = match[0].slice( 0, excess );
2005				match[2] = unquoted.slice( 0, excess );
2006			}
2007
2008			// Return only captures needed by the pseudo filter method (type and argument)
2009			return match.slice( 0, 3 );
2010		}
2011	},
2012
2013	filter: {
2014
2015		"TAG": function( nodeNameSelector ) {
2016			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
2017			return nodeNameSelector === "*" ?
2018				function() { return true; } :
2019				function( elem ) {
2020					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
2021				};
2022		},
2023
2024		"CLASS": function( className ) {
2025			var pattern = classCache[ className + " " ];
2026
2027			return pattern ||
2028				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
2029				classCache( className, function( elem ) {
2030					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
2031				});
2032		},
2033
2034		"ATTR": function( name, operator, check ) {
2035			return function( elem ) {
2036				var result = Sizzle.attr( elem, name );
2037
2038				if ( result == null ) {
2039					return operator === "!=";
2040				}
2041				if ( !operator ) {
2042					return true;
2043				}
2044
2045				result += "";
2046
2047				return operator === "=" ? result === check :
2048					operator === "!=" ? result !== check :
2049					operator === "^=" ? check && result.indexOf( check ) === 0 :
2050					operator === "*=" ? check && result.indexOf( check ) > -1 :
2051					operator === "$=" ? check && result.slice( -check.length ) === check :
2052					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
2053					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
2054					false;
2055			};
2056		},
2057
2058		"CHILD": function( type, what, argument, first, last ) {
2059			var simple = type.slice( 0, 3 ) !== "nth",
2060				forward = type.slice( -4 ) !== "last",
2061				ofType = what === "of-type";
2062
2063			return first === 1 && last === 0 ?
2064
2065				// Shortcut for :nth-*(n)
2066				function( elem ) {
2067					return !!elem.parentNode;
2068				} :
2069
2070				function( elem, context, xml ) {
2071					var cache, outerCache, node, diff, nodeIndex, start,
2072						dir = simple !== forward ? "nextSibling" : "previousSibling",
2073						parent = elem.parentNode,
2074						name = ofType && elem.nodeName.toLowerCase(),
2075						useCache = !xml && !ofType;
2076
2077					if ( parent ) {
2078
2079						// :(first|last|only)-(child|of-type)
2080						if ( simple ) {
2081							while ( dir ) {
2082								node = elem;
2083								while ( (node = node[ dir ]) ) {
2084									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
2085										return false;
2086									}
2087								}
2088								// Reverse direction for :only-* (if we haven't yet done so)
2089								start = dir = type === "only" && !start && "nextSibling";
2090							}
2091							return true;
2092						}
2093
2094						start = [ forward ? parent.firstChild : parent.lastChild ];
2095
2096						// non-xml :nth-child(...) stores cache data on `parent`
2097						if ( forward && useCache ) {
2098							// Seek `elem` from a previously-cached index
2099							outerCache = parent[ expando ] || (parent[ expando ] = {});
2100							cache = outerCache[ type ] || [];
2101							nodeIndex = cache[0] === dirruns && cache[1];
2102							diff = cache[0] === dirruns && cache[2];
2103							node = nodeIndex && parent.childNodes[ nodeIndex ];
2104
2105							while ( (node = ++nodeIndex && node && node[ dir ] ||
2106
2107								// Fallback to seeking `elem` from the start
2108								(diff = nodeIndex = 0) || start.pop()) ) {
2109
2110								// When found, cache indexes on `parent` and break
2111								if ( node.nodeType === 1 && ++diff && node === elem ) {
2112									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
2113									break;
2114								}
2115							}
2116
2117						// Use previously-cached element index if available
2118						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
2119							diff = cache[1];
2120
2121						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
2122						} else {
2123							// Use the same loop as above to seek `elem` from the start
2124							while ( (node = ++nodeIndex && node && node[ dir ] ||
2125								(diff = nodeIndex = 0) || start.pop()) ) {
2126
2127								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
2128									// Cache the index of each encountered element
2129									if ( useCache ) {
2130										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
2131									}
2132
2133									if ( node === elem ) {
2134										break;
2135									}
2136								}
2137							}
2138						}
2139
2140						// Incorporate the offset, then check against cycle size
2141						diff -= last;
2142						return diff === first || ( diff % first === 0 && diff / first >= 0 );
2143					}
2144				};
2145		},
2146
2147		"PSEUDO": function( pseudo, argument ) {
2148			// pseudo-class names are case-insensitive
2149			// http://www.w3.org/TR/selectors/#pseudo-classes
2150			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
2151			// Remember that setFilters inherits from pseudos
2152			var args,
2153				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
2154					Sizzle.error( "unsupported pseudo: " + pseudo );
2155
2156			// The user may use createPseudo to indicate that
2157			// arguments are needed to create the filter function
2158			// just as Sizzle does
2159			if ( fn[ expando ] ) {
2160				return fn( argument );
2161			}
2162
2163			// But maintain support for old signatures
2164			if ( fn.length > 1 ) {
2165				args = [ pseudo, pseudo, "", argument ];
2166				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
2167					markFunction(function( seed, matches ) {
2168						var idx,
2169							matched = fn( seed, argument ),
2170							i = matched.length;
2171						while ( i-- ) {
2172							idx = indexOf.call( seed, matched[i] );
2173							seed[ idx ] = !( matches[ idx ] = matched[i] );
2174						}
2175					}) :
2176					function( elem ) {
2177						return fn( elem, 0, args );
2178					};
2179			}
2180
2181			return fn;
2182		}
2183	},
2184
2185	pseudos: {
2186		// Potentially complex pseudos
2187		"not": markFunction(function( selector ) {
2188			// Trim the selector passed to compile
2189			// to avoid treating leading and trailing
2190			// spaces as combinators
2191			var input = [],
2192				results = [],
2193				matcher = compile( selector.replace( rtrim, "$1" ) );
2194
2195			return matcher[ expando ] ?
2196				markFunction(function( seed, matches, context, xml ) {
2197					var elem,
2198						unmatched = matcher( seed, null, xml, [] ),
2199						i = seed.length;
2200
2201					// Match elements unmatched by `matcher`
2202					while ( i-- ) {
2203						if ( (elem = unmatched[i]) ) {
2204							seed[i] = !(matches[i] = elem);
2205						}
2206					}
2207				}) :
2208				function( elem, context, xml ) {
2209					input[0] = elem;
2210					matcher( input, null, xml, results );
2211					return !results.pop();
2212				};
2213		}),
2214
2215		"has": markFunction(function( selector ) {
2216			return function( elem ) {
2217				return Sizzle( selector, elem ).length > 0;
2218			};
2219		}),
2220
2221		"contains": markFunction(function( text ) {
2222			return function( elem ) {
2223				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
2224			};
2225		}),
2226
2227		// "Whether an element is represented by a :lang() selector
2228		// is based solely on the element's language value
2229		// being equal to the identifier C,
2230		// or beginning with the identifier C immediately followed by "-".
2231		// The matching of C against the element's language value is performed case-insensitively.
2232		// The identifier C does not have to be a valid language name."
2233		// http://www.w3.org/TR/selectors/#lang-pseudo
2234		"lang": markFunction( function( lang ) {
2235			// lang value must be a valid identifier
2236			if ( !ridentifier.test(lang || "") ) {
2237				Sizzle.error( "unsupported lang: " + lang );
2238			}
2239			lang = lang.replace( runescape, funescape ).toLowerCase();
2240			return function( elem ) {
2241				var elemLang;
2242				do {
2243					if ( (elemLang = documentIsHTML ?
2244						elem.lang :
2245						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
2246
2247						elemLang = elemLang.toLowerCase();
2248						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
2249					}
2250				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
2251				return false;
2252			};
2253		}),
2254
2255		// Miscellaneous
2256		"target": function( elem ) {
2257			var hash = window.location && window.location.hash;
2258			return hash && hash.slice( 1 ) === elem.id;
2259		},
2260
2261		"root": function( elem ) {
2262			return elem === docElem;
2263		},
2264
2265		"focus": function( elem ) {
2266			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
2267		},
2268
2269		// Boolean properties
2270		"enabled": function( elem ) {
2271			return elem.disabled === false;
2272		},
2273
2274		"disabled": function( elem ) {
2275			return elem.disabled === true;
2276		},
2277
2278		"checked": function( elem ) {
2279			// In CSS3, :checked should return both checked and selected elements
2280			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2281			var nodeName = elem.nodeName.toLowerCase();
2282			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
2283		},
2284
2285		"selected": function( elem ) {
2286			// Accessing this property makes selected-by-default
2287			// options in Safari work properly
2288			if ( elem.parentNode ) {
2289				elem.parentNode.selectedIndex;
2290			}
2291
2292			return elem.selected === true;
2293		},
2294
2295		// Contents
2296		"empty": function( elem ) {
2297			// http://www.w3.org/TR/selectors/#empty-pseudo
2298			// :empty is 
vendor: 3,404 bytes, lines 2298-2423
2298only affected by element nodes and content nodes(including text(3), cdata(4)),
2299			//   not comment, processing instructions, or others
2300			// Thanks to Diego Perini for the nodeName shortcut
2301			//   Greater than "@" means alpha characters (specifically not starting with "#" or "?")
2302			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2303				if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
2304					return false;
2305				}
2306			}
2307			return true;
2308		},
2309
2310		"parent": function( elem ) {
2311			return !Expr.pseudos["empty"]( elem );
2312		},
2313
2314		// Element/input types
2315		"header": function( elem ) {
2316			return rheader.test( elem.nodeName );
2317		},
2318
2319		"input": function( elem ) {
2320			return rinputs.test( elem.nodeName );
2321		},
2322
2323		"button": function( elem ) {
2324			var name = elem.nodeName.toLowerCase();
2325			return name === "input" && elem.type === "button" || name === "button";
2326		},
2327
2328		"text": function( elem ) {
2329			var attr;
2330			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
2331			// use getAttribute instead to test this case
2332			return elem.nodeName.toLowerCase() === "input" &&
2333				elem.type === "text" &&
2334				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
2335		},
2336
2337		// Position-in-collection
2338		"first": createPositionalPseudo(function() {
2339			return [ 0 ];
2340		}),
2341
2342		"last": createPositionalPseudo(function( matchIndexes, length ) {
2343			return [ length - 1 ];
2344		}),
2345
2346		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2347			return [ argument < 0 ? argument + length : argument ];
2348		}),
2349
2350		"even": createPositionalPseudo(function( matchIndexes, length ) {
2351			var i = 0;
2352			for ( ; i < length; i += 2 ) {
2353				matchIndexes.push( i );
2354			}
2355			return matchIndexes;
2356		}),
2357
2358		"odd": createPositionalPseudo(function( matchIndexes, length ) {
2359			var i = 1;
2360			for ( ; i < length; i += 2 ) {
2361				matchIndexes.push( i );
2362			}
2363			return matchIndexes;
2364		}),
2365
2366		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2367			var i = argument < 0 ? argument + length : argument;
2368			for ( ; --i >= 0; ) {
2369				matchIndexes.push( i );
2370			}
2371			return matchIndexes;
2372		}),
2373
2374		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2375			var i = argument < 0 ? argument + length : argument;
2376			for ( ; ++i < length; ) {
2377				matchIndexes.push( i );
2378			}
2379			return matchIndexes;
2380		})
2381	}
2382};
2383
2384Expr.pseudos["nth"] = Expr.pseudos["eq"];
2385
2386// Add button/input type pseudos
2387for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2388	Expr.pseudos[ i ] = createInputPseudo( i );
2389}
2390for ( i in { submit: true, reset: true } ) {
2391	Expr.pseudos[ i ] = createButtonPseudo( i );
2392}
2393
2394// Easy API for creating new setFilters
2395function setFilters() {}
2396setFilters.prototype = Expr.filters = Expr.pseudos;
2397Expr.setFilters = new setFilters();
2398
2399function tokenize( selector, parseOnly ) {
2400	var matched, match, tokens, type,
2401		soFar, groups, preFilters,
2402		cached = tokenCache[ selector + " " ];
2403
2404	if ( cached ) {
2405		return parseOnly ? 0 : cached.slice( 0 );
2406	}
2407
2408	soFar = selector;
2409	groups = [];
2410	preFilters = Expr.preFilter;
2411
2412	while ( soFar ) {
2413
2414		// Comma and first run
2415		if ( !matched || (match = rcomma.exec( soFar )) ) {
2416			if ( match ) {
2417				// Don't consume trailing commas as valid
2418				soFar = soFar.slice( match[0].length ) || soFar;
2419			}
2420			groups.push( tokens = [] );
2421		}
2422
2423		matched = false;
vendor: 25,111 bytes, lines 2424-3313
2424
2425		// Combinators
2426		if ( (match = rcombinators.exec( soFar )) ) {
2427			matched = match.shift();
2428			tokens.push({
2429				value: matched,
2430				// Cast descendant combinators to space
2431				type: match[0].replace( rtrim, " " )
2432			});
2433			soFar = soFar.slice( matched.length );
2434		}
2435
2436		// Filters
2437		for ( type in Expr.filter ) {
2438			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2439				(match = preFilters[ type ]( match ))) ) {
2440				matched = match.shift();
2441				tokens.push({
2442					value: matched,
2443					type: type,
2444					matches: match
2445				});
2446				soFar = soFar.slice( matched.length );
2447			}
2448		}
2449
2450		if ( !matched ) {
2451			break;
2452		}
2453	}
2454
2455	// Return the length of the invalid excess
2456	// if we're just parsing
2457	// Otherwise, throw an error or return tokens
2458	return parseOnly ?
2459		soFar.length :
2460		soFar ?
2461			Sizzle.error( selector ) :
2462			// Cache the tokens
2463			tokenCache( selector, groups ).slice( 0 );
2464}
2465
2466function toSelector( tokens ) {
2467	var i = 0,
2468		len = tokens.length,
2469		selector = "";
2470	for ( ; i < len; i++ ) {
2471		selector += tokens[i].value;
2472	}
2473	return selector;
2474}
2475
2476function addCombinator( matcher, combinator, base ) {
2477	var dir = combinator.dir,
2478		checkNonElements = base && dir === "parentNode",
2479		doneName = done++;
2480
2481	return combinator.first ?
2482		// Check against closest ancestor/preceding element
2483		function( elem, context, xml ) {
2484			while ( (elem = elem[ dir ]) ) {
2485				if ( elem.nodeType === 1 || checkNonElements ) {
2486					return matcher( elem, context, xml );
2487				}
2488			}
2489		} :
2490
2491		// Check against all ancestor/preceding elements
2492		function( elem, context, xml ) {
2493			var data, cache, outerCache,
2494				dirkey = dirruns + " " + doneName;
2495
2496			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
2497			if ( xml ) {
2498				while ( (elem = elem[ dir ]) ) {
2499					if ( elem.nodeType === 1 || checkNonElements ) {
2500						if ( matcher( elem, context, xml ) ) {
2501							return true;
2502						}
2503					}
2504				}
2505			} else {
2506				while ( (elem = elem[ dir ]) ) {
2507					if ( elem.nodeType === 1 || checkNonElements ) {
2508						outerCache = elem[ expando ] || (elem[ expando ] = {});
2509						if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
2510							if ( (data = cache[1]) === true || data === cachedruns ) {
2511								return data === true;
2512							}
2513						} else {
2514							cache = outerCache[ dir ] = [ dirkey ];
2515							cache[1] = matcher( elem, context, xml ) || cachedruns;
2516							if ( cache[1] === true ) {
2517								return true;
2518							}
2519						}
2520					}
2521				}
2522			}
2523		};
2524}
2525
2526function elementMatcher( matchers ) {
2527	return matchers.length > 1 ?
2528		function( elem, context, xml ) {
2529			var i = matchers.length;
2530			while ( i-- ) {
2531				if ( !matchers[i]( elem, context, xml ) ) {
2532					return false;
2533				}
2534			}
2535			return true;
2536		} :
2537		matchers[0];
2538}
2539
2540function condense( unmatched, map, filter, context, xml ) {
2541	var elem,
2542		newUnmatched = [],
2543		i = 0,
2544		len = unmatched.length,
2545		mapped = map != null;
2546
2547	for ( ; i < len; i++ ) {
2548		if ( (elem = unmatched[i]) ) {
2549			if ( !filter || filter( elem, context, xml ) ) {
2550				newUnmatched.push( elem );
2551				if ( mapped ) {
2552					map.push( i );
2553				}
2554			}
2555		}
2556	}
2557
2558	return newUnmatched;
2559}
2560
2561function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2562	if ( postFilter && !postFilter[ expando ] ) {
2563		postFilter = setMatcher( postFilter );
2564	}
2565	if ( postFinder && !postFinder[ expando ] ) {
2566		postFinder = setMatcher( postFinder, postSelector );
2567	}
2568	return markFunction(function( seed, results, context, xml ) {
2569		var temp, i, elem,
2570			preMap = [],
2571			postMap = [],
2572			preexisting = results.length,
2573
2574			// Get initial elements from seed or context
2575			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2576
2577			// Prefilter to get matcher input, preserving a map for seed-results synchronization
2578			matcherIn = preFilter && ( seed || !selector ) ?
2579				condense( elems, preMap, preFilter, context, xml ) :
2580				elems,
2581
2582			matcherOut = matcher ?
2583				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2584				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2585
2586					// ...intermediate processing is necessary
2587					[] :
2588
2589					// ...otherwise use results directly
2590					results :
2591				matcherIn;
2592
2593		// Find primary matches
2594		if ( matcher ) {
2595			matcher( matcherIn, matcherOut, context, xml );
2596		}
2597
2598		// Apply postFilter
2599		if ( postFilter ) {
2600			temp = condense( matcherOut, postMap );
2601			postFilter( temp, [], context, xml );
2602
2603			// Un-match failing elements by moving them back to matcherIn
2604			i = temp.length;
2605			while ( i-- ) {
2606				if ( (elem = temp[i]) ) {
2607					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2608				}
2609			}
2610		}
2611
2612		if ( seed ) {
2613			if ( postFinder || preFilter ) {
2614				if ( postFinder ) {
2615					// Get the final matcherOut by condensing this intermediate into postFinder contexts
2616					temp = [];
2617					i = matcherOut.length;
2618					while ( i-- ) {
2619						if ( (elem = matcherOut[i]) ) {
2620							// Restore matcherIn since elem is not yet a final match
2621							temp.push( (matcherIn[i] = elem) );
2622						}
2623					}
2624					postFinder( null, (matcherOut = []), temp, xml );
2625				}
2626
2627				// Move matched elements from seed to results to keep them synchronized
2628				i = matcherOut.length;
2629				while ( i-- ) {
2630					if ( (elem = matcherOut[i]) &&
2631						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
2632
2633						seed[temp] = !(results[temp] = elem);
2634					}
2635				}
2636			}
2637
2638		// Add elements to results, through postFinder if defined
2639		} else {
2640			matcherOut = condense(
2641				matcherOut === results ?
2642					matcherOut.splice( preexisting, matcherOut.length ) :
2643					matcherOut
2644			);
2645			if ( postFinder ) {
2646				postFinder( null, results, matcherOut, xml );
2647			} else {
2648				push.apply( results, matcherOut );
2649			}
2650		}
2651	});
2652}
2653
2654function matcherFromTokens( tokens ) {
2655	var checkContext, matcher, j,
2656		len = tokens.length,
2657		leadingRelative = Expr.relative[ tokens[0].type ],
2658		implicitRelative = leadingRelative || Expr.relative[" "],
2659		i = leadingRelative ? 1 : 0,
2660
2661		// The foundational matcher ensures that elements are reachable from top-level context(s)
2662		matchContext = addCombinator( function( elem ) {
2663			return elem === checkContext;
2664		}, implicitRelative, true ),
2665		matchAnyContext = addCombinator( function( elem ) {
2666			return indexOf.call( checkContext, elem ) > -1;
2667		}, implicitRelative, true ),
2668		matchers = [ function( elem, context, xml ) {
2669			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2670				(checkContext = context).nodeType ?
2671					matchContext( elem, context, xml ) :
2672					matchAnyContext( elem, context, xml ) );
2673		} ];
2674
2675	for ( ; i < len; i++ ) {
2676		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2677			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2678		} else {
2679			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2680
2681			// Return special upon seeing a positional matcher
2682			if ( matcher[ expando ] ) {
2683				// Find the next relative operator (if any) for proper handling
2684				j = ++i;
2685				for ( ; j < len; j++ ) {
2686					if ( Expr.relative[ tokens[j].type ] ) {
2687						break;
2688					}
2689				}
2690				return setMatcher(
2691					i > 1 && elementMatcher( matchers ),
2692					i > 1 && toSelector(
2693						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
2694						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2695					).replace( rtrim, "$1" ),
2696					matcher,
2697					i < j && matcherFromTokens( tokens.slice( i, j ) ),
2698					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2699					j < len && toSelector( tokens )
2700				);
2701			}
2702			matchers.push( matcher );
2703		}
2704	}
2705
2706	return elementMatcher( matchers );
2707}
2708
2709function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2710	// A counter to specify which element is currently being matched
2711	var matcherCachedRuns = 0,
2712		bySet = setMatchers.length > 0,
2713		byElement = elementMatchers.length > 0,
2714		superMatcher = function( seed, context, xml, results, expandContext ) {
2715			var elem, j, matcher,
2716				setMatched = [],
2717				matchedCount = 0,
2718				i = "0",
2719				unmatched = seed && [],
2720				outermost = expandContext != null,
2721				contextBackup = outermostContext,
2722				// We must always have either seed elements or context
2723				elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
2724				// Use integer dirruns iff this is the outermost matcher
2725				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
2726
2727			if ( outermost ) {
2728				outermostContext = context !== document && context;
2729				cachedruns = matcherCachedRuns;
2730			}
2731
2732			// Add elements passing elementMatchers directly to results
2733			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
2734			for ( ; (elem = elems[i]) != null; i++ ) {
2735				if ( byElement && elem ) {
2736					j = 0;
2737					while ( (matcher = elementMatchers[j++]) ) {
2738						if ( matcher( elem, context, xml ) ) {
2739							results.push( elem );
2740							break;
2741						}
2742					}
2743					if ( outermost ) {
2744						dirruns = dirrunsUnique;
2745						cachedruns = ++matcherCachedRuns;
2746					}
2747				}
2748
2749				// Track unmatched elements for set filters
2750				if ( bySet ) {
2751					// They will have gone through all possible matchers
2752					if ( (elem = !matcher && elem) ) {
2753						matchedCount--;
2754					}
2755
2756					// Lengthen the array for every element, matched or not
2757					if ( seed ) {
2758						unmatched.push( elem );
2759					}
2760				}
2761			}
2762
2763			// Apply set filters to unmatched elements
2764			matchedCount += i;
2765			if ( bySet && i !== matchedCount ) {
2766				j = 0;
2767				while ( (matcher = setMatchers[j++]) ) {
2768					matcher( unmatched, setMatched, context, xml );
2769				}
2770
2771				if ( seed ) {
2772					// Reintegrate element matches to eliminate the need for sorting
2773					if ( matchedCount > 0 ) {
2774						while ( i-- ) {
2775							if ( !(unmatched[i] || setMatched[i]) ) {
2776								setMatched[i] = pop.call( results );
2777							}
2778						}
2779					}
2780
2781					// Discard index placeholder values to get only actual matches
2782					setMatched = condense( setMatched );
2783				}
2784
2785				// Add matches to results
2786				push.apply( results, setMatched );
2787
2788				// Seedless set matches succeeding multiple successful matchers stipulate sorting
2789				if ( outermost && !seed && setMatched.length > 0 &&
2790					( matchedCount + setMatchers.length ) > 1 ) {
2791
2792					Sizzle.uniqueSort( results );
2793				}
2794			}
2795
2796			// Override manipulation of globals by nested matchers
2797			if ( outermost ) {
2798				dirruns = dirrunsUnique;
2799				outermostContext = contextBackup;
2800			}
2801
2802			return unmatched;
2803		};
2804
2805	return bySet ?
2806		markFunction( superMatcher ) :
2807		superMatcher;
2808}
2809
2810compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
2811	var i,
2812		setMatchers = [],
2813		elementMatchers = [],
2814		cached = compilerCache[ selector + " " ];
2815
2816	if ( !cached ) {
2817		// Generate a function of recursive functions that can be used to check each element
2818		if ( !group ) {
2819			group = tokenize( selector );
2820		}
2821		i = group.length;
2822		while ( i-- ) {
2823			cached = matcherFromTokens( group[i] );
2824			if ( cached[ expando ] ) {
2825				setMatchers.push( cached );
2826			} else {
2827				elementMatchers.push( cached );
2828			}
2829		}
2830
2831		// Cache the compiled function
2832		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2833	}
2834	return cached;
2835};
2836
2837function multipleContexts( selector, contexts, results ) {
2838	var i = 0,
2839		len = contexts.length;
2840	for ( ; i < len; i++ ) {
2841		Sizzle( selector, contexts[i], results );
2842	}
2843	return results;
2844}
2845
2846function select( selector, context, results, seed ) {
2847	var i, tokens, token, type, find,
2848		match = tokenize( selector );
2849
2850	if ( !seed ) {
2851		// Try to minimize operations if there is only one group
2852		if ( match.length === 1 ) {
2853
2854			// Take a shortcut and set the context if the root selector is an ID
2855			tokens = match[0] = match[0].slice( 0 );
2856			if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2857					support.getById && context.nodeType === 9 && documentIsHTML &&
2858					Expr.relative[ tokens[1].type ] ) {
2859
2860				context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2861				if ( !context ) {
2862					return results;
2863				}
2864				selector = selector.slice( tokens.shift().value.length );
2865			}
2866
2867			// Fetch a seed set for right-to-left matching
2868			i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2869			while ( i-- ) {
2870				token = tokens[i];
2871
2872				// Abort if we hit a combinator
2873				if ( Expr.relative[ (type = token.type) ] ) {
2874					break;
2875				}
2876				if ( (find = Expr.find[ type ]) ) {
2877					// Search, expanding context for leading sibling combinators
2878					if ( (seed = find(
2879						token.matches[0].replace( runescape, funescape ),
2880						rsibling.test( tokens[0].type ) && context.parentNode || context
2881					)) ) {
2882
2883						// If seed is empty or no tokens remain, we can return early
2884						tokens.splice( i, 1 );
2885						selector = seed.length && toSelector( tokens );
2886						if ( !selector ) {
2887							push.apply( results, seed );
2888							return results;
2889						}
2890
2891						break;
2892					}
2893				}
2894			}
2895		}
2896	}
2897
2898	// Compile and execute a filtering function
2899	// Provide `match` to avoid retokenization if we modified the selector above
2900	compile( selector, match )(
2901		seed,
2902		context,
2903		!documentIsHTML,
2904		results,
2905		rsibling.test( selector )
2906	);
2907	return results;
2908}
2909
2910// One-time assignments
2911
2912// Sort stability
2913support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2914
2915// Support: Chrome<14
2916// Always assume duplicates if they aren't passed to the comparison function
2917support.detectDuplicates = hasDuplicate;
2918
2919// Initialize against the default document
2920setDocument();
2921
2922// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2923// Detached nodes confoundingly follow *each other*
2924support.sortDetached = assert(function( div1 ) {
2925	// Should return 1, but returns 4 (following)
2926	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2927});
2928
2929// Support: IE<8
2930// Prevent attribute/property "interpolation"
2931// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2932if ( !assert(function( div ) {
2933	div.innerHTML = "<a href='#'></a>";
2934	return div.firstChild.getAttribute("href") === "#" ;
2935}) ) {
2936	addHandle( "type|href|height|width", function( elem, name, isXML ) {
2937		if ( !isXML ) {
2938			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2939		}
2940	});
2941}
2942
2943// Support: IE<9
2944// Use defaultValue in place of getAttribute("value")
2945if ( !support.attributes || !assert(function( div ) {
2946	div.innerHTML = "<input/>";
2947	div.firstChild.setAttribute( "value", "" );
2948	return div.firstChild.getAttribute( "value" ) === "";
2949}) ) {
2950	addHandle( "value", function( elem, name, isXML ) {
2951		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2952			return elem.defaultValue;
2953		}
2954	});
2955}
2956
2957// Support: IE<9
2958// Use getAttributeNode to fetch booleans when getAttribute lies
2959if ( !assert(function( div ) {
2960	return div.getAttribute("disabled") == null;
2961}) ) {
2962	addHandle( booleans, function( elem, name, isXML ) {
2963		var val;
2964		if ( !isXML ) {
2965			return (val = elem.getAttributeNode( name )) && val.specified ?
2966				val.value :
2967				elem[ name ] === true ? name.toLowerCase() : null;
2968		}
2969	});
2970}
2971
2972jQuery.find = Sizzle;
2973jQuery.expr = Sizzle.selectors;
2974jQuery.expr[":"] = jQuery.expr.pseudos;
2975jQuery.unique = Sizzle.uniqueSort;
2976jQuery.text = Sizzle.getText;
2977jQuery.isXMLDoc = Sizzle.isXML;
2978jQuery.contains = Sizzle.contains;
2979
2980
2981})( window );
2982// String to Object options format cache
2983var optionsCache = {};
2984
2985// Convert String-formatted options into Object-formatted ones and store in cache
2986function createOptions( options ) {
2987	var object = optionsCache[ options ] = {};
2988	jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
2989		object[ flag ] = true;
2990	});
2991	return object;
2992}
2993
2994/*
2995 * Create a callback list using the following parameters:
2996 *
2997 *	options: an optional list of space-separated options that will change how
2998 *			the callback list behaves or a more traditional option object
2999 *
3000 * By default a callback list will act like an event callback list and can be
3001 * "fired" multiple times.
3002 *
3003 * Possible options:
3004 *
3005 *	once:			will ensure the callback list can only be fired once (like a Deferred)
3006 *
3007 *	memory:			will keep track of previous values and will call any callback added
3008 *					after the list has been fired right away with the latest "memorized"
3009 *					values (like a Deferred)
3010 *
3011 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
3012 *
3013 *	stopOnFalse:	interrupt callings when a callback returns false
3014 *
3015 */
3016jQuery.Callbacks = function( options ) {
3017
3018	// Convert options from String-formatted to Object-formatted if needed
3019	// (we check in cache first)
3020	options = typeof options === "string" ?
3021		( optionsCache[ options ] || createOptions( options ) ) :
3022		jQuery.extend( {}, options );
3023
3024	var // Flag to know if list is currently firing
3025		firing,
3026		// Last fire value (for non-forgettable lists)
3027		memory,
3028		// Flag to know if list was already fired
3029		fired,
3030		// End of the loop when firing
3031		firingLength,
3032		// Index of currently firing callback (modified by remove if needed)
3033		firingIndex,
3034		// First callback to fire (used internally by add and fireWith)
3035		firingStart,
3036		// Actual callback list
3037		list = [],
3038		// Stack of fire calls for repeatable lists
3039		stack = !options.once && [],
3040		// Fire callbacks
3041		fire = function( data ) {
3042			memory = options.memory && data;
3043			fired = true;
3044			firingIndex = firingStart || 0;
3045			firingStart = 0;
3046			firingLength = list.length;
3047			firing = true;
3048			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
3049				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
3050					memory = false; // To prevent further calls using add
3051					break;
3052				}
3053			}
3054			firing = false;
3055			if ( list ) {
3056				if ( stack ) {
3057					if ( stack.length ) {
3058						fire( stack.shift() );
3059					}
3060				} else if ( memory ) {
3061					list = [];
3062				} else {
3063					self.disable();
3064				}
3065			}
3066		},
3067		// Actual Callbacks object
3068		self = {
3069			// Add a callback or a collection of callbacks to the list
3070			add: function() {
3071				if ( list ) {
3072					// First, we save the current length
3073					var start = list.length;
3074					(function add( args ) {
3075						jQuery.each( args, function( _, arg ) {
3076							var type = jQuery.type( arg );
3077							if ( type === "function" ) {
3078								if ( !options.unique || !self.has( arg ) ) {
3079									list.push( arg );
3080								}
3081							} else if ( arg && arg.length && type !== "string" ) {
3082								// Inspect recursively
3083								add( arg );
3084							}
3085						});
3086					})( arguments );
3087					// Do we need to add the callbacks to the
3088					// current firing batch?
3089					if ( firing ) {
3090						firingLength = list.length;
3091					// With memory, if we're not firing then
3092					// we should call right away
3093					} else if ( memory ) {
3094						firingStart = start;
3095						fire( memory );
3096					}
3097				}
3098				return this;
3099			},
3100			// Remove a callback from the list
3101			remove: function() {
3102				if ( list ) {
3103					jQuery.each( arguments, function( _, arg ) {
3104						var index;
3105						while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3106							list.splice( index, 1 );
3107							// Handle firing indexes
3108							if ( firing ) {
3109								if ( index <= firingLength ) {
3110									firingLength--;
3111								}
3112								if ( index <= firingIndex ) {
3113									firingIndex--;
3114								}
3115							}
3116						}
3117					});
3118				}
3119				return this;
3120			},
3121			// Check if a given callback is in the list.
3122			// If no argument is given, return whether or not list has callbacks attached.
3123			has: function( fn ) {
3124				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
3125			},
3126			// Remove all callbacks from the list
3127			empty: function() {
3128				list = [];
3129				firingLength = 0;
3130				return this;
3131			},
3132			// Have the list do nothing anymore
3133			disable: function() {
3134				list = stack = memory = undefined;
3135				return this;
3136			},
3137			// Is it disabled?
3138			disabled: function() {
3139				return !list;
3140			},
3141			// Lock the list in its current state
3142			lock: function() {
3143				stack = undefined;
3144				if ( !memory ) {
3145					self.disable();
3146				}
3147				return this;
3148			},
3149			// Is it locked?
3150			locked: function() {
3151				return !stack;
3152			},
3153			// Call all callbacks with the given context and arguments
3154			fireWith: function( context, args ) {
3155				if ( list && ( !fired || stack ) ) {
3156					args = args || [];
3157					args = [ context, args.slice ? args.slice() : args ];
3158					if ( firing ) {
3159						stack.push( args );
3160					} else {
3161						fire( args );
3162					}
3163				}
3164				return this;
3165			},
3166			// Call all the callbacks with the given arguments
3167			fire: function() {
3168				self.fireWith( this, arguments );
3169				return this;
3170			},
3171			// To know if the callbacks have already been called at least once
3172			fired: function() {
3173				return !!fired;
3174			}
3175		};
3176
3177	return self;
3178};
3179jQuery.extend({
3180
3181	Deferred: function( func ) {
3182		var tuples = [
3183				// action, add listener, listener list, final state
3184				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
3185				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
3186				[ "notify", "progress", jQuery.Callbacks("memory") ]
3187			],
3188			state = "pending",
3189			promise = {
3190				state: function() {
3191					return state;
3192				},
3193				always: function() {
3194					deferred.done( arguments ).fail( arguments );
3195					return this;
3196				},
3197				then: function( /* fnDone, fnFail, fnProgress */ ) {
3198					var fns = arguments;
3199					return jQuery.Deferred(function( newDefer ) {
3200						jQuery.each( tuples, function( i, tuple ) {
3201							var action = tuple[ 0 ],
3202								fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3203							// deferred[ done | fail | progress ] for forwarding actions to newDefer
3204							deferred[ tuple[1] ](function() {
3205								var returned = fn && fn.apply( this, arguments );
3206								if ( returned && jQuery.isFunction( returned.promise ) ) {
3207									returned.promise()
3208										.done( newDefer.resolve )
3209										.fail( newDefer.reject )
3210										.progress( newDefer.notify );
3211								} else {
3212									newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
3213								}
3214							});
3215						});
3216						fns = null;
3217					}).promise();
3218				},
3219				// Get a promise for this deferred
3220				// If obj is provided, the promise aspect is added to the object
3221				promise: function( obj ) {
3222					return obj != null ? jQuery.extend( obj, promise ) : promise;
3223				}
3224			},
3225			deferred = {};
3226
3227		// Keep pipe for back-compat
3228		promise.pipe = promise.then;
3229
3230		// Add list-specific methods
3231		jQuery.each( tuples, function( i, tuple ) {
3232			var list = tuple[ 2 ],
3233				stateString = tuple[ 3 ];
3234
3235			// promise[ done | fail | progress ] = list.add
3236			promise[ tuple[1] ] = list.add;
3237
3238			// Handle state
3239			if ( stateString ) {
3240				list.add(function() {
3241					// state = [ resolved | rejected ]
3242					state = stateString;
3243
3244				// [ reject_list | resolve_list ].disable; progress_list.lock
3245				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3246			}
3247
3248			// deferred[ resolve | reject | notify ]
3249			deferred[ tuple[0] ] = function() {
3250				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
3251				return this;
3252			};
3253			deferred[ tuple[0] + "With" ] = list.fireWith;
3254		});
3255
3256		// Make the deferred a promise
3257		promise.promise( deferred );
3258
3259		// Call given func if any
3260		if ( func ) {
3261			func.call( deferred, deferred );
3262		}
3263
3264		// All done!
3265		return deferred;
3266	},
3267
3268	// Deferred helper
3269	when: function( subordinate /* , ..., subordinateN */ ) {
3270		var i = 0,
3271			resolveValues = core_slice.call( arguments ),
3272			length = resolveValues.length,
3273
3274			// the count of uncompleted subordinates
3275			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3276
3277			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
3278			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3279
3280			// Update function for both resolve and progress values
3281			updateFunc = function( i, contexts, values ) {
3282				return function( value ) {
3283					contexts[ i ] = this;
3284					values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
3285					if( values === progressValues ) {
3286						deferred.notifyWith( contexts, values );
3287					} else if ( !( --remaining ) ) {
3288						deferred.resolveWith( contexts, values );
3289					}
3290				};
3291			},
3292
3293			progressValues, progressContexts, resolveContexts;
3294
3295		// add listeners to Deferred subordinates; treat others as resolved
3296		if ( length > 1 ) {
3297			progressValues = new Array( length );
3298			progressContexts = new Array( length );
3299			resolveContexts = new Array( length );
3300			for ( ; i < length; i++ ) {
3301				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3302					resolveValues[ i ].promise()
3303						.done( updateFunc( i, resolveContexts, resolveValues ) )
3304						.fail( deferred.reject )
3305						.progress( updateFunc( i, progressContexts, progressValues ) );
3306				} else {
3307					--remaining;
3308				}
3309			}
3310		}
3311
3312		// if we're not waiting on anything, resolve the master
3313		if ( !remaining ) {
3314			deferred.resolveWith( resolveContexts, resolveValues );
3315		}
3316
3317		return deferred.promise();
3318	}
3319});
3320jQuery.support = (function( support ) {
3321
3322	var all, a, input, select, fragment, opt, eventName, isSupported, i,
3323		div = document.createElement("div");
3324
3325	// Setup
3326	div.setAttribute( "className", "t" );
3327	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
3328
3329	// Finish early in limited (non-browser) environments
3330	all = div.getElementsByTagName("*") || [];
3331	a = div.getElementsByTagName("a")[ 0 ];
3332	if ( !a || !a.style || !all.length ) {
3333		return support;
3334	}
3335
3336	// First batch of tests
3337	select = document.createElement("select");
3338	opt = select.appendChild( document.createElement("option") );
3339	input = div.getElementsByTagName("input")[ 0 ];
3340
3341	a.style.cssText = "top:1px;float:left;opacity:.5";
3342
3343	// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
3344	support.getSetAttribute = div.className !== "t";
3345
3346	// IE strips leading whitespace when .innerHTML is used
3347	support.leadingWhitespace = div.firstChild.nodeType === 3;
3348
3349	// Make sure that tbody elements aren't automatically inserted
3350	// IE will insert them into empty tables
3351	support.tbody = !div.getElementsByTagName("tbody").length;
3352
3353	// Make sure that link elements get serialized correctly by innerHTML
3354	// This requires a wrapper element in IE
3355	support.htmlSerialize = !!div.getElementsByTagName("link").length;
3356
3357	// Get the style information from getAttribute
3358	// (IE uses .cssText instead)
3359	support.style = /top/.test( a.getAttribute("style") );
3360
3361	// Make sure that URLs aren't manipulated
3362	// (IE normalizes it by default)
3363	support.hrefNormalized = a.getAttribute("href") === "/a";
3364
3365	// Make sure that element opacity exists
3366	// (IE uses filter instead)
3367	// Use a regex to work around a WebKit issue. See #5145
3368	support.opacity = /^0.5/.test( a.style.opacity );
3369
3370	// Verify style float existence
3371	// (IE uses styleFloat instead of cssFloat)
3372	support.cssFloat = !!a.style.cssFloat;
3373
3374	// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
3375	support.checkOn = !!input.value;
3376
3377	// Make sure that a selected-by-default option has a working selected property.
3378	// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
3379	support.optSelected = opt.selected;
3380
3381	// Tests for enctype support on a form (#6743)
3382	support.enctype = !!document.createElement("form").enctype;
3383
3384	// Makes sure cloning an html5 element does not cause problems
3385	// Where outerHTML is undefined, this still works
3386	support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>";
3387
3388	// Will be defined later
3389	support.inlineBlockNeedsLayout = false;
3390	support.shrinkWrapBlocks = false;
3391	support.pixelPosition = false;
3392	support.deleteExpando = true;
3393	support.noCloneEvent = true;
3394	support.reliableMarginRight = true;
3395	support.boxSizingReliable = true;
3396
3397	// Make sure checked status is properly cloned
3398	input.checked = true;
3399	support.noCloneChecked = input.cloneNode( true ).checked;
3400
3401	// Make sure that the options inside disabled selects aren't marked as disabled
3402	// (WebKit marks them as disabled)
3403	select.disabled = true;
3404	support.optDisabled = !opt.disabled;
3405
3406	// Support: IE<9
3407	try {
3408		delete div.test;
3409	} catch( e ) {
3410		support.deleteExpando = false;
3411	}
3412
3413	// Check if we can trust getAttribute("value")
3414	input = document.createElement("input");
3415	input.setAttribute( "value", "" );
3416	support.input = input.getAttribute( "value" ) === "";
3417
3418	// Check if an input maintains its value after becoming a radio
3419	input.value = "t";
3420	input.setAttribute( "type", "radio" );
3421	support.radioValue = input.value === "t";
3422
3423	// #11217 - WebKit loses check when the name is after the checked attribute
3424	input.setAttribute( "checked", "t" );
3425	input.setAttribute( "name", "t" );
3426
3427	fragment = document.createDocumentFragment();
3428	fragment.appendChild( input );
3429
3430	// Check if a disconnected checkbox will retain its checked
3431	// value of true after appended to the DOM (IE6/7)
3432	support.appendChecked = input.checked;
3433
3434	// WebKit doesn't clone checked state correctly in fragments
3435	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
3436
3437	// Support: IE<9
3438	// Opera does not clone events (and typeof div.attachEvent === undefined).
3439	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
3440	if ( div.attachEvent ) {
3441		div.attachEvent( "onclick", function() {
3442			support.noCloneEvent = false;
3443		});
3444
3445		div.cloneNode( true ).click();
3446	}
3447
3448	// Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
3449	// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
3450	for ( i in { submit: true, change: true, focusin: true }) {
3451		div.setAttribute( eventName = "on" + i, "t" );
3452
3453		support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
3454	}
3455
3456	div.style.backgroundClip = "content-box";
3457	div.cloneNode( true ).style.backgroundClip = "";
3458	support.clearCloneStyle = div.style.backgroundClip === "content-box";
3459
3460	// Support: IE<9
3461	// Iteration over object's inherited properties before its own.
3462	for ( i in jQuery( support ) ) {
3463		break;
3464	}
3465	support.ownLast = i !== "0";
3466
3467	// Run tests that need a body at doc ready
3468	jQuery(function() {
3469		var container, marginDiv, tds,
3470			divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
3471			body = document.getElementsByTagName("body")[0];
3472
3473		if ( !body ) {
3474			// Return for frameset docs that don't have a body
3475			return;
3476		}
3477
3478		container = document.createElement("div");
3479		container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
3480
3481		body.appendChild( container ).appendChild( div );
3482
3483		// Support: IE8
3484		// Check if table cells still have offsetWidth/Height when they are set
3485		// to display:none and there are still other visible table cells in a
3486		// table row; if so, offsetWidth/Height are not reliable for use when
3487		// determining if an element has been hidden directly using
3488		// display:none (it is still safe to use offsets if a parent element is
3489		// hidden; don safety goggles and see bug #4512 for more information).
3490		div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
3491		tds = div.getElementsByTagName("td");
3492		tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
3493		isSupported = ( tds[ 0 ].offsetHeight === 0 );
3494
3495		tds[ 0 ].style.display = "";
3496		tds[ 1 ].style.display = "none";
3497
3498		// Support: IE8
3499		// Check if empty table cells still have offsetWidth/Height
3500		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
3501
3502		// Check box-sizing and margin behavior.
3503		div.innerHTML = "";
3504		div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
3505
3506		// Workaround failing boxSizing test due to offsetWidth returning wrong value
3507		// with some non-1 values of body zoom, ticket #13543
3508		jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {
3509			support.boxSizing = div.offsetWidth === 4;
3510		});
3511
3512		// Use window.getComputedStyle because jsdom on node.js will break without it.
3513		if ( window.getComputedStyle ) {
3514			support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
3515			support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
3516
3517			// Check if div with explicit width and no margin-right incorrectly
3518			// gets computed margin-right based on width of container. (#3333)
3519			// Fails in WebKit before Feb 2011 nightlies
3520			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
3521			marginDiv = div.appendChild( document.createElement("div") );
3522			marginDiv.style.cssText = div.style.cssText = divReset;
3523			marginDiv.style.marginRight = marginDiv.style.width = "0";
3524			div.style.width = "1px";
3525
3526			support.reliableMarginRight =
3527				!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
3528		}
3529
3530		if ( typeof div.style.zoom !== core_strundefined ) {
3531			// Support: IE<8
3532			// Check if natively block-level elements act like inline-block
3533			// elements when setting their display to 'inline' and giving
3534			// them layout
3535			div.innerHTML = "";
3536			div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
3537			support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
3538
3539			// Support: IE6
3540			// Check if elements with layout shrink-wrap their children
3541			div.style.display = "block";
3542			div.innerHTML = "<div></div>";
3543			div.firstChild.style.width = "5px";
3544			support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
3545
3546			if ( support.inlineBlockNeedsLayout ) {
3547				// Prevent IE 6 from affecting layout for positioned elements #11048
3548				// Prevent IE from shrinking the body in IE 7 mode #12869
vendor: 4,821 bytes, lines 3549-3726
3549				// Support: IE<8
3550				body.style.zoom = 1;
3551			}
3552		}
3553
3554		body.removeChild( container );
3555
3556		// Null elements to avoid leaks in IE
3557		container = div = tds = marginDiv = null;
3558	});
3559
3560	// Null elements to avoid leaks in IE
3561	all = select = fragment = opt = a = input = null;
3562
3563	return support;
3564})({});
3565
3566var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
3567	rmultiDash = /([A-Z])/g;
3568
3569function internalData( elem, name, data, pvt /* Internal Use Only */ ){
3570	if ( !jQuery.acceptData( elem ) ) {
3571		return;
3572	}
3573
3574	var ret, thisCache,
3575		internalKey = jQuery.expando,
3576
3577		// We have to handle DOM nodes and JS objects differently because IE6-7
3578		// can't GC object references properly across the DOM-JS boundary
3579		isNode = elem.nodeType,
3580
3581		// Only DOM nodes need the global jQuery cache; JS object data is
3582		// attached directly to the object so GC can occur automatically
3583		cache = isNode ? jQuery.cache : elem,
3584
3585		// Only defining an ID for JS objects if its cache already exists allows
3586		// the code to shortcut on the same path as a DOM node with no cache
3587		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
3588
3589	// Avoid doing any more work than we need to when trying to get data on an
3590	// object that has no data at all
3591	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
3592		return;
3593	}
3594
3595	if ( !id ) {
3596		// Only DOM nodes need a new unique ID for each element since their data
3597		// ends up in the global cache
3598		if ( isNode ) {
3599			id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++;
3600		} else {
3601			id = internalKey;
3602		}
3603	}
3604
3605	if ( !cache[ id ] ) {
3606		// Avoid exposing jQuery metadata on plain JS objects when the object
3607		// is serialized using JSON.stringify
3608		cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
3609	}
3610
3611	// An object can be passed to jQuery.data instead of a key/value pair; this gets
3612	// shallow copied over onto the existing cache
3613	if ( typeof name === "object" || typeof name === "function" ) {
3614		if ( pvt ) {
3615			cache[ id ] = jQuery.extend( cache[ id ], name );
3616		} else {
3617			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
3618		}
3619	}
3620
3621	thisCache = cache[ id ];
3622
3623	// jQuery data() is stored in a separate object inside the object's internal data
3624	// cache in order to avoid key collisions between internal data and user-defined
3625	// data.
3626	if ( !pvt ) {
3627		if ( !thisCache.data ) {
3628			thisCache.data = {};
3629		}
3630
3631		thisCache = thisCache.data;
3632	}
3633
3634	if ( data !== undefined ) {
3635		thisCache[ jQuery.camelCase( name ) ] = data;
3636	}
3637
3638	// Check for both converted-to-camel and non-converted data property names
3639	// If a data property was specified
3640	if ( typeof name === "string" ) {
3641
3642		// First Try to find as-is property data
3643		ret = thisCache[ name ];
3644
3645		// Test for null|undefined property data
3646		if ( ret == null ) {
3647
3648			// Try to find the camelCased property
3649			ret = thisCache[ jQuery.camelCase( name ) ];
3650		}
3651	} else {
3652		ret = thisCache;
3653	}
3654
3655	return ret;
3656}
3657
3658function internalRemoveData( elem, name, pvt ) {
3659	if ( !jQuery.acceptData( elem ) ) {
3660		return;
3661	}
3662
3663	var thisCache, i,
3664		isNode = elem.nodeType,
3665
3666		// See jQuery.data for more information
3667		cache = isNode ? jQuery.cache : elem,
3668		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
3669
3670	// If there is already no cache entry for this object, there is no
3671	// purpose in continuing
3672	if ( !cache[ id ] ) {
3673		return;
3674	}
3675
3676	if ( name ) {
3677
3678		thisCache = pvt ? cache[ id ] : cache[ id ].data;
3679
3680		if ( thisCache ) {
3681
3682			// Support array or space separated string names for data keys
3683			if ( !jQuery.isArray( name ) ) {
3684
3685				// try the string as a key before any manipulation
3686				if ( name in thisCache ) {
3687					name = [ name ];
3688				} else {
3689
3690					// split the camel cased version by spaces unless a key with the spaces exists
3691					name = jQuery.camelCase( name );
3692					if ( name in thisCache ) {
3693						name = [ name ];
3694					} else {
3695						name = name.split(" ");
3696					}
3697				}
3698			} else {
3699				// If "name" is an array of keys...
3700				// When data is initially created, via ("key", "val") signature,
3701				// keys will be converted to camelCase.
3702				// Since there is no way to tell _how_ a key was added, remove
3703				// both plain key and camelCase key. #12786
3704				// This will only penalize the array argument path.
3705				name = name.concat( jQuery.map( name, jQuery.camelCase ) );
3706			}
3707
3708			i = name.length;
3709			while ( i-- ) {
3710				delete thisCache[ name[i] ];
3711			}
3712
3713			// If there is no data left in the cache, we want to continue
3714			// and let the cache object itself get destroyed
3715			if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
3716				return;
3717			}
3718		}
3719	}
3720
3721	// See jQuery.data for more information
3722	if ( !pvt ) {
3723		delete cache[ id ].data;
3724
3725		// Don't destroy the parent cache unless the internal data object
3726		// had been the only thing left in it
3727		if ( !isEmptyDataObject( cache[ id ] ) ) {
3728			return;
3729		}
3730	}
3731
3732	// Destroy the cache
3733	if ( isNode ) {
3734		jQuery.cleanData( [ elem ], true );
3735
3736	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
3737	/* jshint eqeqeq: false */
3738	} else if ( jQuery.support.deleteExpando || cache != cache.window ) {
3739		/* jshint eqeqeq: true */
3740		delete cache[ id ];
3741
3742	// When all else fails, null
3743	} else {
3744		cache[ id ] = null;
3745	}
3746}
3747
3748jQuery.extend({
3749	cache: {},
3750
3751	// The following elements throw uncatchable exceptions if you
3752	// attempt to add expando properties to them.
3753	noData: {
3754		"applet": true,
3755		"embed": true,
3756		// Ban all objects except for Flash (which handle expandos)
3757		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
3758	},
3759
3760	hasData: function( elem ) {
3761		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
3762		return !!elem && !isEmptyDataObject( elem );
3763	},
3764
3765	data: function( elem, name, data ) {
3766		return internalData( elem, name, data );
3767	},
3768
3769	removeData: function( elem, name ) {
3770		return internalRemoveData( elem, name );
3771	},
3772
3773	// For internal use only.
3774	_data: function( elem, name, data ) {
3775		return internalData( elem, name, data, true );
3776	},
3777
3778	_removeData: function( elem, name ) {
3779		return internalRemoveData( elem, name, true );
3780	},
3781
3782	// A method for determining if a DOM node can handle the data expando
3783	acceptData: function( elem ) {
3784		// Do not set data on non-element because it will not be cleared (#8335).
3785		if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
3786			return false;
3787		}
3788
3789		var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
3790
3791		// nodes accept data unless otherwise specified; rejection can be conditional
3792		return !noData || noData !== true && elem.getAttribute("classid") === noData;
3793	}
3794});
3795
3796jQuery.fn.extend({
3797	data: function( key, value ) {
3798		var attrs, name,
3799			data = null,
3800			i = 0,
3801			elem = this[0];
3802
3803		// Special expections of .data basically thwart jQuery.access,
3804		// so implement the relevant behavior ourselves
3805
3806		// Gets all values
3807		if ( key === undefined ) {
3808			if ( this.length ) {
3809				data = jQuery.data( elem );
3810
3811				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
3812					attrs = elem.attributes;
3813					for ( ; i < attrs.length; i++ ) {
3814						name = attrs[i].name;
3815
3816						if ( name.indexOf("data-") === 0 ) {
3817							name = jQuery.camelCase( name.slice(5) );
3818
3819							dataAttr( elem, name, data[ name ] );
3820						}
3821					}
3822					jQuery._data( elem, "parsedAttrs", true );
3823				}
3824			}
3825
3826			return data;
3827		}
3828
3829		// Sets multiple values
3830		if ( typeof key === "object" ) {
3831			return this.each(function() {
3832				jQuery.data( this, key );
3833			});
3834		}
3835
3836		return arguments.length > 1 ?
3837
3838			// Sets one value
3839			this.each(function() {
3840				jQuery.data( this, key, value );
3841			}) :
3842
3843			// Gets one value
3844			// Try to fetch any internally stored data first
3845			elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
3846	},
3847
3848	removeData: function( key ) {
3849		return this.each(function() {
3850			jQuery.removeData( this, key );
3851		});
3852	}
3853});
3854
3855function dataAttr( elem, key, data ) {
3856	// If nothing was found internally, try to fetch any
3857	// data from the HTML5 data-* attribute
3858	if ( data === undefined && elem.nodeType === 1 ) {
3859
3860		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
3861
3862		data = elem.getAttribute( name );
3863
3864		if ( typeof data === "string" ) {
3865			try {
3866				data = data === "true" ? true :
3867					data === "false" ? false :
3868					data === "null" ? null :
3869					// Only convert to a number if it doesn't change the string
3870					+data + "" === data ? +data :
3871					rbrace.test( data ) ? jQuery.parseJSON( data ) :
3872						data;
3873			} catch( e ) {}
3874
3875			// Make sure we set the data so it isn't changed later
3876			jQuery.data( elem, key, data );
3877
3878		} else {
3879			data = undefined;
3880		}
3881	}
3882
3883	return data;
3884}
3885
3886// checks a cache object for emptiness
3887function isEmptyDataObject( obj ) {
3888	var name;
3889	for ( name in obj ) {
3890
3891		// if the public data object is empty, the private is still empty
3892		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
3893			continue;
3894		}
3895		if ( name !== "toJSON" ) {
3896			return false;
vendor: 5,969 bytes, lines 3897-4146
3897		}
3898	}
3899
3900	return true;
3901}
3902jQuery.extend({
3903	queue: function( elem, type, data ) {
3904		var queue;
3905
3906		if ( elem ) {
3907			type = ( type || "fx" ) + "queue";
3908			queue = jQuery._data( elem, type );
3909
3910			// Speed up dequeue by getting out quickly if this is just a lookup
3911			if ( data ) {
3912				if ( !queue || jQuery.isArray(data) ) {
3913					queue = jQuery._data( elem, type, jQuery.makeArray(data) );
3914				} else {
3915					queue.push( data );
3916				}
3917			}
3918			return queue || [];
3919		}
3920	},
3921
3922	dequeue: function( elem, type ) {
3923		type = type || "fx";
3924
3925		var queue = jQuery.queue( elem, type ),
3926			startLength = queue.length,
3927			fn = queue.shift(),
3928			hooks = jQuery._queueHooks( elem, type ),
3929			next = function() {
3930				jQuery.dequeue( elem, type );
3931			};
3932
3933		// If the fx queue is dequeued, always remove the progress sentinel
3934		if ( fn === "inprogress" ) {
3935			fn = queue.shift();
3936			startLength--;
3937		}
3938
3939		if ( fn ) {
3940
3941			// Add a progress sentinel to prevent the fx queue from being
3942			// automatically dequeued
3943			if ( type === "fx" ) {
3944				queue.unshift( "inprogress" );
3945			}
3946
3947			// clear up the last queue stop function
3948			delete hooks.stop;
3949			fn.call( elem, next, hooks );
3950		}
3951
3952		if ( !startLength && hooks ) {
3953			hooks.empty.fire();
3954		}
3955	},
3956
3957	// not intended for public consumption - generates a queueHooks object, or returns the current one
3958	_queueHooks: function( elem, type ) {
3959		var key = type + "queueHooks";
3960		return jQuery._data( elem, key ) || jQuery._data( elem, key, {
3961			empty: jQuery.Callbacks("once memory").add(function() {
3962				jQuery._removeData( elem, type + "queue" );
3963				jQuery._removeData( elem, key );
3964			})
3965		});
3966	}
3967});
3968
3969jQuery.fn.extend({
3970	queue: function( type, data ) {
3971		var setter = 2;
3972
3973		if ( typeof type !== "string" ) {
3974			data = type;
3975			type = "fx";
3976			setter--;
3977		}
3978
3979		if ( arguments.length < setter ) {
3980			return jQuery.queue( this[0], type );
3981		}
3982
3983		return data === undefined ?
3984			this :
3985			this.each(function() {
3986				var queue = jQuery.queue( this, type, data );
3987
3988				// ensure a hooks for this queue
3989				jQuery._queueHooks( this, type );
3990
3991				if ( type === "fx" && queue[0] !== "inprogress" ) {
3992					jQuery.dequeue( this, type );
3993				}
3994			});
3995	},
3996	dequeue: function( type ) {
3997		return this.each(function() {
3998			jQuery.dequeue( this, type );
3999		});
4000	},
4001	// Based off of the plugin by Clint Helfers, with permission.
4002	// http://blindsignals.com/index.php/2009/07/jquery-delay/
4003	delay: function( time, type ) {
4004		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
4005		type = type || "fx";
4006
4007		return this.queue( type, function( next, hooks ) {
4008			var timeout = setTimeout( next, time );
4009			hooks.stop = function() {
4010				clearTimeout( timeout );
4011			};
4012		});
4013	},
4014	clearQueue: function( type ) {
4015		return this.queue( type || "fx", [] );
4016	},
4017	// Get a promise resolved when queues of a certain type
4018	// are emptied (fx is the type by default)
4019	promise: function( type, obj ) {
4020		var tmp,
4021			count = 1,
4022			defer = jQuery.Deferred(),
4023			elements = this,
4024			i = this.length,
4025			resolve = function() {
4026				if ( !( --count ) ) {
4027					defer.resolveWith( elements, [ elements ] );
4028				}
4029			};
4030
4031		if ( typeof type !== "string" ) {
4032			obj = type;
4033			type = undefined;
4034		}
4035		type = type || "fx";
4036
4037		while( i-- ) {
4038			tmp = jQuery._data( elements[ i ], type + "queueHooks" );
4039			if ( tmp && tmp.empty ) {
4040				count++;
4041				tmp.empty.add( resolve );
4042			}
4043		}
4044		resolve();
4045		return defer.promise( obj );
4046	}
4047});
4048var nodeHook, boolHook,
4049	rclass = /[\t\r\n\f]/g,
4050	rreturn = /\r/g,
4051	rfocusable = /^(?:input|select|textarea|button|object)$/i,
4052	rclickable = /^(?:a|area)$/i,
4053	ruseDefault = /^(?:checked|selected)$/i,
4054	getSetAttribute = jQuery.support.getSetAttribute,
4055	getSetInput = jQuery.support.input;
4056
4057jQuery.fn.extend({
4058	attr: function( name, value ) {
4059		return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
4060	},
4061
4062	removeAttr: function( name ) {
4063		return this.each(function() {
4064			jQuery.removeAttr( this, name );
4065		});
4066	},
4067
4068	prop: function( name, value ) {
4069		return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
4070	},
4071
4072	removeProp: function( name ) {
4073		name = jQuery.propFix[ name ] || name;
4074		return this.each(function() {
4075			// try/catch handles cases where IE balks (such as removing a property on window)
4076			try {
4077				this[ name ] = undefined;
4078				delete this[ name ];
4079			} catch( e ) {}
4080		});
4081	},
4082
4083	addClass: function( value ) {
4084		var classes, elem, cur, clazz, j,
4085			i = 0,
4086			len = this.length,
4087			proceed = typeof value === "string" && value;
4088
4089		if ( jQuery.isFunction( value ) ) {
4090			return this.each(function( j ) {
4091				jQuery( this ).addClass( value.call( this, j, this.className ) );
4092			});
4093		}
4094
4095		if ( proceed ) {
4096			// The disjunction here is for better compressibility (see removeClass)
4097			classes = ( value || "" ).match( core_rnotwhite ) || [];
4098
4099			for ( ; i < len; i++ ) {
4100				elem = this[ i ];
4101				cur = elem.nodeType === 1 && ( elem.className ?
4102					( " " + elem.className + " " ).replace( rclass, " " ) :
4103					" "
4104				);
4105
4106				if ( cur ) {
4107					j = 0;
4108					while ( (clazz = classes[j++]) ) {
4109						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
4110							cur += clazz + " ";
4111						}
4112					}
4113					elem.className = jQuery.trim( cur );
4114
4115				}
4116			}
4117		}
4118
4119		return this;
4120	},
4121
4122	removeClass: function( value ) {
4123		var classes, elem, cur, clazz, j,
4124			i = 0,
4125			len = this.length,
4126			proceed = arguments.length === 0 || typeof value === "string" && value;
4127
4128		if ( jQuery.isFunction( value ) ) {
4129			return this.each(function( j ) {
4130				jQuery( this ).removeClass( value.call( this, j, this.className ) );
4131			});
4132		}
4133		if ( proceed ) {
4134			classes = ( value || "" ).match( core_rnotwhite ) || [];
4135
4136			for ( ; i < len; i++ ) {
4137				elem = this[ i ];
4138				// This expression is here for better compressibility (see addClass)
4139				cur = elem.nodeType === 1 && ( elem.className ?
4140					( " " + elem.className + " " ).replace( rclass, " " ) :
4141					""
4142				);
4143
4144				if ( cur ) {
4145					j = 0;
4146					while ( (clazz = classes[j++]) ) {
vendor: 6,992 bytes, lines 4147-4411
4147						// Remove *all* instances
4148						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
4149							cur = cur.replace( " " + clazz + " ", " " );
4150						}
4151					}
4152					elem.className = value ? jQuery.trim( cur ) : "";
4153				}
4154			}
4155		}
4156
4157		return this;
4158	},
4159
4160	toggleClass: function( value, stateVal ) {
4161		var type = typeof value;
4162
4163		if ( typeof stateVal === "boolean" && type === "string" ) {
4164			return stateVal ? this.addClass( value ) : this.removeClass( value );
4165		}
4166
4167		if ( jQuery.isFunction( value ) ) {
4168			return this.each(function( i ) {
4169				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
4170			});
4171		}
4172
4173		return this.each(function() {
4174			if ( type === "string" ) {
4175				// toggle individual class names
4176				var className,
4177					i = 0,
4178					self = jQuery( this ),
4179					classNames = value.match( core_rnotwhite ) || [];
4180
4181				while ( (className = classNames[ i++ ]) ) {
4182					// check each className given, space separated list
4183					if ( self.hasClass( className ) ) {
4184						self.removeClass( className );
4185					} else {
4186						self.addClass( className );
4187					}
4188				}
4189
4190			// Toggle whole class name
4191			} else if ( type === core_strundefined || type === "boolean" ) {
4192				if ( this.className ) {
4193					// store className if set
4194					jQuery._data( this, "__className__", this.className );
4195				}
4196
4197				// If the element has a class name or if we're passed "false",
4198				// then remove the whole classname (if there was one, the above saved it).
4199				// Otherwise bring back whatever was previously saved (if anything),
4200				// falling back to the empty string if nothing was stored.
4201				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
4202			}
4203		});
4204	},
4205
4206	hasClass: function( selector ) {
4207		var className = " " + selector + " ",
4208			i = 0,
4209			l = this.length;
4210		for ( ; i < l; i++ ) {
4211			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
4212				return true;
4213			}
4214		}
4215
4216		return false;
4217	},
4218
4219	val: function( value ) {
4220		var ret, hooks, isFunction,
4221			elem = this[0];
4222
4223		if ( !arguments.length ) {
4224			if ( elem ) {
4225				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
4226
4227				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
4228					return ret;
4229				}
4230
4231				ret = elem.value;
4232
4233				return typeof ret === "string" ?
4234					// handle most common string cases
4235					ret.replace(rreturn, "") :
4236					// handle cases where value is null/undef or number
4237					ret == null ? "" : ret;
4238			}
4239
4240			return;
4241		}
4242
4243		isFunction = jQuery.isFunction( value );
4244
4245		return this.each(function( i ) {
4246			var val;
4247
4248			if ( this.nodeType !== 1 ) {
4249				return;
4250			}
4251
4252			if ( isFunction ) {
4253				val = value.call( this, i, jQuery( this ).val() );
4254			} else {
4255				val = value;
4256			}
4257
4258			// Treat null/undefined as ""; convert numbers to string
4259			if ( val == null ) {
4260				val = "";
4261			} else if ( typeof val === "number" ) {
4262				val += "";
4263			} else if ( jQuery.isArray( val ) ) {
4264				val = jQuery.map(val, function ( value ) {
4265					return value == null ? "" : value + "";
4266				});
4267			}
4268
4269			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
4270
4271			// If set returns undefined, fall back to normal setting
4272			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
4273				this.value = val;
4274			}
4275		});
4276	}
4277});
4278
4279jQuery.extend({
4280	valHooks: {
4281		option: {
4282			get: function( elem ) {
4283				// Use proper attribute retrieval(#6932, #12072)
4284				var val = jQuery.find.attr( elem, "value" );
4285				return val != null ?
4286					val :
4287					elem.text;
4288			}
4289		},
4290		select: {
4291			get: function( elem ) {
4292				var value, option,
4293					options = elem.options,
4294					index = elem.selectedIndex,
4295					one = elem.type === "select-one" || index < 0,
4296					values = one ? null : [],
4297					max = one ? index + 1 : options.length,
4298					i = index < 0 ?
4299						max :
4300						one ? index : 0;
4301
4302				// Loop through all the selected options
4303				for ( ; i < max; i++ ) {
4304					option = options[ i ];
4305
4306					// oldIE doesn't update selected after form reset (#2551)
4307					if ( ( option.selected || i === index ) &&
4308							// Don't return options that are disabled or in a disabled optgroup
4309							( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
4310							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
4311
4312						// Get the specific value for the option
4313						value = jQuery( option ).val();
4314
4315						// We don't need an array for one selects
4316						if ( one ) {
4317							return value;
4318						}
4319
4320						// Multi-Selects return an array
4321						values.push( value );
4322					}
4323				}
4324
4325				return values;
4326			},
4327
4328			set: function( elem, value ) {
4329				var optionSet, option,
4330					options = elem.options,
4331					values = jQuery.makeArray( value ),
4332					i = options.length;
4333
4334				while ( i-- ) {
4335					option = options[ i ];
4336					if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {
4337						optionSet = true;
4338					}
4339				}
4340
4341				// force browsers to behave consistently when non-matching value is set
4342				if ( !optionSet ) {
4343					elem.selectedIndex = -1;
4344				}
4345				return values;
4346			}
4347		}
4348	},
4349
4350	attr: function( elem, name, value ) {
4351		var hooks, ret,
4352			nType = elem.nodeType;
4353
4354		// don't get/set attributes on text, comment and attribute nodes
4355		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
4356			return;
4357		}
4358
4359		// Fallback to prop when attributes are not supported
4360		if ( typeof elem.getAttribute === core_strundefined ) {
4361			return jQuery.prop( elem, name, value );
4362		}
4363
4364		// All attributes are lowercase
4365		// Grab necessary hook if one is defined
4366		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
4367			name = name.toLowerCase();
4368			hooks = jQuery.attrHooks[ name ] ||
4369				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
4370		}
4371
4372		if ( value !== undefined ) {
4373
4374			if ( value === null ) {
4375				jQuery.removeAttr( elem, name );
4376
4377			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
4378				return ret;
4379
4380			} else {
4381				elem.setAttribute( name, value + "" );
4382				return value;
4383			}
4384
4385		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
4386			return ret;
4387
4388		} else {
4389			ret = jQuery.find.attr( elem, name );
4390
4391			// Non-existent attributes return null, we normalize to undefined
4392			return ret == null ?
4393				undefined :
4394				ret;
4395		}
4396	},
4397
4398	removeAttr: function( elem, value ) {
4399		var name, propName,
4400			i = 0,
4401			attrNames = value && value.match( core_rnotwhite );
4402
4403		if ( attrNames && elem.nodeType === 1 ) {
4404			while ( (name = attrNames[i++]) ) {
4405				propName = jQuery.propFix[ name ] || name;
4406
4407				// Boolean attributes get special treatment (#10870)
4408				if ( jQuery.expr.match.bool.test( name ) ) {
4409					// Set corresponding property to false
4410					if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
4411						elem[ propName ] = false;
4412					// Support: IE<9
4413					// Also clear defaultChecked/defaultSelected (if appropriate)
4414					} else {
4415						elem[ jQuery.camelCase( "default-" + name ) ] =
4416							elem[ propName ] = false;
4417					}
4418
4419				// See #9699 for explanation of this approach (setting first, then removal)
4420				} else {
4421					jQuery.attr( elem, name, "" );
4422				}
4423
4424				elem.removeAttribute( getSetAttribute ? name : propName );
4425			}
4426		}
4427	},
4428
4429	attrHooks: {
4430		type: {
4431			set: function( elem, value ) {
4432				if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
4433					// Setting the type on a radio button after the value resets the value in IE6-9
4434					// Reset value to default in case type is set after value during creation
4435					var val = elem.value;
4436					elem.setAttribute( "type", value );
4437					if ( val ) {
4438						elem.value = val;
4439					}
4440					return value;
4441				}
4442			}
4443		}
4444	},
4445
4446	propFix: {
4447		"for": "htmlFor",
4448		"class": "className"
4449	},
4450
4451	prop: function( elem, name, value ) {
4452		var ret, hooks, notxml,
4453			nType = elem.nodeType;
4454
4455		// don't get/set properties on text, comment and attribute nodes
4456		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
4457			return;
4458		}
4459
4460		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
4461
4462		if ( notxml ) {
4463			// Fix name and attach hooks
4464			name = jQuery.propFix[ name ] || name;
4465			hooks = jQuery.propHooks[ name ];
4466		}
4467
4468		if ( value !== undefined ) {
4469			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
4470				ret :
4471				( elem[ name ] = value );
4472
4473		} else {
4474			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
4475				ret :
4476				elem[ name ];
4477		}
4478	},
4479
4480	propHooks: {
4481		tabIndex: {
4482			get: function( elem ) {
4483				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
4484				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
4485				// Use proper attribute retrieval(#12072)
4486				var tabindex = jQuery.find.attr( elem, "tabindex" );
4487
4488				return tabindex ?
4489					parseInt( tabindex, 10 ) :
4490					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
4491						0 :
4492						-1;
4493			}
4494		}
4495	}
4496});
4497
4498// Hooks for boolean attributes
4499boolHook = {
4500	set: function( elem, value, name ) {
4501		if ( value === false ) {
4502			// Remove boolean attributes when set to false
4503			jQuery.removeAttr( elem, name );
4504		} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
4505			// IE<8 needs the *property* name
4506			elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
4507
4508		// Use defaultChecked and defaultSelected for oldIE
4509		} else {
4510			elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
4511		}
4512
4513		return name;
4514	}
4515};
4516jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
4517	var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;
4518
4519	jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
4520		function( elem, name, isXML ) {
4521			var fn = jQuery.expr.attrHandle[ name ],
4522				ret = isXML ?
4523					undefined :
4524					/* jshint eqeqeq: false */
4525					(jQuery.expr.attrHandle[ name ] = undefined) !=
4526						getter( elem, name, isXML ) ?
4527
4528						name.toLowerCase() :
4529						null;
4530			jQuery.expr.attrHandle[ name ] = fn;
4531			return ret;
4532		} :
4533		function( elem, name, isXML ) {
4534			return isXML ?
4535				undefined :
4536				elem[ jQuery.camelCase( "default-" + name ) ] ?
4537					name.toLowerCase() :
4538					null;
4539		};
4540});
4541
4542// fix oldIE attroperties
4543if ( !getSetInput || !getSetAttribute ) {
4544	jQuery.attrHooks.value = {
4545		set: function( elem, value, name ) {
4546			if ( jQuery.nodeName( elem, "input" ) ) {
4547				// Does not return so that setAttribute is also used
4548				elem.defaultValue = value;
4549			} else {
4550				// Use nodeHook if defined (#1954); otherwise setAttribute is fine
4551				return nodeHook && nodeHook.set( elem, value, name );
4552			}
4553		}
4554	};
4555}
4556
4557// IE6/7 do not support getting/setting some attributes with get/setAttribute
4558if ( !getSetAttribute ) {
4559
4560	// Use this for any attribute in IE6/7
4561	// This fixes almost every IE6/7 issue
4562	nodeHook = {
4563		set: function( elem, value, name ) {
4564			// Set the existing or create a new attribute node
4565			var ret = elem.getAttributeNode( name );
4566			if ( !ret ) {
4567				elem.setAttributeNode(
4568					(ret = elem.ownerDocument.createAttribute( name ))
4569				);
4570			}
4571
4572			ret.value = value += "";
4573
4574			// Break association with cloned elements by also using setAttribute (#9646)
4575			return name === "value" || value === elem.getAttribute( name ) ?
4576				value :
4577				undefined;
4578		}
4579	};
4580	jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords =
4581		// Some attributes are constructed with empty-string values when not defined
4582		function( elem, name, isXML ) {
4583			var ret;
4584			return isXML ?
4585				undefined :
4586				(ret = elem.getAttributeNode( name )) && ret.value !== "" ?
4587					ret.value :
4588					null;
4589		};
4590	jQuery.valHooks.button = {
4591		get: function( elem, name ) {
4592			var ret = elem.getAttributeNode( name );
4593			return ret && ret.specified ?
4594				ret.value :
4595				undefined;
4596		},
4597		set: nodeHook.set
4598	};
4599
4600	// Set contenteditable to false on removals(#10429)
vendor: 13,769 bytes, lines 4601-5064
4601	// Setting to empty string throws an error as an invalid value
4602	jQuery.attrHooks.contenteditable = {
4603		set: function( elem, value, name ) {
4604			nodeHook.set( elem, value === "" ? false : value, name );
4605		}
4606	};
4607
4608	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
4609	// This is for removals
4610	jQuery.each([ "width", "height" ], function( i, name ) {
4611		jQuery.attrHooks[ name ] = {
4612			set: function( elem, value ) {
4613				if ( value === "" ) {
4614					elem.setAttribute( name, "auto" );
4615					return value;
4616				}
4617			}
4618		};
4619	});
4620}
4621
4622
4623// Some attributes require a special call on IE
4624// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
4625if ( !jQuery.support.hrefNormalized ) {
4626	// href/src property should get the full normalized URL (#10299/#12915)
4627	jQuery.each([ "href", "src" ], function( i, name ) {
4628		jQuery.propHooks[ name ] = {
4629			get: function( elem ) {
4630				return elem.getAttribute( name, 4 );
4631			}
4632		};
4633	});
4634}
4635
4636if ( !jQuery.support.style ) {
4637	jQuery.attrHooks.style = {
4638		get: function( elem ) {
4639			// Return undefined in the case of empty string
4640			// Note: IE uppercases css property names, but if we were to .toLowerCase()
4641			// .cssText, that would destroy case senstitivity in URL's, like in "background"
4642			return elem.style.cssText || undefined;
4643		},
4644		set: function( elem, value ) {
4645			return ( elem.style.cssText = value + "" );
4646		}
4647	};
4648}
4649
4650// Safari mis-reports the default selected property of an option
4651// Accessing the parent's selectedIndex property fixes it
4652if ( !jQuery.support.optSelected ) {
4653	jQuery.propHooks.selected = {
4654		get: function( elem ) {
4655			var parent = elem.parentNode;
4656
4657			if ( parent ) {
4658				parent.selectedIndex;
4659
4660				// Make sure that it also works with optgroups, see #5701
4661				if ( parent.parentNode ) {
4662					parent.parentNode.selectedIndex;
4663				}
4664			}
4665			return null;
4666		}
4667	};
4668}
4669
4670jQuery.each([
4671	"tabIndex",
4672	"readOnly",
4673	"maxLength",
4674	"cellSpacing",
4675	"cellPadding",
4676	"rowSpan",
4677	"colSpan",
4678	"useMap",
4679	"frameBorder",
4680	"contentEditable"
4681], function() {
4682	jQuery.propFix[ this.toLowerCase() ] = this;
4683});
4684
4685// IE6/7 call enctype encoding
4686if ( !jQuery.support.enctype ) {
4687	jQuery.propFix.enctype = "encoding";
4688}
4689
4690// Radios and checkboxes getter/setter
4691jQuery.each([ "radio", "checkbox" ], function() {
4692	jQuery.valHooks[ this ] = {
4693		set: function( elem, value ) {
4694			if ( jQuery.isArray( value ) ) {
4695				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
4696			}
4697		}
4698	};
4699	if ( !jQuery.support.checkOn ) {
4700		jQuery.valHooks[ this ].get = function( elem ) {
4701			// Support: Webkit
4702			// "" is returned instead of "on" if a value isn't specified
4703			return elem.getAttribute("value") === null ? "on" : elem.value;
4704		};
4705	}
4706});
4707var rformElems = /^(?:input|select|textarea)$/i,
4708	rkeyEvent = /^key/,
4709	rmouseEvent = /^(?:mouse|contextmenu)|click/,
4710	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
4711	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
4712
4713function returnTrue() {
4714	return true;
4715}
4716
4717function returnFalse() {
4718	return false;
4719}
4720
4721function safeActiveElement() {
4722	try {
4723		return document.activeElement;
4724	} catch ( err ) { }
4725}
4726
4727/*
4728 * Helper functions for managing events -- not part of the public interface.
4729 * Props to Dean Edwards' addEvent library for many of the ideas.
4730 */
4731jQuery.event = {
4732
4733	global: {},
4734
4735	add: function( elem, types, handler, data, selector ) {
4736		var tmp, events, t, handleObjIn,
4737			special, eventHandle, handleObj,
4738			handlers, type, namespaces, origType,
4739			elemData = jQuery._data( elem );
4740
4741		// Don't attach events to noData or text/comment nodes (but allow plain objects)
4742		if ( !elemData ) {
4743			return;
4744		}
4745
4746		// Caller can pass in an object of custom data in lieu of the handler
4747		if ( handler.handler ) {
4748			handleObjIn = handler;
4749			handler = handleObjIn.handler;
4750			selector = handleObjIn.selector;
4751		}
4752
4753		// Make sure that the handler has a unique ID, used to find/remove it later
4754		if ( !handler.guid ) {
4755			handler.guid = jQuery.guid++;
4756		}
4757
4758		// Init the element's event structure and main handler, if this is the first
4759		if ( !(events = elemData.events) ) {
4760			events = elemData.events = {};
4761		}
4762		if ( !(eventHandle = elemData.handle) ) {
4763			eventHandle = elemData.handle = function( e ) {
4764				// Discard the second event of a jQuery.event.trigger() and
4765				// when an event is called after a page has unloaded
4766				return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
4767					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
4768					undefined;
4769			};
4770			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
4771			eventHandle.elem = elem;
4772		}
4773
4774		// Handle multiple events separated by a space
4775		types = ( types || "" ).match( core_rnotwhite ) || [""];
4776		t = types.length;
4777		while ( t-- ) {
4778			tmp = rtypenamespace.exec( types[t] ) || [];
4779			type = origType = tmp[1];
4780			namespaces = ( tmp[2] || "" ).split( "." ).sort();
4781
4782			// There *must* be a type, no attaching namespace-only handlers
4783			if ( !type ) {
4784				continue;
4785			}
4786
4787			// If event changes its type, use the special event handlers for the changed type
4788			special = jQuery.event.special[ type ] || {};
4789
4790			// If selector defined, determine special event api type, otherwise given type
4791			type = ( selector ? special.delegateType : special.bindType ) || type;
4792
4793			// Update special based on newly reset type
4794			special = jQuery.event.special[ type ] || {};
4795
4796			// handleObj is passed to all event handlers
4797			handleObj = jQuery.extend({
4798				type: type,
4799				origType: origType,
4800				data: data,
4801				handler: handler,
4802				guid: handler.guid,
4803				selector: selector,
4804				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4805				namespace: namespaces.join(".")
4806			}, handleObjIn );
4807
4808			// Init the event handler queue if we're the first
4809			if ( !(handlers = events[ type ]) ) {
4810				handlers = events[ type ] = [];
4811				handlers.delegateCount = 0;
4812
4813				// Only use addEventListener/attachEvent if the special events handler returns false
4814				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4815					// Bind the global event handler to the element
4816					if ( elem.addEventListener ) {
4817						elem.addEventListener( type, eventHandle, false );
4818
4819					} else if ( elem.attachEvent ) {
4820						elem.attachEvent( "on" + type, eventHandle );
4821					}
4822				}
4823			}
4824
4825			if ( special.add ) {
4826				special.add.call( elem, handleObj );
4827
4828				if ( !handleObj.handler.guid ) {
4829					handleObj.handler.guid = handler.guid;
4830				}
4831			}
4832
4833			// Add to the element's handler list, delegates in front
4834			if ( selector ) {
4835				handlers.splice( handlers.delegateCount++, 0, handleObj );
4836			} else {
4837				handlers.push( handleObj );
4838			}
4839
4840			// Keep track of which events have ever been used, for event optimization
4841			jQuery.event.global[ type ] = true;
4842		}
4843
4844		// Nullify elem to prevent memory leaks in IE
4845		elem = null;
4846	},
4847
4848	// Detach an event or set of events from an element
4849	remove: function( elem, types, handler, selector, mappedTypes ) {
4850		var j, handleObj, tmp,
4851			origCount, t, events,
4852			special, handlers, type,
4853			namespaces, origType,
4854			elemData = jQuery.hasData( elem ) && jQuery._data( elem );
4855
4856		if ( !elemData || !(events = elemData.events) ) {
4857			return;
4858		}
4859
4860		// Once for each type.namespace in types; type may be omitted
4861		types = ( types || "" ).match( core_rnotwhite ) || [""];
4862		t = types.length;
4863		while ( t-- ) {
4864			tmp = rtypenamespace.exec( types[t] ) || [];
4865			type = origType = tmp[1];
4866			namespaces = ( tmp[2] || "" ).split( "." ).sort();
4867
4868			// Unbind all events (on this namespace, if provided) for the element
4869			if ( !type ) {
4870				for ( type in events ) {
4871					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4872				}
4873				continue;
4874			}
4875
4876			special = jQuery.event.special[ type ] || {};
4877			type = ( selector ? special.delegateType : special.bindType ) || type;
4878			handlers = events[ type ] || [];
4879			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
4880
4881			// Remove matching events
4882			origCount = j = handlers.length;
4883			while ( j-- ) {
4884				handleObj = handlers[ j ];
4885
4886				if ( ( mappedTypes || origType === handleObj.origType ) &&
4887					( !handler || handler.guid === handleObj.guid ) &&
4888					( !tmp || tmp.test( handleObj.namespace ) ) &&
4889					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
4890					handlers.splice( j, 1 );
4891
4892					if ( handleObj.selector ) {
4893						handlers.delegateCount--;
4894					}
4895					if ( special.remove ) {
4896						special.remove.call( elem, handleObj );
4897					}
4898				}
4899			}
4900
4901			// Remove generic event handler if we removed something and no more handlers exist
4902			// (avoids potential for endless recursion during removal of special event handlers)
4903			if ( origCount && !handlers.length ) {
4904				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
4905					jQuery.removeEvent( elem, type, elemData.handle );
4906				}
4907
4908				delete events[ type ];
4909			}
4910		}
4911
4912		// Remove the expando if it's no longer used
4913		if ( jQuery.isEmptyObject( events ) ) {
4914			delete elemData.handle;
4915
4916			// removeData also checks for emptiness and clears the expando if empty
4917			// so use it instead of delete
4918			jQuery._removeData( elem, "events" );
4919		}
4920	},
4921
4922	trigger: function( event, data, elem, onlyHandlers ) {
4923		var handle, ontype, cur,
4924			bubbleType, special, tmp, i,
4925			eventPath = [ elem || document ],
4926			type = core_hasOwn.call( event, "type" ) ? event.type : event,
4927			namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
4928
4929		cur = tmp = elem = elem || document;
4930
4931		// Don't do events on text and comment nodes
4932		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
4933			return;
4934		}
4935
4936		// focus/blur morphs to focusin/out; ensure we're not firing them right now
4937		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
4938			return;
4939		}
4940
4941		if ( type.indexOf(".") >= 0 ) {
4942			// Namespaced trigger; create a regexp to match event type in handle()
4943			namespaces = type.split(".");
4944			type = namespaces.shift();
4945			namespaces.sort();
4946		}
4947		ontype = type.indexOf(":") < 0 && "on" + type;
4948
4949		// Caller can pass in a jQuery.Event object, Object, or just an event type string
4950		event = event[ jQuery.expando ] ?
4951			event :
4952			new jQuery.Event( type, typeof event === "object" && event );
4953
4954		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
4955		event.isTrigger = onlyHandlers ? 2 : 3;
4956		event.namespace = namespaces.join(".");
4957		event.namespace_re = event.namespace ?
4958			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
4959			null;
4960
4961		// Clean up the event in case it is being reused
4962		event.result = undefined;
4963		if ( !event.target ) {
4964			event.target = elem;
4965		}
4966
4967		// Clone any incoming data and prepend the event, creating the handler arg list
4968		data = data == null ?
4969			[ event ] :
4970			jQuery.makeArray( data, [ event ] );
4971
4972		// Allow special events to draw outside the lines
4973		special = jQuery.event.special[ type ] || {};
4974		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
4975			return;
4976		}
4977
4978		// Determine event propagation path in advance, per W3C events spec (#9951)
4979		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
4980		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
4981
4982			bubbleType = special.delegateType || type;
4983			if ( !rfocusMorph.test( bubbleType + type ) ) {
4984				cur = cur.parentNode;
4985			}
4986			for ( ; cur; cur = cur.parentNode ) {
4987				eventPath.push( cur );
4988				tmp = cur;
4989			}
4990
4991			// Only add window if we got to document (e.g., not plain obj or detached DOM)
4992			if ( tmp === (elem.ownerDocument || document) ) {
4993				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
4994			}
4995		}
4996
4997		// Fire handlers on the event path
4998		i = 0;
4999		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
5000
5001			event.type = i > 1 ?
5002				bubbleType :
5003				special.bindType || type;
5004
5005			// jQuery handler
5006			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
5007			if ( handle ) {
5008				handle.apply( cur, data );
5009			}
5010
5011			// Native handler
5012			handle = ontype && cur[ ontype ];
5013			if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
5014				event.preventDefault();
5015			}
5016		}
5017		event.type = type;
5018
5019		// If nobody prevented the default action, do it now
5020		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
5021
5022			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
5023				jQuery.acceptData( elem ) ) {
5024
5025				// Call a native DOM method on the target with the same name name as the event.
5026				// Can't use an .isFunction() check here because IE6/7 fails that test.
5027				// Don't do default actions on window, that's where global variables be (#6170)
5028				if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
5029
5030					// Don't re-trigger an onFOO event when we call its FOO() method
5031					tmp = elem[ ontype ];
5032
5033					if ( tmp ) {
5034						elem[ ontype ] = null;
5035					}
5036
5037					// Prevent re-triggering of the same event, since we already bubbled it above
5038					jQuery.event.triggered = type;
5039					try {
5040						elem[ type ]();
5041					} catch ( e ) {
5042						// IE<9 dies on focus/blur to hidden element (#1486,#12518)
5043						// only reproducible on winXP IE8 native, not IE9 in IE8 mode
5044					}
5045					jQuery.event.triggered = undefined;
5046
5047					if ( tmp ) {
5048						elem[ ontype ] = tmp;
5049					}
5050				}
5051			}
5052		}
5053
5054		return event.result;
5055	},
5056
5057	dispatch: function( event ) {
5058
5059		// Make a writable jQuery.Event from the native event object
5060		event = jQuery.event.fix( event );
5061
5062		var i, ret, handleObj, matched, j,
5063			handlerQueue = [],
5064			args = core_
vendor: 7,307 bytes, lines 5064-5309
5064slice.call( arguments ),
5065			handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
5066			special = jQuery.event.special[ event.type ] || {};
5067
5068		// Use the fix-ed jQuery.Event rather than the (read-only) native event
5069		args[0] = event;
5070		event.delegateTarget = this;
5071
5072		// Call the preDispatch hook for the mapped type, and let it bail if desired
5073		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5074			return;
5075		}
5076
5077		// Determine handlers
5078		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5079
5080		// Run delegates first; they may want to stop propagation beneath us
5081		i = 0;
5082		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
5083			event.currentTarget = matched.elem;
5084
5085			j = 0;
5086			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
5087
5088				// Triggered event must either 1) have no namespace, or
5089				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
5090				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
5091
5092					event.handleObj = handleObj;
5093					event.data = handleObj.data;
5094
5095					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
5096							.apply( matched.elem, args );
5097
5098					if ( ret !== undefined ) {
5099						if ( (event.result = ret) === false ) {
5100							event.preventDefault();
5101							event.stopPropagation();
5102						}
5103					}
5104				}
5105			}
5106		}
5107
5108		// Call the postDispatch hook for the mapped type
5109		if ( special.postDispatch ) {
5110			special.postDispatch.call( this, event );
5111		}
5112
5113		return event.result;
5114	},
5115
5116	handlers: function( event, handlers ) {
5117		var sel, handleObj, matches, i,
5118			handlerQueue = [],
5119			delegateCount = handlers.delegateCount,
5120			cur = event.target;
5121
5122		// Find delegate handlers
5123		// Black-hole SVG <use> instance trees (#13180)
5124		// Avoid non-left-click bubbling in Firefox (#3861)
5125		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
5126
5127			/* jshint eqeqeq: false */
5128			for ( ; cur != this; cur = cur.parentNode || this ) {
5129				/* jshint eqeqeq: true */
5130
5131				// Don't check non-elements (#13208)
5132				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
5133				if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
5134					matches = [];
5135					for ( i = 0; i < delegateCount; i++ ) {
5136						handleObj = handlers[ i ];
5137
5138						// Don't conflict with Object.prototype properties (#13203)
5139						sel = handleObj.selector + " ";
5140
5141						if ( matches[ sel ] === undefined ) {
5142							matches[ sel ] = handleObj.needsContext ?
5143								jQuery( sel, this ).index( cur ) >= 0 :
5144								jQuery.find( sel, this, null, [ cur ] ).length;
5145						}
5146						if ( matches[ sel ] ) {
5147							matches.push( handleObj );
5148						}
5149					}
5150					if ( matches.length ) {
5151						handlerQueue.push({ elem: cur, handlers: matches });
5152					}
5153				}
5154			}
5155		}
5156
5157		// Add the remaining (directly-bound) handlers
5158		if ( delegateCount < handlers.length ) {
5159			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
5160		}
5161
5162		return handlerQueue;
5163	},
5164
5165	fix: function( event ) {
5166		if ( event[ jQuery.expando ] ) {
5167			return event;
5168		}
5169
5170		// Create a writable copy of the event object and normalize some properties
5171		var i, prop, copy,
5172			type = event.type,
5173			originalEvent = event,
5174			fixHook = this.fixHooks[ type ];
5175
5176		if ( !fixHook ) {
5177			this.fixHooks[ type ] = fixHook =
5178				rmouseEvent.test( type ) ? this.mouseHooks :
5179				rkeyEvent.test( type ) ? this.keyHooks :
5180				{};
5181		}
5182		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
5183
5184		event = new jQuery.Event( originalEvent );
5185
5186		i = copy.length;
5187		while ( i-- ) {
5188			prop = copy[ i ];
5189			event[ prop ] = originalEvent[ prop ];
5190		}
5191
5192		// Support: IE<9
5193		// Fix target property (#1925)
5194		if ( !event.target ) {
5195			event.target = originalEvent.srcElement || document;
5196		}
5197
5198		// Support: Chrome 23+, Safari?
5199		// Target should not be a text node (#504, #13143)
5200		if ( event.target.nodeType === 3 ) {
5201			event.target = event.target.parentNode;
5202		}
5203
5204		// Support: IE<9
5205		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
5206		event.metaKey = !!event.metaKey;
5207
5208		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
5209	},
5210
5211	// Includes some event props shared by KeyEvent and MouseEvent
5212	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
5213
5214	fixHooks: {},
5215
5216	keyHooks: {
5217		props: "char charCode key keyCode".split(" "),
5218		filter: function( event, original ) {
5219
5220			// Add which for key events
5221			if ( event.which == null ) {
5222				event.which = original.charCode != null ? original.charCode : original.keyCode;
5223			}
5224
5225			return event;
5226		}
5227	},
5228
5229	mouseHooks: {
5230		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
5231		filter: function( event, original ) {
5232			var body, eventDoc, doc,
5233				button = original.button,
5234				fromElement = original.fromElement;
5235
5236			// Calculate pageX/Y if missing and clientX/Y available
5237			if ( event.pageX == null && original.clientX != null ) {
5238				eventDoc = event.target.ownerDocument || document;
5239				doc = eventDoc.documentElement;
5240				body = eventDoc.body;
5241
5242				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
5243				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
5244			}
5245
5246			// Add relatedTarget, if necessary
5247			if ( !event.relatedTarget && fromElement ) {
5248				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
5249			}
5250
5251			// Add which for click: 1 === left; 2 === middle; 3 === right
5252			// Note: button is not normalized, so don't use it
5253			if ( !event.which && button !== undefined ) {
5254				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
5255			}
5256
5257			return event;
5258		}
5259	},
5260
5261	special: {
5262		load: {
5263			// Prevent triggered image.load events from bubbling to window.load
5264			noBubble: true
5265		},
5266		focus: {
5267			// Fire native event if possible so blur/focus sequence is correct
5268			trigger: function() {
5269				if ( this !== safeActiveElement() && this.focus ) {
5270					try {
5271						this.focus();
5272						return false;
5273					} catch ( e ) {
5274						// Support: IE<9
5275						// If we error on focus to hidden element (#1486, #12518),
5276						// let .trigger() run the handlers
5277					}
5278				}
5279			},
5280			delegateType: "focusin"
5281		},
5282		blur: {
5283			trigger: function() {
5284				if ( this === safeActiveElement() && this.blur ) {
5285					this.blur();
5286					return false;
5287				}
5288			},
5289			delegateType: "focusout"
5290		},
5291		click: {
5292			// For checkbox, fire native event so checked state will be right
5293			trigger: function() {
5294				if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
5295					this.click();
5296					return false;
5297				}
5298			},
5299
5300			// For cross-browser consistency, don't fire native .click() on links
5301			_default: function( event ) {
5302				return jQuery.nodeName( event.target, "a" );
5303			}
5304		},
5305
5306		beforeunload: {
5307			postDispatch: function( event ) {
5308
5309				// 
vendor: 4,409 bytes, lines 5309-5476
5309Even when returnValue equals to undefined Firefox will still show alert
5310				if ( event.result !== undefined ) {
5311					event.originalEvent.returnValue = event.result;
5312				}
5313			}
5314		}
5315	},
5316
5317	simulate: function( type, elem, event, bubble ) {
5318		// Piggyback on a donor event to simulate a different one.
5319		// Fake originalEvent to avoid donor's stopPropagation, but if the
5320		// simulated event prevents default then we do the same on the donor.
5321		var e = jQuery.extend(
5322			new jQuery.Event(),
5323			event,
5324			{
5325				type: type,
5326				isSimulated: true,
5327				originalEvent: {}
5328			}
5329		);
5330		if ( bubble ) {
5331			jQuery.event.trigger( e, null, elem );
5332		} else {
5333			jQuery.event.dispatch.call( elem, e );
5334		}
5335		if ( e.isDefaultPrevented() ) {
5336			event.preventDefault();
5337		}
5338	}
5339};
5340
5341jQuery.removeEvent = document.removeEventListener ?
5342	function( elem, type, handle ) {
5343		if ( elem.removeEventListener ) {
5344			elem.removeEventListener( type, handle, false );
5345		}
5346	} :
5347	function( elem, type, handle ) {
5348		var name = "on" + type;
5349
5350		if ( elem.detachEvent ) {
5351
5352			// #8545, #7054, preventing memory leaks for custom events in IE6-8
5353			// detachEvent needed property on element, by name of that event, to properly expose it to GC
5354			if ( typeof elem[ name ] === core_strundefined ) {
5355				elem[ name ] = null;
5356			}
5357
5358			elem.detachEvent( name, handle );
5359		}
5360	};
5361
5362jQuery.Event = function( src, props ) {
5363	// Allow instantiation without the 'new' keyword
5364	if ( !(this instanceof jQuery.Event) ) {
5365		return new jQuery.Event( src, props );
5366	}
5367
5368	// Event object
5369	if ( src && src.type ) {
5370		this.originalEvent = src;
5371		this.type = src.type;
5372
5373		// Events bubbling up the document may have been marked as prevented
5374		// by a handler lower down the tree; reflect the correct value.
5375		this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
5376			src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
5377
5378	// Event type
5379	} else {
5380		this.type = src;
5381	}
5382
5383	// Put explicitly provided properties onto the event object
5384	if ( props ) {
5385		jQuery.extend( this, props );
5386	}
5387
5388	// Create a timestamp if incoming event doesn't have one
5389	this.timeStamp = src && src.timeStamp || jQuery.now();
5390
5391	// Mark it as fixed
5392	this[ jQuery.expando ] = true;
5393};
5394
5395// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5396// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5397jQuery.Event.prototype = {
5398	isDefaultPrevented: returnFalse,
5399	isPropagationStopped: returnFalse,
5400	isImmediatePropagationStopped: returnFalse,
5401
5402	preventDefault: function() {
5403		var e = this.originalEvent;
5404
5405		this.isDefaultPrevented = returnTrue;
5406		if ( !e ) {
5407			return;
5408		}
5409
5410		// If preventDefault exists, run it on the original event
5411		if ( e.preventDefault ) {
5412			e.preventDefault();
5413
5414		// Support: IE
5415		// Otherwise set the returnValue property of the original event to false
5416		} else {
5417			e.returnValue = false;
5418		}
5419	},
5420	stopPropagation: function() {
5421		var e = this.originalEvent;
5422
5423		this.isPropagationStopped = returnTrue;
5424		if ( !e ) {
5425			return;
5426		}
5427		// If stopPropagation exists, run it on the original event
5428		if ( e.stopPropagation ) {
5429			e.stopPropagation();
5430		}
5431
5432		// Support: IE
5433		// Set the cancelBubble property of the original event to true
5434		e.cancelBubble = true;
5435	},
5436	stopImmediatePropagation: function() {
5437		this.isImmediatePropagationStopped = returnTrue;
5438		this.stopPropagation();
5439	}
5440};
5441
5442// Create mouseenter/leave events using mouseover/out and event-time checks
5443jQuery.each({
5444	mouseenter: "mouseover",
5445	mouseleave: "mouseout"
5446}, function( orig, fix ) {
5447	jQuery.event.special[ orig ] = {
5448		delegateType: fix,
5449		bindType: fix,
5450
5451		handle: function( event ) {
5452			var ret,
5453				target = this,
5454				related = event.relatedTarget,
5455				handleObj = event.handleObj;
5456
5457			// For mousenter/leave call the handler if related is outside the target.
5458			// NB: No relatedTarget if the mouse left/entered the browser window
5459			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
5460				event.type = handleObj.origType;
5461				ret = handleObj.handler.apply( this, arguments );
5462				event.type = fix;
5463			}
5464			return ret;
5465		}
5466	};
5467});
5468
5469// IE submit delegation
5470if ( !jQuery.support.submitBubbles ) {
5471
5472	jQuery.event.special.submit = {
5473		setup: function() {
5474			// Only need this for delegated form submit events
5475			if ( jQuery.nodeName( this, "form" ) ) {
5476				return false;
vendor: 6,944 bytes, lines 5477-5720
5477			}
5478
5479			// Lazy-add a submit handler when a descendant form may potentially be submitted
5480			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
5481				// Node name check avoids a VML-related crash in IE (#9807)
5482				var elem = e.target,
5483					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
5484				if ( form && !jQuery._data( form, "submitBubbles" ) ) {
5485					jQuery.event.add( form, "submit._submit", function( event ) {
5486						event._submit_bubble = true;
5487					});
5488					jQuery._data( form, "submitBubbles", true );
5489				}
5490			});
5491			// return undefined since we don't need an event listener
5492		},
5493
5494		postDispatch: function( event ) {
5495			// If form was submitted by the user, bubble the event up the tree
5496			if ( event._submit_bubble ) {
5497				delete event._submit_bubble;
5498				if ( this.parentNode && !event.isTrigger ) {
5499					jQuery.event.simulate( "submit", this.parentNode, event, true );
5500				}
5501			}
5502		},
5503
5504		teardown: function() {
5505			// Only need this for delegated form submit events
5506			if ( jQuery.nodeName( this, "form" ) ) {
5507				return false;
5508			}
5509
5510			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
5511			jQuery.event.remove( this, "._submit" );
5512		}
5513	};
5514}
5515
5516// IE change delegation and checkbox/radio fix
5517if ( !jQuery.support.changeBubbles ) {
5518
5519	jQuery.event.special.change = {
5520
5521		setup: function() {
5522
5523			if ( rformElems.test( this.nodeName ) ) {
5524				// IE doesn't fire change on a check/radio until blur; trigger it on click
5525				// after a propertychange. Eat the blur-change in special.change.handle.
5526				// This still fires onchange a second time for check/radio after blur.
5527				if ( this.type === "checkbox" || this.type === "radio" ) {
5528					jQuery.event.add( this, "propertychange._change", function( event ) {
5529						if ( event.originalEvent.propertyName === "checked" ) {
5530							this._just_changed = true;
5531						}
5532					});
5533					jQuery.event.add( this, "click._change", function( event ) {
5534						if ( this._just_changed && !event.isTrigger ) {
5535							this._just_changed = false;
5536						}
5537						// Allow triggered, simulated change events (#11500)
5538						jQuery.event.simulate( "change", this, event, true );
5539					});
5540				}
5541				return false;
5542			}
5543			// Delegated event; lazy-add a change handler on descendant inputs
5544			jQuery.event.add( this, "beforeactivate._change", function( e ) {
5545				var elem = e.target;
5546
5547				if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
5548					jQuery.event.add( elem, "change._change", function( event ) {
5549						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
5550							jQuery.event.simulate( "change", this.parentNode, event, true );
5551						}
5552					});
5553					jQuery._data( elem, "changeBubbles", true );
5554				}
5555			});
5556		},
5557
5558		handle: function( event ) {
5559			var elem = event.target;
5560
5561			// Swallow native change events from checkbox/radio, we already triggered them above
5562			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
5563				return event.handleObj.handler.apply( this, arguments );
5564			}
5565		},
5566
5567		teardown: function() {
5568			jQuery.event.remove( this, "._change" );
5569
5570			return !rformElems.test( this.nodeName );
5571		}
5572	};
5573}
5574
5575// Create "bubbling" focus and blur events
5576if ( !jQuery.support.focusinBubbles ) {
5577	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
5578
5579		// Attach a single capturing handler while someone wants focusin/focusout
5580		var attaches = 0,
5581			handler = function( event ) {
5582				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
5583			};
5584
5585		jQuery.event.special[ fix ] = {
5586			setup: function() {
5587				if ( attaches++ === 0 ) {
5588					document.addEventListener( orig, handler, true );
5589				}
5590			},
5591			teardown: function() {
5592				if ( --attaches === 0 ) {
5593					document.removeEventListener( orig, handler, true );
5594				}
5595			}
5596		};
5597	});
5598}
5599
5600jQuery.fn.extend({
5601
5602	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
5603		var type, origFn;
5604
5605		// Types can be a map of types/handlers
5606		if ( typeof types === "object" ) {
5607			// ( types-Object, selector, data )
5608			if ( typeof selector !== "string" ) {
5609				// ( types-Object, data )
5610				data = data || selector;
5611				selector = undefined;
5612			}
5613			for ( type in types ) {
5614				this.on( type, selector, data, types[ type ], one );
5615			}
5616			return this;
5617		}
5618
5619		if ( data == null && fn == null ) {
5620			// ( types, fn )
5621			fn = selector;
5622			data = selector = undefined;
5623		} else if ( fn == null ) {
5624			if ( typeof selector === "string" ) {
5625				// ( types, selector, fn )
5626				fn = data;
5627				data = undefined;
5628			} else {
5629				// ( types, data, fn )
5630				fn = data;
5631				data = selector;
5632				selector = undefined;
5633			}
5634		}
5635		if ( fn === false ) {
5636			fn = returnFalse;
5637		} else if ( !fn ) {
5638			return this;
5639		}
5640
5641		if ( one === 1 ) {
5642			origFn = fn;
5643			fn = function( event ) {
5644				// Can use an empty set, since event contains the info
5645				jQuery().off( event );
5646				return origFn.apply( this, arguments );
5647			};
5648			// Use same guid so caller can remove using origFn
5649			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
5650		}
5651		return this.each( function() {
5652			jQuery.event.add( this, types, fn, data, selector );
5653		});
5654	},
5655	one: function( types, selector, data, fn ) {
5656		return this.on( types, selector, data, fn, 1 );
5657	},
5658	off: function( types, selector, fn ) {
5659		var handleObj, type;
5660		if ( types && types.preventDefault && types.handleObj ) {
5661			// ( event )  dispatched jQuery.Event
5662			handleObj = types.handleObj;
5663			jQuery( types.delegateTarget ).off(
5664				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
5665				handleObj.selector,
5666				handleObj.handler
5667			);
5668			return this;
5669		}
5670		if ( typeof types === "object" ) {
5671			// ( types-object [, selector] )
5672			for ( type in types ) {
5673				this.off( type, selector, types[ type ] );
5674			}
5675			return this;
5676		}
5677		if ( selector === false || typeof selector === "function" ) {
5678			// ( types [, fn] )
5679			fn = selector;
5680			selector = undefined;
5681		}
5682		if ( fn === false ) {
5683			fn = returnFalse;
5684		}
5685		return this.each(function() {
5686			jQuery.event.remove( this, types, fn, selector );
5687		});
5688	},
5689
5690	trigger: function( type, data ) {
5691		return this.each(function() {
5692			jQuery.event.trigger( type, data, this );
5693		});
5694	},
5695	triggerHandler: function( type, data ) {
5696		var elem = this[0];
5697		if ( elem ) {
5698			return jQuery.event.trigger( type, data, elem, true );
5699		}
5700	}
5701});
5702var isSimple = /^.[^:#\[\.,]*$/,
5703	rparentsprev = /^(?:parents|prev(?:Until|All))/,
5704	rneedsContext = jQuery.expr.match.needsContext,
5705	// methods guaranteed to produce a unique set when starting from a unique set
5706	guaranteedUnique = {
5707		children: true,
5708		contents: true,
5709		next: true,
5710		prev: true
5711	};
5712
5713jQuery.fn.extend({
5714	find: function( selector ) {
5715		var i,
5716			ret = [],
5717			self = this,
5718			len = self.length;
5719
5720		if ( typeof selector !== "string" ) {
vendor: 37,017 bytes, lines 5721-7082
5721			return this.pushStack( jQuery( selector ).filter(function() {
5722				for ( i = 0; i < len; i++ ) {
5723					if ( jQuery.contains( self[ i ], this ) ) {
5724						return true;
5725					}
5726				}
5727			}) );
5728		}
5729
5730		for ( i = 0; i < len; i++ ) {
5731			jQuery.find( selector, self[ i ], ret );
5732		}
5733
5734		// Needed because $( selector, context ) becomes $( context ).find( selector )
5735		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
5736		ret.selector = this.selector ? this.selector + " " + selector : selector;
5737		return ret;
5738	},
5739
5740	has: function( target ) {
5741		var i,
5742			targets = jQuery( target, this ),
5743			len = targets.length;
5744
5745		return this.filter(function() {
5746			for ( i = 0; i < len; i++ ) {
5747				if ( jQuery.contains( this, targets[i] ) ) {
5748					return true;
5749				}
5750			}
5751		});
5752	},
5753
5754	not: function( selector ) {
5755		return this.pushStack( winnow(this, selector || [], true) );
5756	},
5757
5758	filter: function( selector ) {
5759		return this.pushStack( winnow(this, selector || [], false) );
5760	},
5761
5762	is: function( selector ) {
5763		return !!winnow(
5764			this,
5765
5766			// If this is a positional/relative selector, check membership in the returned set
5767			// so $("p:first").is("p:last") won't return true for a doc with two "p".
5768			typeof selector === "string" && rneedsContext.test( selector ) ?
5769				jQuery( selector ) :
5770				selector || [],
5771			false
5772		).length;
5773	},
5774
5775	closest: function( selectors, context ) {
5776		var cur,
5777			i = 0,
5778			l = this.length,
5779			ret = [],
5780			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
5781				jQuery( selectors, context || this.context ) :
5782				0;
5783
5784		for ( ; i < l; i++ ) {
5785			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
5786				// Always skip document fragments
5787				if ( cur.nodeType < 11 && (pos ?
5788					pos.index(cur) > -1 :
5789
5790					// Don't pass non-elements to Sizzle
5791					cur.nodeType === 1 &&
5792						jQuery.find.matchesSelector(cur, selectors)) ) {
5793
5794					cur = ret.push( cur );
5795					break;
5796				}
5797			}
5798		}
5799
5800		return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
5801	},
5802
5803	// Determine the position of an element within
5804	// the matched set of elements
5805	index: function( elem ) {
5806
5807		// No argument, return index in parent
5808		if ( !elem ) {
5809			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
5810		}
5811
5812		// index in selector
5813		if ( typeof elem === "string" ) {
5814			return jQuery.inArray( this[0], jQuery( elem ) );
5815		}
5816
5817		// Locate the position of the desired element
5818		return jQuery.inArray(
5819			// If it receives a jQuery object, the first element is used
5820			elem.jquery ? elem[0] : elem, this );
5821	},
5822
5823	add: function( selector, context ) {
5824		var set = typeof selector === "string" ?
5825				jQuery( selector, context ) :
5826				jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5827			all = jQuery.merge( this.get(), set );
5828
5829		return this.pushStack( jQuery.unique(all) );
5830	},
5831
5832	addBack: function( selector ) {
5833		return this.add( selector == null ?
5834			this.prevObject : this.prevObject.filter(selector)
5835		);
5836	}
5837});
5838
5839function sibling( cur, dir ) {
5840	do {
5841		cur = cur[ dir ];
5842	} while ( cur && cur.nodeType !== 1 );
5843
5844	return cur;
5845}
5846
5847jQuery.each({
5848	parent: function( elem ) {
5849		var parent = elem.parentNode;
5850		return parent && parent.nodeType !== 11 ? parent : null;
5851	},
5852	parents: function( elem ) {
5853		return jQuery.dir( elem, "parentNode" );
5854	},
5855	parentsUntil: function( elem, i, until ) {
5856		return jQuery.dir( elem, "parentNode", until );
5857	},
5858	next: function( elem ) {
5859		return sibling( elem, "nextSibling" );
5860	},
5861	prev: function( elem ) {
5862		return sibling( elem, "previousSibling" );
5863	},
5864	nextAll: function( elem ) {
5865		return jQuery.dir( elem, "nextSibling" );
5866	},
5867	prevAll: function( elem ) {
5868		return jQuery.dir( elem, "previousSibling" );
5869	},
5870	nextUntil: function( elem, i, until ) {
5871		return jQuery.dir( elem, "nextSibling", until );
5872	},
5873	prevUntil: function( elem, i, until ) {
5874		return jQuery.dir( elem, "previousSibling", until );
5875	},
5876	siblings: function( elem ) {
5877		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
5878	},
5879	children: function( elem ) {
5880		return jQuery.sibling( elem.firstChild );
5881	},
5882	contents: function( elem ) {
5883		return jQuery.nodeName( elem, "iframe" ) ?
5884			elem.contentDocument || elem.contentWindow.document :
5885			jQuery.merge( [], elem.childNodes );
5886	}
5887}, function( name, fn ) {
5888	jQuery.fn[ name ] = function( until, selector ) {
5889		var ret = jQuery.map( this, fn, until );
5890
5891		if ( name.slice( -5 ) !== "Until" ) {
5892			selector = until;
5893		}
5894
5895		if ( selector && typeof selector === "string" ) {
5896			ret = jQuery.filter( selector, ret );
5897		}
5898
5899		if ( this.length > 1 ) {
5900			// Remove duplicates
5901			if ( !guaranteedUnique[ name ] ) {
5902				ret = jQuery.unique( ret );
5903			}
5904
5905			// Reverse order for parents* and prev-derivatives
5906			if ( rparentsprev.test( name ) ) {
5907				ret = ret.reverse();
5908			}
5909		}
5910
5911		return this.pushStack( ret );
5912	};
5913});
5914
5915jQuery.extend({
5916	filter: function( expr, elems, not ) {
5917		var elem = elems[ 0 ];
5918
5919		if ( not ) {
5920			expr = ":not(" + expr + ")";
5921		}
5922
5923		return elems.length === 1 && elem.nodeType === 1 ?
5924			jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
5925			jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
5926				return elem.nodeType === 1;
5927			}));
5928	},
5929
5930	dir: function( elem, dir, until ) {
5931		var matched = [],
5932			cur = elem[ dir ];
5933
5934		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5935			if ( cur.nodeType === 1 ) {
5936				matched.push( cur );
5937			}
5938			cur = cur[dir];
5939		}
5940		return matched;
5941	},
5942
5943	sibling: function( n, elem ) {
5944		var r = [];
5945
5946		for ( ; n; n = n.nextSibling ) {
5947			if ( n.nodeType === 1 && n !== elem ) {
5948				r.push( n );
5949			}
5950		}
5951
5952		return r;
5953	}
5954});
5955
5956// Implement the identical functionality for filter and not
5957function winnow( elements, qualifier, not ) {
5958	if ( jQuery.isFunction( qualifier ) ) {
5959		return jQuery.grep( elements, function( elem, i ) {
5960			/* jshint -W018 */
5961			return !!qualifier.call( elem, i, elem ) !== not;
5962		});
5963
5964	}
5965
5966	if ( qualifier.nodeType ) {
5967		return jQuery.grep( elements, function( elem ) {
5968			return ( elem === qualifier ) !== not;
5969		});
5970
5971	}
5972
5973	if ( typeof qualifier === "string" ) {
5974		if ( isSimple.test( qualifier ) ) {
5975			return jQuery.filter( qualifier, elements, not );
5976		}
5977
5978		qualifier = jQuery.filter( qualifier, elements );
5979	}
5980
5981	return jQuery.grep( elements, function( elem ) {
5982		return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
5983	});
5984}
5985function createSafeFragment( document ) {
5986	var list = nodeNames.split( "|" ),
5987		safeFrag = document.createDocumentFragment();
5988
5989	if ( safeFrag.createElement ) {
5990		while ( list.length ) {
5991			safeFrag.createElement(
5992				list.pop()
5993			);
5994		}
5995	}
5996	return safeFrag;
5997}
5998
5999var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
6000		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
6001	rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
6002	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
6003	rleadingWhitespace = /^\s+/,
6004	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
6005	rtagName = /<([\w:]+)/,
6006	rtbody = /<tbody/i,
6007	rhtml = /<|&#?\w+;/,
6008	rnoInnerhtml = /<(?:script|style|link)/i,
6009	manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
6010	// checked="checked" or checked
6011	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
6012	rscriptType = /^$|\/(?:java|ecma)script/i,
6013	rscriptTypeMasked = /^true\/(.*)/,
6014	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
6015
6016	// We have to close these tags to support XHTML (#13200)
6017	wrapMap = {
6018		option: [ 1, "<select multiple='multiple'>", "</select>" ],
6019		legend: [ 1, "<fieldset>", "</fieldset>" ],
6020		area: [ 1, "<map>", "</map>" ],
6021		param: [ 1, "<object>", "</object>" ],
6022		thead: [ 1, "<table>", "</table>" ],
6023		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
6024		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
6025		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
6026
6027		// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
6028		// unless wrapped in a div with non-breaking characters in front of it.
6029		_default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
6030	},
6031	safeFragment = createSafeFragment( document ),
6032	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
6033
6034wrapMap.optgroup = wrapMap.option;
6035wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
6036wrapMap.th = wrapMap.td;
6037
6038jQuery.fn.extend({
6039	text: function( value ) {
6040		return jQuery.access( this, function( value ) {
6041			return value === undefined ?
6042				jQuery.text( this ) :
6043				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
6044		}, null, value, arguments.length );
6045	},
6046
6047	append: function() {
6048		return this.domManip( arguments, function( elem ) {
6049			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6050				var target = manipulationTarget( this, elem );
6051				target.appendChild( elem );
6052			}
6053		});
6054	},
6055
6056	prepend: function() {
6057		return this.domManip( arguments, function( elem ) {
6058			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6059				var target = manipulationTarget( this, elem );
6060				target.insertBefore( elem, target.firstChild );
6061			}
6062		});
6063	},
6064
6065	before: function() {
6066		return this.domManip( arguments, function( elem ) {
6067			if ( this.parentNode ) {
6068				this.parentNode.insertBefore( elem, this );
6069			}
6070		});
6071	},
6072
6073	after: function() {
6074		return this.domManip( arguments, function( elem ) {
6075			if ( this.parentNode ) {
6076				this.parentNode.insertBefore( elem, this.nextSibling );
6077			}
6078		});
6079	},
6080
6081	// keepData is for internal use only--do not document
6082	remove: function( selector, keepData ) {
6083		var elem,
6084			elems = selector ? jQuery.filter( selector, this ) : this,
6085			i = 0;
6086
6087		for ( ; (elem = elems[i]) != null; i++ ) {
6088
6089			if ( !keepData && elem.nodeType === 1 ) {
6090				jQuery.cleanData( getAll( elem ) );
6091			}
6092
6093			if ( elem.parentNode ) {
6094				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
6095					setGlobalEval( getAll( elem, "script" ) );
6096				}
6097				elem.parentNode.removeChild( elem );
6098			}
6099		}
6100
6101		return this;
6102	},
6103
6104	empty: function() {
6105		var elem,
6106			i = 0;
6107
6108		for ( ; (elem = this[i]) != null; i++ ) {
6109			// Remove element nodes and prevent memory leaks
6110			if ( elem.nodeType === 1 ) {
6111				jQuery.cleanData( getAll( elem, false ) );
6112			}
6113
6114			// Remove any remaining nodes
6115			while ( elem.firstChild ) {
6116				elem.removeChild( elem.firstChild );
6117			}
6118
6119			// If this is a select, ensure that it displays empty (#12336)
6120			// Support: IE<9
6121			if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
6122				elem.options.length = 0;
6123			}
6124		}
6125
6126		return this;
6127	},
6128
6129	clone: function( dataAndEvents, deepDataAndEvents ) {
6130		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6131		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6132
6133		return this.map( function () {
6134			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6135		});
6136	},
6137
6138	html: function( value ) {
6139		return jQuery.access( this, function( value ) {
6140			var elem = this[0] || {},
6141				i = 0,
6142				l = this.length;
6143
6144			if ( value === undefined ) {
6145				return elem.nodeType === 1 ?
6146					elem.innerHTML.replace( rinlinejQuery, "" ) :
6147					undefined;
6148			}
6149
6150			// See if we can take a shortcut and just use innerHTML
6151			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6152				( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&
6153				( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
6154				!wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
6155
6156				value = value.replace( rxhtmlTag, "<$1></$2>" );
6157
6158				try {
6159					for (; i < l; i++ ) {
6160						// Remove element nodes and prevent memory leaks
6161						elem = this[i] || {};
6162						if ( elem.nodeType === 1 ) {
6163							jQuery.cleanData( getAll( elem, false ) );
6164							elem.innerHTML = value;
6165						}
6166					}
6167
6168					elem = 0;
6169
6170				// If using innerHTML throws an exception, use the fallback method
6171				} catch(e) {}
6172			}
6173
6174			if ( elem ) {
6175				this.empty().append( value );
6176			}
6177		}, null, value, arguments.length );
6178	},
6179
6180	replaceWith: function() {
6181		var
6182			// Snapshot the DOM in case .domManip sweeps something relevant into its fragment
6183			args = jQuery.map( this, function( elem ) {
6184				return [ elem.nextSibling, elem.parentNode ];
6185			}),
6186			i = 0;
6187
6188		// Make the changes, replacing each context element with the new content
6189		this.domManip( arguments, function( elem ) {
6190			var next = args[ i++ ],
6191				parent = args[ i++ ];
6192
6193			if ( parent ) {
6194				// Don't use the snapshot next if it has moved (#13810)
6195				if ( next && next.parentNode !== parent ) {
6196					next = this.nextSibling;
6197				}
6198				jQuery( this ).remove();
6199				parent.insertBefore( elem, next );
6200			}
6201		// Allow new content to include elements from the context set
6202		}, true );
6203
6204		// Force removal if there was no new content (e.g., from empty arguments)
6205		return i ? this : this.remove();
6206	},
6207
6208	detach: function( selector ) {
6209		return this.remove( selector, true );
6210	},
6211
6212	domManip: function( args, callback, allowIntersection ) {
6213
6214		// Flatten any nested arrays
6215		args = core_concat.apply( [], args );
6216
6217		var first, node, hasScripts,
6218			scripts, doc, fragment,
6219			i = 0,
6220			l = this.length,
6221			set = this,
6222			iNoClone = l - 1,
6223			value = args[0],
6224			isFunction = jQuery.isFunction( value );
6225
6226		// We can't cloneNode fragments that contain checked, in WebKit
6227		if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
6228			return this.each(function( index ) {
6229				var self = set.eq( index );
6230				if ( isFunction ) {
6231					args[0] = value.call( this, index, self.html() );
6232				}
6233				self.domManip( args, callback, allowIntersection );
6234			});
6235		}
6236
6237		if ( l ) {
6238			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this );
6239			first = fragment.firstChild;
6240
6241			if ( fragment.childNodes.length === 1 ) {
6242				fragment = first;
6243			}
6244
6245			if ( first ) {
6246				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6247				hasScripts = scripts.length;
6248
6249				// Use the original fragment for the last item instead of the first because it can end up
6250				// being emptied incorrectly in certain situations (#8070).
6251				for ( ; i < l; i++ ) {
6252					node = fragment;
6253
6254					if ( i !== iNoClone ) {
6255						node = jQuery.clone( node, true, true );
6256
6257						// Keep references to cloned scripts for later restoration
6258						if ( hasScripts ) {
6259							jQuery.merge( scripts, getAll( node, "script" ) );
6260						}
6261					}
6262
6263					callback.call( this[i], node, i );
6264				}
6265
6266				if ( hasScripts ) {
6267					doc = scripts[ scripts.length - 1 ].ownerDocument;
6268
6269					// Reenable scripts
6270					jQuery.map( scripts, restoreScript );
6271
6272					// Evaluate executable scripts on first document insertion
6273					for ( i = 0; i < hasScripts; i++ ) {
6274						node = scripts[ i ];
6275						if ( rscriptType.test( node.type || "" ) &&
6276							!jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
6277
6278							if ( node.src ) {
6279								// Hope ajax is available...
6280								jQuery._evalUrl( node.src );
6281							} else {
6282								jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
6283							}
6284						}
6285					}
6286				}
6287
6288				// Fix #11809: Avoid leaking memory
6289				fragment = first = null;
6290			}
6291		}
6292
6293		return this;
6294	}
6295});
6296
6297// Support: IE<8
6298// Manipulating tables requires a tbody
6299function manipulationTarget( elem, content ) {
6300	return jQuery.nodeName( elem, "table" ) &&
6301		jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ?
6302
6303		elem.getElementsByTagName("tbody")[0] ||
6304			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
6305		elem;
6306}
6307
6308// Replace/restore the type attribute of script elements for safe DOM manipulation
6309function disableScript( elem ) {
6310	elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
6311	return elem;
6312}
6313function restoreScript( elem ) {
6314	var match = rscriptTypeMasked.exec( elem.type );
6315	if ( match ) {
6316		elem.type = match[1];
6317	} else {
6318		elem.removeAttribute("type");
6319	}
6320	return elem;
6321}
6322
6323// Mark scripts as having already been evaluated
6324function setGlobalEval( elems, refElements ) {
6325	var elem,
6326		i = 0;
6327	for ( ; (elem = elems[i]) != null; i++ ) {
6328		jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
6329	}
6330}
6331
6332function cloneCopyEvent( src, dest ) {
6333
6334	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6335		return;
6336	}
6337
6338	var type, i, l,
6339		oldData = jQuery._data( src ),
6340		curData = jQuery._data( dest, oldData ),
6341		events = oldData.events;
6342
6343	if ( events ) {
6344		delete curData.handle;
6345		curData.events = {};
6346
6347		for ( type in events ) {
6348			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6349				jQuery.event.add( dest, type, events[ type ][ i ] );
6350			}
6351		}
6352	}
6353
6354	// make the cloned public data object a copy from the original
6355	if ( curData.data ) {
6356		curData.data = jQuery.extend( {}, curData.data );
6357	}
6358}
6359
6360function fixCloneNodeIssues( src, dest ) {
6361	var nodeName, e, data;
6362
6363	// We do not need to do anything for non-Elements
6364	if ( dest.nodeType !== 1 ) {
6365		return;
6366	}
6367
6368	nodeName = dest.nodeName.toLowerCase();
6369
6370	// IE6-8 copies events bound via attachEvent when using cloneNode.
6371	if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
6372		data = jQuery._data( dest );
6373
6374		for ( e in data.events ) {
6375			jQuery.removeEvent( dest, e, data.handle );
6376		}
6377
6378		// Event data gets referenced instead of copied if the expando gets copied too
6379		dest.removeAttribute( jQuery.expando );
6380	}
6381
6382	// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
6383	if ( nodeName === "script" && dest.text !== src.text ) {
6384		disableScript( dest ).text = src.text;
6385		restoreScript( dest );
6386
6387	// IE6-10 improperly clones children of object elements using classid.
6388	// IE10 throws NoModificationAllowedError if parent is null, #12132.
6389	} else if ( nodeName === "object" ) {
6390		if ( dest.parentNode ) {
6391			dest.outerHTML = src.outerHTML;
6392		}
6393
6394		// This path appears unavoidable for IE9. When cloning an object
6395		// element in IE9, the outerHTML strategy above is not sufficient.
6396		// If the src has innerHTML and the destination does not,
6397		// copy the src.innerHTML into the dest.innerHTML. #10324
6398		if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
6399			dest.innerHTML = src.innerHTML;
6400		}
6401
6402	} else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
6403		// IE6-8 fails to persist the checked state of a cloned checkbox
6404		// or radio button. Worse, IE6-7 fail to give the cloned element
6405		// a checked appearance if the defaultChecked value isn't also set
6406
6407		dest.defaultChecked = dest.checked = src.checked;
6408
6409		// IE6-7 get confused and end up setting the value of a cloned
6410		// checkbox/radio button to an empty string instead of "on"
6411		if ( dest.value !== src.value ) {
6412			dest.value = src.value;
6413		}
6414
6415	// IE6-8 fails to return the selected option to the default selected
6416	// state when cloning options
6417	} else if ( nodeName === "option" ) {
6418		dest.defaultSelected = dest.selected = src.defaultSelected;
6419
6420	// IE6-8 fails to set the defaultValue to the correct value when
6421	// cloning other types of input fields
6422	} else if ( nodeName === "input" || nodeName === "textarea" ) {
6423		dest.defaultValue = src.defaultValue;
6424	}
6425}
6426
6427jQuery.each({
6428	appendTo: "append",
6429	prependTo: "prepend",
6430	insertBefore: "before",
6431	insertAfter: "after",
6432	replaceAll: "replaceWith"
6433}, function( name, original ) {
6434	jQuery.fn[ name ] = function( selector ) {
6435		var elems,
6436			i = 0,
6437			ret = [],
6438			insert = jQuery( selector ),
6439			last = insert.length - 1;
6440
6441		for ( ; i <= last; i++ ) {
6442			elems = i === last ? this : this.clone(true);
6443			jQuery( insert[i] )[ original ]( elems );
6444
6445			// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6446			core_push.apply( ret, elems.get() );
6447		}
6448
6449		return this.pushStack( ret );
6450	};
6451});
6452
6453function getAll( context, tag ) {
6454	var elems, elem,
6455		i = 0,
6456		found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
6457			typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
6458			undefined;
6459
6460	if ( !found ) {
6461		for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
6462			if ( !tag || jQuery.nodeName( elem, tag ) ) {
6463				found.push( elem );
6464			} else {
6465				jQuery.merge( found, getAll( elem, tag ) );
6466			}
6467		}
6468	}
6469
6470	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
6471		jQuery.merge( [ context ], found ) :
6472		found;
6473}
6474
6475// Used in buildFragment, fixes the defaultChecked property
6476function fixDefaultChecked( elem ) {
6477	if ( manipulation_rcheckableType.test( elem.type ) ) {
6478		elem.defaultChecked = elem.checked;
6479	}
6480}
6481
6482jQuery.extend({
6483	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6484		var destElements, node, clone, i, srcElements,
6485			inPage = jQuery.contains( elem.ownerDocument, elem );
6486
6487		if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6488			clone = elem.cloneNode( true );
6489
6490		// IE<=8 does not properly clone detached, unknown element nodes
6491		} else {
6492			fragmentDiv.innerHTML = elem.outerHTML;
6493			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6494		}
6495
6496		if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6497				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6498
6499			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
6500			destElements = getAll( clone );
6501			srcElements = getAll( elem );
6502
6503			// Fix all IE cloning issues
6504			for ( i = 0; (node = srcElements[i]) != null; ++i ) {
6505				// Ensure that the destination node is not null; Fixes #9587
6506				if ( destElements[i] ) {
6507					fixCloneNodeIssues( node, destElements[i] );
6508				}
6509			}
6510		}
6511
6512		// Copy the events from the original to the clone
6513		if ( dataAndEvents ) {
6514			if ( deepDataAndEvents ) {
6515				srcElements = srcElements || getAll( elem );
6516				destElements = destElements || getAll( clone );
6517
6518				for ( i = 0; (node = srcElements[i]) != null; i++ ) {
6519					cloneCopyEvent( node, destElements[i] );
6520				}
6521			} else {
6522				cloneCopyEvent( elem, clone );
6523			}
6524		}
6525
6526		// Preserve script evaluation history
6527		destElements = getAll( clone, "script" );
6528		if ( destElements.length > 0 ) {
6529			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6530		}
6531
6532		destElements = srcElements = node = null;
6533
6534		// Return the cloned set
6535		return clone;
6536	},
6537
6538	buildFragment: function( elems, context, scripts, selection ) {
6539		var j, elem, contains,
6540			tmp, tag, tbody, wrap,
6541			l = elems.length,
6542
6543			// Ensure a safe fragment
6544			safe = createSafeFragment( context ),
6545
6546			nodes = [],
6547			i = 0;
6548
6549		for ( ; i < l; i++ ) {
6550			elem = elems[ i ];
6551
6552			if ( elem || elem === 0 ) {
6553
6554				// Add nodes directly
6555				if ( jQuery.type( elem ) === "object" ) {
6556					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
6557
6558				// Convert non-html into a text node
6559				} else if ( !rhtml.test( elem ) ) {
6560					nodes.push( context.createTextNode( elem ) );
6561
6562				// Convert html into DOM nodes
6563				} else {
6564					tmp = tmp || safe.appendChild( context.createElement("div") );
6565
6566					// Deserialize a standard representation
6567					tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
6568					wrap = wrapMap[ tag ] || wrapMap._default;
6569
6570					tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
6571
6572					// Descend through wrappers to the right content
6573					j = wrap[0];
6574					while ( j-- ) {
6575						tmp = tmp.lastChild;
6576					}
6577
6578					// Manually add leading whitespace removed by IE
6579					if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6580						nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
6581					}
6582
6583					// Remove IE's autoinserted <tbody> from table fragments
6584					if ( !jQuery.support.tbody ) {
6585
6586						// String was a <table>, *may* have spurious <tbody>
6587						elem = tag === "table" && !rtbody.test( elem ) ?
6588							tmp.firstChild :
6589
6590							// String was a bare <thead> or <tfoot>
6591							wrap[1] === "<table>" && !rtbody.test( elem ) ?
6592								tmp :
6593								0;
6594
6595						j = elem && elem.childNodes.length;
6596						while ( j-- ) {
6597							if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
6598								elem.removeChild( tbody );
6599							}
6600						}
6601					}
6602
6603					jQuery.merge( nodes, tmp.childNodes );
6604
6605					// Fix #12392 for WebKit and IE > 9
6606					tmp.textContent = "";
6607
6608					// Fix #12392 for oldIE
6609					while ( tmp.firstChild ) {
6610						tmp.removeChild( tmp.firstChild );
6611					}
6612
6613					// Remember the top-level container for proper cleanup
6614					tmp = safe.lastChild;
6615				}
6616			}
6617		}
6618
6619		// Fix #11356: Clear elements from fragment
6620		if ( tmp ) {
6621			safe.removeChild( tmp );
6622		}
6623
6624		// Reset defaultChecked for any radios and checkboxes
6625		// about to be appended to the DOM in IE 6/7 (#8060)
6626		if ( !jQuery.support.appendChecked ) {
6627			jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
6628		}
6629
6630		i = 0;
6631		while ( (elem = nodes[ i++ ]) ) {
6632
6633			// #4087 - If origin and destination elements are the same, and this is
6634			// that element, do not do anything
6635			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
6636				continue;
6637			}
6638
6639			contains = jQuery.contains( elem.ownerDocument, elem );
6640
6641			// Append to fragment
6642			tmp = getAll( safe.appendChild( elem ), "script" );
6643
6644			// Preserve script evaluation history
6645			if ( contains ) {
6646				setGlobalEval( tmp );
6647			}
6648
6649			// Capture executables
6650			if ( scripts ) {
6651				j = 0;
6652				while ( (elem = tmp[ j++ ]) ) {
6653					if ( rscriptType.test( elem.type || "" ) ) {
6654						scripts.push( elem );
6655					}
6656				}
6657			}
6658		}
6659
6660		tmp = null;
6661
6662		return safe;
6663	},
6664
6665	cleanData: function( elems, /* internal */ acceptData ) {
6666		var elem, type, id, data,
6667			i = 0,
6668			internalKey = jQuery.expando,
6669			cache = jQuery.cache,
6670			deleteExpando = jQuery.support.deleteExpando,
6671			special = jQuery.event.special;
6672
6673		for ( ; (elem = elems[i]) != null; i++ ) {
6674
6675			if ( acceptData || jQuery.acceptData( elem ) ) {
6676
6677				id = elem[ internalKey ];
6678				data = id && cache[ id ];
6679
6680				if ( data ) {
6681					if ( data.events ) {
6682						for ( type in data.events ) {
6683							if ( special[ type ] ) {
6684								jQuery.event.remove( elem, type );
6685
6686							// This is a shortcut to avoid jQuery.event.remove's overhead
6687							} else {
6688								jQuery.removeEvent( elem, type, data.handle );
6689							}
6690						}
6691					}
6692
6693					// Remove cache only if it was not already removed by jQuery.event.remove
6694					if ( cache[ id ] ) {
6695
6696						delete cache[ id ];
6697
6698						// IE does not allow us to delete expando properties from nodes,
6699						// nor does it have a removeAttribute function on Document nodes;
6700						// we must handle all of these cases
6701						if ( deleteExpando ) {
6702							delete elem[ internalKey ];
6703
6704						} else if ( typeof elem.removeAttribute !== core_strundefined ) {
6705							elem.removeAttribute( internalKey );
6706
6707						} else {
6708							elem[ internalKey ] = null;
6709						}
6710
6711						core_deletedIds.push( id );
6712					}
6713				}
6714			}
6715		}
6716	},
6717
6718	_evalUrl: function( url ) {
6719		return jQuery.ajax({
6720			url: url,
6721			type: "GET",
6722			dataType: "script",
6723			async: false,
6724			global: false,
6725			"throws": true
6726		});
6727	}
6728});
6729jQuery.fn.extend({
6730	wrapAll: function( html ) {
6731		if ( jQuery.isFunction( html ) ) {
6732			return this.each(function(i) {
6733				jQuery(this).wrapAll( html.call(this, i) );
6734			});
6735		}
6736
6737		if ( this[0] ) {
6738			// The elements to wrap the target around
6739			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
6740
6741			if ( this[0].parentNode ) {
6742				wrap.insertBefore( this[0] );
6743			}
6744
6745			wrap.map(function() {
6746				var elem = this;
6747
6748				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
6749					elem = elem.firstChild;
6750				}
6751
6752				return elem;
6753			}).append( this );
6754		}
6755
6756		return this;
6757	},
6758
6759	wrapInner: function( html ) {
6760		if ( jQuery.isFunction( html ) ) {
6761			return this.each(function(i) {
6762				jQuery(this).wrapInner( html.call(this, i) );
6763			});
6764		}
6765
6766		return this.each(function() {
6767			var self = jQuery( this ),
6768				contents = self.contents();
6769
6770			if ( contents.length ) {
6771				contents.wrapAll( html );
6772
6773			} else {
6774				self.append( html );
6775			}
6776		});
6777	},
6778
6779	wrap: function( html ) {
6780		var isFunction = jQuery.isFunction( html );
6781
6782		return this.each(function(i) {
6783			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
6784		});
6785	},
6786
6787	unwrap: function() {
6788		return this.parent().each(function() {
6789			if ( !jQuery.nodeName( this, "body" ) ) {
6790				jQuery( this ).replaceWith( this.childNodes );
6791			}
6792		}).end();
6793	}
6794});
6795var iframe, getStyles, curCSS,
6796	ralpha = /alpha\([^)]*\)/i,
6797	ropacity = /opacity\s*=\s*([^)]*)/,
6798	rposition = /^(top|right|bottom|left)$/,
6799	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6800	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6801	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6802	rmargin = /^margin/,
6803	rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
6804	rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
6805	rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
6806	elemdisplay = { BODY: "block" },
6807
6808	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6809	cssNormalTransform = {
6810		letterSpacing: 0,
6811		fontWeight: 400
6812	},
6813
6814	cssExpand = [ "Top", "Right", "Bottom", "Left" ],
6815	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6816
6817// return a css property mapped to a potentially vendor prefixed property
6818function vendorPropName( style, name ) {
6819
6820	// shortcut for names that are not vendor prefixed
6821	if ( name in style ) {
6822		return name;
6823	}
6824
6825	// check for vendor prefixed names
6826	var capName = name.charAt(0).toUpperCase() + name.slice(1),
6827		origName = name,
6828		i = cssPrefixes.length;
6829
6830	while ( i-- ) {
6831		name = cssPrefixes[ i ] + capName;
6832		if ( name in style ) {
6833			return name;
6834		}
6835	}
6836
6837	return origName;
6838}
6839
6840function isHidden( elem, el ) {
6841	// isHidden might be called from jQuery#filter function;
6842	// in that case, element will be second argument
6843	elem = el || elem;
6844	return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
6845}
6846
6847function showHide( elements, show ) {
6848	var display, elem, hidden,
6849		values = [],
6850		index = 0,
6851		length = elements.length;
6852
6853	for ( ; index < length; index++ ) {
6854		elem = elements[ index ];
6855		if ( !elem.style ) {
6856			continue;
6857		}
6858
6859		values[ index ] = jQuery._data( elem, "olddisplay" );
6860		display = elem.style.display;
6861		if ( show ) {
6862			// Reset the inline display of this element to learn if it is
6863			// being hidden by cascaded rules or not
6864			if ( !values[ index ] && display === "none" ) {
6865				elem.style.display = "";
6866			}
6867
6868			// Set elements which have been overridden with display: none
6869			// in a stylesheet to whatever the default browser style is
6870			// for such an element
6871			if ( elem.style.display === "" && isHidden( elem ) ) {
6872				values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
6873			}
6874		} else {
6875
6876			if ( !values[ index ] ) {
6877				hidden = isHidden( elem );
6878
6879				if ( display && display !== "none" || !hidden ) {
6880					jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6881				}
6882			}
6883		}
6884	}
6885
6886	// Set the display of most of the elements in a second loop
6887	// to avoid the constant reflow
6888	for ( index = 0; index < length; index++ ) {
6889		elem = elements[ index ];
6890		if ( !elem.style ) {
6891			continue;
6892		}
6893		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6894			elem.style.display = show ? values[ index ] || "" : "none";
6895		}
6896	}
6897
6898	return elements;
6899}
6900
6901jQuery.fn.extend({
6902	css: function( name, value ) {
6903		return jQuery.access( this, function( elem, name, value ) {
6904			var len, styles,
6905				map = {},
6906				i = 0;
6907
6908			if ( jQuery.isArray( name ) ) {
6909				styles = getStyles( elem );
6910				len = name.length;
6911
6912				for ( ; i < len; i++ ) {
6913					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6914				}
6915
6916				return map;
6917			}
6918
6919			return value !== undefined ?
6920				jQuery.style( elem, name, value ) :
6921				jQuery.css( elem, name );
6922		}, name, value, arguments.length > 1 );
6923	},
6924	show: function() {
6925		return showHide( this, true );
6926	},
6927	hide: function() {
6928		return showHide( this );
6929	},
6930	toggle: function( state ) {
6931		if ( typeof state === "boolean" ) {
6932			return state ? this.show() : this.hide();
6933		}
6934
6935		return this.each(function() {
6936			if ( isHidden( this ) ) {
6937				jQuery( this ).show();
6938			} else {
6939				jQuery( this ).hide();
6940			}
6941		});
6942	}
6943});
6944
6945jQuery.extend({
6946	// Add in style property hooks for overriding the default
6947	// behavior of getting and setting a style property
6948	cssHooks: {
6949		opacity: {
6950			get: function( elem, computed ) {
6951				if ( computed ) {
6952					// We should always get a number back from opacity
6953					var ret = curCSS( elem, "opacity" );
6954					return ret === "" ? "1" : ret;
6955				}
6956			}
6957		}
6958	},
6959
6960	// Don't automatically add "px" to these possibly-unitless properties
6961	cssNumber: {
6962		"columnCount": true,
6963		"fillOpacity": true,
6964		"fontWeight": true,
6965		"lineHeight": true,
6966		"opacity": true,
6967		"order": true,
6968		"orphans": true,
6969		"widows": true,
6970		"zIndex": true,
6971		"zoom": true
6972	},
6973
6974	// Add in properties whose names you wish to fix before
6975	// setting or getting the value
6976	cssProps: {
6977		// normalize float css property
6978		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6979	},
6980
6981	// Get and set the style property on a DOM Node
6982	style: function( elem, name, value, extra ) {
6983		// Don't set styles on text and comment nodes
6984		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6985			return;
6986		}
6987
6988		// Make sure that we're working with the right name
6989		var ret, type, hooks,
6990			origName = jQuery.camelCase( name ),
6991			style = elem.style;
6992
6993		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6994
6995		// gets hook for the prefixed version
6996		// followed by the unprefixed version
6997		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6998
6999		// Check if we're setting a value
7000		if ( value !== undefined ) {
7001			type = typeof value;
7002
7003			// convert relative number strings (+= or -=) to relative numbers. #7345
7004			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
7005				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
7006				// Fixes bug #9237
7007				type = "number";
7008			}
7009
7010			// Make sure that NaN and null values aren't set. See: #7116
7011			if ( value == null || type === "number" && isNaN( value ) ) {
7012				return;
7013			}
7014
7015			// If a number was passed in, add 'px' to the (except for certain CSS properties)
7016			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
7017				value += "px";
7018			}
7019
7020			// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
7021			// but it would mean to define eight (for every problematic property) identical functions
7022			if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
7023				style[ name ] = "inherit";
7024			}
7025
7026			// If a hook was provided, use that value, otherwise just set the specified value
7027			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
7028
7029				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
7030				// Fixes bug #5509
7031				try {
7032					style[ name ] = value;
7033				} catch(e) {}
7034			}
7035
7036		} else {
7037			// If a hook was provided get the non-computed value from there
7038			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
7039				return ret;
7040			}
7041
7042			// Otherwise just get the value from the style object
7043			return style[ name ];
7044		}
7045	},
7046
7047	css: function( elem, name, extra, styles ) {
7048		var num, val, hooks,
7049			origName = jQuery.camelCase( name );
7050
7051		// Make sure that we're working with the right name
7052		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
7053
7054		// gets hook for the prefixed version
7055		// followed by the unprefixed version
7056		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
7057
7058		// If a hook was provided get the computed value from there
7059		if ( hooks && "get" in hooks ) {
7060			val = hooks.get( elem, true, extra );
7061		}
7062
7063		// Otherwise, if a way to get the computed value exists, use that
7064		if ( val === undefined ) {
7065			val = curCSS( elem, name, styles );
7066		}
7067
7068		//convert "normal" to computed value
7069		if ( val === "normal" && name in cssNormalTransform ) {
7070			val = cssNormalTransform[ name ];
7071		}
7072
7073		// Return, converting to number if forced or a qualifier was provided and val looks numeric
7074		if ( extra === "" || extra ) {
7075			num = parseFloat( val );
7076			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
7077		}
7078		return val;
7079	}
7080});
7081
7082// NOTE: we've included the "window" in window.getComputedStyle
7083// because jsdom on node.js will break without it.
7084if ( window.getComputedStyle ) {
7085	getStyles = function( elem ) {
7086		return window.getComputedStyle( elem, null );
7087	};
7088
7089	curCSS = function( elem, name, _computed ) {
7090		var width, minWidth, maxWidth,
7091			computed = _computed || getStyles( elem ),
7092
7093			// getPropertyValue is only needed for .css('filter') in IE9, see #12537
7094			ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
7095			style = elem.style;
7096
7097		if ( computed ) {
7098
7099			if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
7100				ret = jQuery.style( elem, name );
7101			}
7102
7103			// A tribute to the "awesome hack by Dean Edwards"
7104			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
7105			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
7106			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
7107			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
7108
7109				// Remember the original values
7110				width = style.width;
7111				minWidth = style.minWidth;
7112				maxWidth = style.maxWidth;
7113
7114				// Put in the new values to get a computed value out
7115				style.minWidth = style.maxWidth = style.width = ret;
7116				ret = computed.width;
7117
7118				// Revert the changed values
7119				style.width = width;
7120				style.minWidth = minWidth;
7121				style.maxWidth = maxWidth;
7122			}
7123		}
7124
7125		return ret;
7126	};
7127} else if ( document.documentElement.currentStyle ) {
7128	getStyles = function( elem ) {
7129		return elem.currentStyle;
7130	};
7131
7132	curCSS = function( elem, name, _computed ) {
7133		var left, rs, rsLeft,
7134			computed = _computed || getStyles( elem ),
7135			ret = computed ? computed[ name ] : undefined,
7136			style = elem.style;
7137
7138		// Avoid setting ret to empty string here
7139		// so we don't default to auto
7140		if ( ret == null && style && style[ name ] ) {
7141			ret = style[ name ];
7142		}
7143
7144		// From the awesome hack by Dean Edwards
7145		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
7146
7147		// If we're not dealing with a regular pixel number
7148		// but a number that has a weird ending, we need to convert it to pixels
7149		// but not position css attributes, as those are proportional to the parent element instead
7150		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
7151		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
7152
7153			// Remember the original values
7154			left = style.left;
7155			rs = elem.runtimeStyle;
7156			rsLeft = rs && rs.left;
7157
7158			// Put in the new values to get a computed value out
7159			if ( rsLeft ) {
7160				rs.left = elem.currentStyle.left;
7161			}
7162			style.left = name === "fontSize" ? "1em" : ret;
7163			ret = style.pixelLeft + "px";
7164
7165			// Revert the changed values
7166			style.left = left;
7167			if ( rsLeft ) {
7168				rs.left = rsLeft;
7169			}
7170		}
7171
7172		return ret === "" ? "auto" : ret;
7173	};
7174}
7175
7176function setPositiveNumber( elem, value, subtract ) {
7177	var matches = rnumsplit.exec( value );
7178	return matches ?
7179		// Guard against undefined "subtract", e.g., when used as in cssHooks
7180		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
7181		value;
7182}
7183
7184function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
7185	var i = extra === ( isBorderBox ? "border" : "content" ) ?
7186		// If we already have the right measurement, avoid augmentation
7187		4 :
7188		// Otherwise initialize for horizontal or vertical properties
7189		name === "width" ? 1 : 0,
7190
7191		val = 0;
7192
7193	for ( ; i < 4; i += 2 ) {
7194		// both box models exclude margin, so add it if we want it
7195		if ( extra === "margin" ) {
7196			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
7197		}
7198
7199		if ( isBorderBox ) {
7200			// border-box includes padding, so remove it if we want content
7201			if ( extra === "content" ) {
7202				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7203			}
7204
7205			// at this point, extra isn't border nor margin, so remove border
7206			if ( extra !== "margin" ) {
7207				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7208			}
7209		} else {
7210			// at this point, extra isn't content, so add padding
7211			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7212
7213			// at this point, extra isn't content nor padding, so add border
7214			if ( extra !== "padding" ) {
7215				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7216			}
7217		}
7218	}
7219
7220	return val;
7221}
7222
7223function getWidthOrHeight( elem, name, extra ) {
7224
7225	// Start with offset property, which is equivalent to the border-box value
7226	var valueIsBorderBox = true,
7227		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7228		styles = getStyles( elem ),
7229		isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
7230
7231	// some non-html elements return undefined for offsetWidth, so check for null/undefined
7232	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
7233	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
7234	if ( val <= 0 || val == null ) {
7235		// Fall back to computed then uncomputed css if necessary
7236		val = curCSS( elem, name, styles );
7237		if ( val < 0 || val == null ) {
7238			val = elem.style[ name ];
7239		}
7240
7241		// Computed unit is not pixels. Stop here and return.
7242		if ( rnumnonpx.test(val) ) {
7243			return val;
7244		}
7245
7246		// we need the check for style in case a browser which returns unreliable values
7247		// for getComputedStyle silently falls back to the reliable elem.style
7248		valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
7249
7250		// Normalize "", auto, and prepare for extra
7251		val = parseFloat( val ) || 0;
7252	}
7253
7254	// use the active box-sizing model to add/subtract irrelevant styles
7255	return ( val +
7256		augmentWidthOrHeight(
7257			elem,
7258			name,
7259			extra || ( isBorderBox ? "border" : "content" ),
7260			valueIsBorderBox,
7261			styles
7262		)
7263	) + "px";
7264}
7265
7266// Try to determine the default display value of an element
7267function css_defaultDisplay( nodeName ) {
7268	var doc = document,
7269		display = elemdisplay[ nodeName ];
7270
7271	if ( !display ) {
7272		display = actualDisplay( nodeName, doc );
7273
7274		// If the simple way fails, read from inside an iframe
7275		if ( display === "none" || !display ) {
7276			// Use the already-created iframe if possible
7277			iframe = ( iframe ||
7278				jQuery("<iframe frameborder='0' width='0' height='0'/>")
7279				.css( "cssText", "display:block !important" )
7280			).appendTo( doc.documentElement );
7281
7282			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
7283			doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
7284			doc.write("<!doctype html><html><body>");
7285			doc.close();
7286
7287			display = actualDisplay( nodeName, doc );
7288			iframe.detach();
7289		}
7290
7291		// Store the correct default display
7292		elemdisplay[ nodeName ] = display;
7293	}
7294
7295	return display;
7296}
7297
7298// Called ONLY from within css_defaultDisplay
7299function actualDisplay( name, doc ) {
7300	var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
7301		display = jQuery.css( elem[0], "display" );
7302	elem.remove();
7303	return display;
7304}
7305
7306jQuery.each([ "height", "width" ], function( i, name ) {
7307	jQuery.cssHooks[ name ] = {
7308		get: function( elem, computed, extra ) {
7309			if ( computed ) {
7310				// certain elements can have dimension info if we invisibly show them
7311				// however, it must have a current display style that would benefit from this
7312				return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
7313					jQuery.swap( elem, cssShow, function() {
7314						return getWidthOrHeight( elem, name, extra );
7315					}) :
7316					getWidthOrHeight( elem, name, extra );
7317			}
7318		},
7319
7320		set: function( elem, value, extra ) {
7321			var styles = extra && getStyles( elem );
7322			return setPositiveNumber( elem, value, extra ?
7323				augmentWidthOrHeight(
7324					elem,
7325					name,
7326					extra,
7327					jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7328					styles
7329				) : 0
7330			);
7331		}
7332	};
7333});
7334
7335if ( !jQuery.support.opacity ) {
7336	jQuery.cssHooks.opacity = {
7337		get: function( elem, computed ) {
7338			// IE uses filters for opacity
7339			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7340				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7341				computed ? "1" : "";
7342		},
7343
7344		set: function( elem, value ) {
7345			var style = elem.style,
7346				currentStyle = elem.currentStyle,
7347				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7348				filter = currentStyle && currentStyle.filter || style.filter || "";
7349
7350			// IE has trouble with opacity if it does not have layout
7351			// Force it by setting the zoom level
7352			style.zoom = 1;
7353
7354			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7355			// if value === "", then remove inline opacity #12685
7356			if ( ( value >= 1 || value === "" ) &&
7357					jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7358					style.removeAttribute ) {
7359
7360				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7361				// if "filter:" is present at all, clearType is disabled, we want to avoid this
7362				// style.removeAttribute is IE Only, but so apparently is this code path...
7363				style.removeAttribute( "filter" );
7364
7365				// if there is no filter style applied in a css rule or unset inline opacity, we are done
7366				if ( value === "" || currentStyle && !currentStyle.filter ) {
7367					return;
7368				}
7369			}
7370
7371			// otherwise, set new filter values
7372			style.filter = ralpha.test( filter ) ?
7373				filter.replace( ralpha, opacity ) :
7374				filter + " " + opacity;
7375		}
7376	};
7377}
7378
7379// These hooks cannot be added until DOM ready because the support test
7380// for it is not run until after DOM ready
7381jQuery(function() {
7382	if ( !jQuery.support.reliableMarginRight ) {
7383		jQuery.cssHooks.marginRight = {
7384			get: function( elem, computed ) {
7385				if ( computed ) {
7386					// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7387					// Work around by temporarily setting element display to inline-block
7388					return jQuery.swap( elem, { "display": "inline-block" },
7389						curCSS, [ elem, "marginRight" ] );
7390				}
7391			}
7392		};
7393	}
7394
7395	// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
7396	// getComputedStyle returns percent when specified for top/left/bottom/right
7397	// rather than make the css module depend on the offset module, we just check for it here
7398	if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
7399		jQuery.each( [ "top", "left" ], function( i, prop ) {
7400			jQuery.cssHooks[ prop ] = {
7401				get: function( elem, computed ) {
7402					if ( computed ) {
7403						computed = curCSS( elem, prop );
7404						// if curCSS returns percentage, fallback to offset
7405						return rnumnonpx.test( computed ) ?
7406							jQuery( elem ).position()[ prop ] + "px" :
7407							computed;
7408					}
7409				}
7410			};
7411		});
7412	}
7413
7414});
7415
7416if ( jQuery.expr && jQuery.expr.filters ) {
7417	jQuery.expr.filters.hidden = function( elem ) {
vendor: 5,333 bytes, lines 7418-7596
7418		// Support: Opera <= 12.12
7419		// Opera reports offsetWidths and offsetHeights less than zero on some elements
7420		return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
7421			(!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7422	};
7423
7424	jQuery.expr.filters.visible = function( elem ) {
7425		return !jQuery.expr.filters.hidden( elem );
7426	};
7427}
7428
7429// These hooks are used by animate to expand properties
7430jQuery.each({
7431	margin: "",
7432	padding: "",
7433	border: "Width"
7434}, function( prefix, suffix ) {
7435	jQuery.cssHooks[ prefix + suffix ] = {
7436		expand: function( value ) {
7437			var i = 0,
7438				expanded = {},
7439
7440				// assumes a single number if not a string
7441				parts = typeof value === "string" ? value.split(" ") : [ value ];
7442
7443			for ( ; i < 4; i++ ) {
7444				expanded[ prefix + cssExpand[ i ] + suffix ] =
7445					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7446			}
7447
7448			return expanded;
7449		}
7450	};
7451
7452	if ( !rmargin.test( prefix ) ) {
7453		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7454	}
7455});
7456var r20 = /%20/g,
7457	rbracket = /\[\]$/,
7458	rCRLF = /\r?\n/g,
7459	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
7460	rsubmittable = /^(?:input|select|textarea|keygen)/i;
7461
7462jQuery.fn.extend({
7463	serialize: function() {
7464		return jQuery.param( this.serializeArray() );
7465	},
7466	serializeArray: function() {
7467		return this.map(function(){
7468			// Can add propHook for "elements" to filter or add form elements
7469			var elements = jQuery.prop( this, "elements" );
7470			return elements ? jQuery.makeArray( elements ) : this;
7471		})
7472		.filter(function(){
7473			var type = this.type;
7474			// Use .is(":disabled") so that fieldset[disabled] works
7475			return this.name && !jQuery( this ).is( ":disabled" ) &&
7476				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
7477				( this.checked || !manipulation_rcheckableType.test( type ) );
7478		})
7479		.map(function( i, elem ){
7480			var val = jQuery( this ).val();
7481
7482			return val == null ?
7483				null :
7484				jQuery.isArray( val ) ?
7485					jQuery.map( val, function( val ){
7486						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7487					}) :
7488					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7489		}).get();
7490	}
7491});
7492
7493//Serialize an array of form elements or a set of
7494//key/values into a query string
7495jQuery.param = function( a, traditional ) {
7496	var prefix,
7497		s = [],
7498		add = function( key, value ) {
7499			// If value is a function, invoke it and return its value
7500			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
7501			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7502		};
7503
7504	// Set traditional to true for jQuery <= 1.3.2 behavior.
7505	if ( traditional === undefined ) {
7506		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
7507	}
7508
7509	// If an array was passed in, assume that it is an array of form elements.
7510	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7511		// Serialize the form elements
7512		jQuery.each( a, function() {
7513			add( this.name, this.value );
7514		});
7515
7516	} else {
7517		// If traditional, encode the "old" way (the way 1.3.2 or older
7518		// did it), otherwise encode params recursively.
7519		for ( prefix in a ) {
7520			buildParams( prefix, a[ prefix ], traditional, add );
7521		}
7522	}
7523
7524	// Return the resulting serialization
7525	return s.join( "&" ).replace( r20, "+" );
7526};
7527
7528function buildParams( prefix, obj, traditional, add ) {
7529	var name;
7530
7531	if ( jQuery.isArray( obj ) ) {
7532		// Serialize array item.
7533		jQuery.each( obj, function( i, v ) {
7534			if ( traditional || rbracket.test( prefix ) ) {
7535				// Treat each array item as a scalar.
7536				add( prefix, v );
7537
7538			} else {
7539				// Item is non-scalar (array or object), encode its numeric index.
7540				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
7541			}
7542		});
7543
7544	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
7545		// Serialize object item.
7546		for ( name in obj ) {
7547			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7548		}
7549
7550	} else {
7551		// Serialize scalar item.
7552		add( prefix, obj );
7553	}
7554}
7555jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
7556	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7557	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
7558
7559	// Handle event binding
7560	jQuery.fn[ name ] = function( data, fn ) {
7561		return arguments.length > 0 ?
7562			this.on( name, null, data, fn ) :
7563			this.trigger( name );
7564	};
7565});
7566
7567jQuery.fn.extend({
7568	hover: function( fnOver, fnOut ) {
7569		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7570	},
7571
7572	bind: function( types, data, fn ) {
7573		return this.on( types, null, data, fn );
7574	},
7575	unbind: function( types, fn ) {
7576		return this.off( types, null, fn );
7577	},
7578
7579	delegate: function( selector, types, data, fn ) {
7580		return this.on( types, selector, data, fn );
7581	},
7582	undelegate: function( selector, types, fn ) {
7583		// ( namespace ) or ( selector, types [, fn] )
7584		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
7585	}
7586});
7587var
7588	// Document location
7589	ajaxLocParts,
7590	ajaxLocation,
7591	ajax_nonce = jQuery.now(),
7592
7593	ajax_rquery = /\?/,
7594	rhash = /#.*$/,
7595	rts = /([?&])_=[^&]*/,
7596	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
vendor: 4,281 bytes, lines 7597-7740
7597	// #7653, #8125, #8152: local protocol detection
7598	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7599	rnoContent = /^(?:GET|HEAD)$/,
7600	rprotocol = /^\/\//,
7601	rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
7602
7603	// Keep a copy of the old load method
7604	_load = jQuery.fn.load,
7605
7606	/* Prefilters
7607	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7608	 * 2) These are called:
7609	 *    - BEFORE asking for a transport
7610	 *    - AFTER param serialization (s.data is a string if s.processData is true)
7611	 * 3) key is the dataType
7612	 * 4) the catchall symbol "*" can be used
7613	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7614	 */
7615	prefilters = {},
7616
7617	/* Transports bindings
7618	 * 1) key is the dataType
7619	 * 2) the catchall symbol "*" can be used
7620	 * 3) selection will start with transport dataType and THEN go to "*" if needed
7621	 */
7622	transports = {},
7623
7624	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7625	allTypes = "*/".concat("*");
7626
7627// #8138, IE may throw an exception when accessing
7628// a field from window.location if document.domain has been set
7629try {
7630	ajaxLocation = location.href;
7631} catch( e ) {
7632	// Use the href attribute of an A element
7633	// since IE will modify it given document.location
7634	ajaxLocation = document.createElement( "a" );
7635	ajaxLocation.href = "";
7636	ajaxLocation = ajaxLocation.href;
7637}
7638
7639// Segment location into parts
7640ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7641
7642// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7643function addToPrefiltersOrTransports( structure ) {
7644
7645	// dataTypeExpression is optional and defaults to "*"
7646	return function( dataTypeExpression, func ) {
7647
7648		if ( typeof dataTypeExpression !== "string" ) {
7649			func = dataTypeExpression;
7650			dataTypeExpression = "*";
7651		}
7652
7653		var dataType,
7654			i = 0,
7655			dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
7656
7657		if ( jQuery.isFunction( func ) ) {
7658			// For each dataType in the dataTypeExpression
7659			while ( (dataType = dataTypes[i++]) ) {
7660				// Prepend if requested
7661				if ( dataType[0] === "+" ) {
7662					dataType = dataType.slice( 1 ) || "*";
7663					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7664
7665				// Otherwise append
7666				} else {
7667					(structure[ dataType ] = structure[ dataType ] || []).push( func );
7668				}
7669			}
7670		}
7671	};
7672}
7673
7674// Base inspection function for prefilters and transports
7675function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7676
7677	var inspected = {},
7678		seekingTransport = ( structure === transports );
7679
7680	function inspect( dataType ) {
7681		var selected;
7682		inspected[ dataType ] = true;
7683		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7684			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7685			if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7686				options.dataTypes.unshift( dataTypeOrTransport );
7687				inspect( dataTypeOrTransport );
7688				return false;
7689			} else if ( seekingTransport ) {
7690				return !( selected = dataTypeOrTransport );
7691			}
7692		});
7693		return selected;
7694	}
7695
7696	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7697}
7698
7699// A special extend for ajax options
7700// that takes "flat" options (not to be deep extended)
7701// Fixes #9887
7702function ajaxExtend( target, src ) {
7703	var deep, key,
7704		flatOptions = jQuery.ajaxSettings.flatOptions || {};
7705
7706	for ( key in src ) {
7707		if ( src[ key ] !== undefined ) {
7708			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7709		}
7710	}
7711	if ( deep ) {
7712		jQuery.extend( true, target, deep );
7713	}
7714
7715	return target;
7716}
7717
7718jQuery.fn.load = function( url, params, callback ) {
7719	if ( typeof url !== "string" && _load ) {
7720		return _load.apply( this, arguments );
7721	}
7722
7723	var selector, response, type,
7724		self = this,
7725		off = url.indexOf(" ");
7726
7727	if ( off >= 0 ) {
7728		selector = url.slice( off, url.length );
7729		url = url.slice( 0, off );
7730	}
7731
7732	// If it's a function
7733	if ( jQuery.isFunction( params ) ) {
7734
7735		// We assume that it's the callback
7736		callback = params;
7737		params = undefined;
7738
7739	// Otherwise, build a param string
7740	} else if ( params && typeof params === "object" ) {
vendor: 15,508 bytes, lines 7741-8323
7741		type = "POST";
7742	}
7743
7744	// If we have elements to modify, make the request
7745	if ( self.length > 0 ) {
7746		jQuery.ajax({
7747			url: url,
7748
7749			// if "type" variable is undefined, then "GET" method will be used
7750			type: type,
7751			dataType: "html",
7752			data: params
7753		}).done(function( responseText ) {
7754
7755			// Save response for use in complete callback
7756			response = arguments;
7757
7758			self.html( selector ?
7759
7760				// If a selector was specified, locate the right elements in a dummy div
7761				// Exclude scripts to avoid IE 'Permission Denied' errors
7762				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
7763
7764				// Otherwise use the full result
7765				responseText );
7766
7767		}).complete( callback && function( jqXHR, status ) {
7768			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
7769		});
7770	}
7771
7772	return this;
7773};
7774
7775// Attach a bunch of functions for handling common AJAX events
7776jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
7777	jQuery.fn[ type ] = function( fn ){
7778		return this.on( type, fn );
7779	};
7780});
7781
7782jQuery.extend({
7783
7784	// Counter for holding the number of active queries
7785	active: 0,
7786
7787	// Last-Modified header cache for next request
7788	lastModified: {},
7789	etag: {},
7790
7791	ajaxSettings: {
7792		url: ajaxLocation,
7793		type: "GET",
7794		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7795		global: true,
7796		processData: true,
7797		async: true,
7798		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7799		/*
7800		timeout: 0,
7801		data: null,
7802		dataType: null,
7803		username: null,
7804		password: null,
7805		cache: null,
7806		throws: false,
7807		traditional: false,
7808		headers: {},
7809		*/
7810
7811		accepts: {
7812			"*": allTypes,
7813			text: "text/plain",
7814			html: "text/html",
7815			xml: "application/xml, text/xml",
7816			json: "application/json, text/javascript"
7817		},
7818
7819		contents: {
7820			xml: /xml/,
7821			html: /html/,
7822			json: /json/
7823		},
7824
7825		responseFields: {
7826			xml: "responseXML",
7827			text: "responseText",
7828			json: "responseJSON"
7829		},
7830
7831		// Data converters
7832		// Keys separate source (or catchall "*") and destination types with a single space
7833		converters: {
7834
7835			// Convert anything to text
7836			"* text": String,
7837
7838			// Text to html (true = no transformation)
7839			"text html": true,
7840
7841			// Evaluate text as a json expression
7842			"text json": jQuery.parseJSON,
7843
7844			// Parse text as xml
7845			"text xml": jQuery.parseXML
7846		},
7847
7848		// For options that shouldn't be deep extended:
7849		// you can add your own custom options here if
7850		// and when you create one that shouldn't be
7851		// deep extended (see ajaxExtend)
7852		flatOptions: {
7853			url: true,
7854			context: true
7855		}
7856	},
7857
7858	// Creates a full fledged settings object into target
7859	// with both ajaxSettings and settings fields.
7860	// If target is omitted, writes into ajaxSettings.
7861	ajaxSetup: function( target, settings ) {
7862		return settings ?
7863
7864			// Building a settings object
7865			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7866
7867			// Extending ajaxSettings
7868			ajaxExtend( jQuery.ajaxSettings, target );
7869	},
7870
7871	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7872	ajaxTransport: addToPrefiltersOrTransports( transports ),
7873
7874	// Main method
7875	ajax: function( url, options ) {
7876
7877		// If url is an object, simulate pre-1.5 signature
7878		if ( typeof url === "object" ) {
7879			options = url;
7880			url = undefined;
7881		}
7882
7883		// Force options to be an object
7884		options = options || {};
7885
7886		var // Cross-domain detection vars
7887			parts,
7888			// Loop variable
7889			i,
7890			// URL without anti-cache param
7891			cacheURL,
7892			// Response headers as string
7893			responseHeadersString,
7894			// timeout handle
7895			timeoutTimer,
7896
7897			// To know if global events are to be dispatched
7898			fireGlobals,
7899
7900			transport,
7901			// Response headers
7902			responseHeaders,
7903			// Create the final options object
7904			s = jQuery.ajaxSetup( {}, options ),
7905			// Callbacks context
7906			callbackContext = s.context || s,
7907			// Context for global events is callbackContext if it is a DOM node or jQuery collection
7908			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7909				jQuery( callbackContext ) :
7910				jQuery.event,
7911			// Deferreds
7912			deferred = jQuery.Deferred(),
7913			completeDeferred = jQuery.Callbacks("once memory"),
7914			// Status-dependent callbacks
7915			statusCode = s.statusCode || {},
7916			// Headers (they are sent all at once)
7917			requestHeaders = {},
7918			requestHeadersNames = {},
7919			// The jqXHR state
7920			state = 0,
7921			// Default abort message
7922			strAbort = "canceled",
7923			// Fake xhr
7924			jqXHR = {
7925				readyState: 0,
7926
7927				// Builds headers hashtable if needed
7928				getResponseHeader: function( key ) {
7929					var match;
7930					if ( state === 2 ) {
7931						if ( !responseHeaders ) {
7932							responseHeaders = {};
7933							while ( (match = rheaders.exec( responseHeadersString )) ) {
7934								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7935							}
7936						}
7937						match = responseHeaders[ key.toLowerCase() ];
7938					}
7939					return match == null ? null : match;
7940				},
7941
7942				// Raw string
7943				getAllResponseHeaders: function() {
7944					return state === 2 ? responseHeadersString : null;
7945				},
7946
7947				// Caches the header
7948				setRequestHeader: function( name, value ) {
7949					var lname = name.toLowerCase();
7950					if ( !state ) {
7951						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7952						requestHeaders[ name ] = value;
7953					}
7954					return this;
7955				},
7956
7957				// Overrides response content-type header
7958				overrideMimeType: function( type ) {
7959					if ( !state ) {
7960						s.mimeType = type;
7961					}
7962					return this;
7963				},
7964
7965				// Status-dependent callbacks
7966				statusCode: function( map ) {
7967					var code;
7968					if ( map ) {
7969						if ( state < 2 ) {
7970							for ( code in map ) {
7971								// Lazy-add the new callback in a way that preserves old ones
7972								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
7973							}
7974						} else {
7975							// Execute the appropriate callbacks
7976							jqXHR.always( map[ jqXHR.status ] );
7977						}
7978					}
7979					return this;
7980				},
7981
7982				// Cancel the request
7983				abort: function( statusText ) {
7984					var finalText = statusText || strAbort;
7985					if ( transport ) {
7986						transport.abort( finalText );
7987					}
7988					done( 0, finalText );
7989					return this;
7990				}
7991			};
7992
7993		// Attach deferreds
7994		deferred.promise( jqXHR ).complete = completeDeferred.add;
7995		jqXHR.success = jqXHR.done;
7996		jqXHR.error = jqXHR.fail;
7997
7998		// Remove hash character (#7531: and string promotion)
7999		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
8000		// Handle falsy url in the settings object (#10093: consistency with old signature)
8001		// We also use the url parameter if available
8002		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
8003
8004		// Alias method option to type as per ticket #12004
8005		s.type = options.method || options.type || s.method || s.type;
8006
8007		// Extract dataTypes list
8008		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
8009
8010		// A cross-domain request is in order when we have a protocol:host:port mismatch
8011		if ( s.crossDomain == null ) {
8012			parts = rurl.exec( s.url.toLowerCase() );
8013			s.crossDomain = !!( parts &&
8014				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
8015					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
8016						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
8017			);
8018		}
8019
8020		// Convert data if not already a string
8021		if ( s.data && s.processData && typeof s.data !== "string" ) {
8022			s.data = jQuery.param( s.data, s.traditional );
8023		}
8024
8025		// Apply prefilters
8026		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
8027
8028		// If request was aborted inside a prefilter, stop there
8029		if ( state === 2 ) {
8030			return jqXHR;
8031		}
8032
8033		// We can fire global events as of now if asked to
8034		fireGlobals = s.global;
8035
8036		// Watch for a new set of requests
8037		if ( fireGlobals && jQuery.active++ === 0 ) {
8038			jQuery.event.trigger("ajaxStart");
8039		}
8040
8041		// Uppercase the type
8042		s.type = s.type.toUpperCase();
8043
8044		// Determine if request has content
8045		s.hasContent = !rnoContent.test( s.type );
8046
8047		// Save the URL in case we're toying with the If-Modified-Since
8048		// and/or If-None-Match header later on
8049		cacheURL = s.url;
8050
8051		// More options handling for requests with no content
8052		if ( !s.hasContent ) {
8053
8054			// If data is available, append data to url
8055			if ( s.data ) {
8056				cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
8057				// #9682: remove data so that it's not used in an eventual retry
8058				delete s.data;
8059			}
8060
8061			// Add anti-cache in url if needed
8062			if ( s.cache === false ) {
8063				s.url = rts.test( cacheURL ) ?
8064
8065					// If there is already a '_' parameter, set its value
8066					cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
8067
8068					// Otherwise add one to the end
8069					cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
8070			}
8071		}
8072
8073		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8074		if ( s.ifModified ) {
8075			if ( jQuery.lastModified[ cacheURL ] ) {
8076				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
8077			}
8078			if ( jQuery.etag[ cacheURL ] ) {
8079				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
8080			}
8081		}
8082
8083		// Set the correct header, if data is being sent
8084		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
8085			jqXHR.setRequestHeader( "Content-Type", s.contentType );
8086		}
8087
8088		// Set the Accepts header for the server, depending on the dataType
8089		jqXHR.setRequestHeader(
8090			"Accept",
8091			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
8092				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
8093				s.accepts[ "*" ]
8094		);
8095
8096		// Check for headers option
8097		for ( i in s.headers ) {
8098			jqXHR.setRequestHeader( i, s.headers[ i ] );
8099		}
8100
8101		// Allow custom headers/mimetypes and early abort
8102		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
8103			// Abort if not done already and return
8104			return jqXHR.abort();
8105		}
8106
8107		// aborting is no longer a cancellation
8108		strAbort = "abort";
8109
8110		// Install callbacks on deferreds
8111		for ( i in { success: 1, error: 1, complete: 1 } ) {
8112			jqXHR[ i ]( s[ i ] );
8113		}
8114
8115		// Get transport
8116		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
8117
8118		// If no transport, we auto-abort
8119		if ( !transport ) {
8120			done( -1, "No Transport" );
8121		} else {
8122			jqXHR.readyState = 1;
8123
8124			// Send global event
8125			if ( fireGlobals ) {
8126				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
8127			}
8128			// Timeout
8129			if ( s.async && s.timeout > 0 ) {
8130				timeoutTimer = setTimeout(function() {
8131					jqXHR.abort("timeout");
8132				}, s.timeout );
8133			}
8134
8135			try {
8136				state = 1;
8137				transport.send( requestHeaders, done );
8138			} catch ( e ) {
8139				// Propagate exception as error if not done
8140				if ( state < 2 ) {
8141					done( -1, e );
8142				// Simply rethrow otherwise
8143				} else {
8144					throw e;
8145				}
8146			}
8147		}
8148
8149		// Callback for when everything is done
8150		function done( status, nativeStatusText, responses, headers ) {
8151			var isSuccess, success, error, response, modified,
8152				statusText = nativeStatusText;
8153
8154			// Called once
8155			if ( state === 2 ) {
8156				return;
8157			}
8158
8159			// State is "done" now
8160			state = 2;
8161
8162			// Clear timeout if it exists
8163			if ( timeoutTimer ) {
8164				clearTimeout( timeoutTimer );
8165			}
8166
8167			// Dereference transport for early garbage collection
8168			// (no matter how long the jqXHR object will be used)
8169			transport = undefined;
8170
8171			// Cache response headers
8172			responseHeadersString = headers || "";
8173
8174			// Set readyState
8175			jqXHR.readyState = status > 0 ? 4 : 0;
8176
8177			// Determine if successful
8178			isSuccess = status >= 200 && status < 300 || status === 304;
8179
8180			// Get response data
8181			if ( responses ) {
8182				response = ajaxHandleResponses( s, jqXHR, responses );
8183			}
8184
8185			// Convert no matter what (that way responseXXX fields are always set)
8186			response = ajaxConvert( s, response, jqXHR, isSuccess );
8187
8188			// If successful, handle type chaining
8189			if ( isSuccess ) {
8190
8191				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8192				if ( s.ifModified ) {
8193					modified = jqXHR.getResponseHeader("Last-Modified");
8194					if ( modified ) {
8195						jQuery.lastModified[ cacheURL ] = modified;
8196					}
8197					modified = jqXHR.getResponseHeader("etag");
8198					if ( modified ) {
8199						jQuery.etag[ cacheURL ] = modified;
8200					}
8201				}
8202
8203				// if no content
8204				if ( status === 204 || s.type === "HEAD" ) {
8205					statusText = "nocontent";
8206
8207				// if not modified
8208				} else if ( status === 304 ) {
8209					statusText = "notmodified";
8210
8211				// If we have data, let's convert it
8212				} else {
8213					statusText = response.state;
8214					success = response.data;
8215					error = response.error;
8216					isSuccess = !error;
8217				}
8218			} else {
8219				// We extract error from statusText
8220				// then normalize statusText and status for non-aborts
8221				error = statusText;
8222				if ( status || !statusText ) {
8223					statusText = "error";
8224					if ( status < 0 ) {
8225						status = 0;
8226					}
8227				}
8228			}
8229
8230			// Set data for the fake xhr object
8231			jqXHR.status = status;
8232			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8233
8234			// Success/Error
8235			if ( isSuccess ) {
8236				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8237			} else {
8238				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8239			}
8240
8241			// Status-dependent callbacks
8242			jqXHR.statusCode( statusCode );
8243			statusCode = undefined;
8244
8245			if ( fireGlobals ) {
8246				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8247					[ jqXHR, s, isSuccess ? success : error ] );
8248			}
8249
8250			// Complete
8251			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8252
8253			if ( fireGlobals ) {
8254				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8255				// Handle the global AJAX counter
8256				if ( !( --jQuery.active ) ) {
8257					jQuery.event.trigger("ajaxStop");
8258				}
8259			}
8260		}
8261
8262		return jqXHR;
8263	},
8264
8265	getJSON: function( url, data, callback ) {
8266		return jQuery.get( url, data, callback, "json" );
8267	},
8268
8269	getScript: function( url, callback ) {
8270		return jQuery.get( url, undefined, callback, "script" );
8271	}
8272});
8273
8274jQuery.each( [ "get", "post" ], function( i, method ) {
8275	jQuery[ method ] = function( url, data, callback, type ) {
8276		// shift arguments if data argument was omitted
8277		if ( jQuery.isFunction( data ) ) {
8278			type = type || callback;
8279			callback = data;
8280			data = undefined;
8281		}
8282
8283		return jQuery.ajax({
8284			url: url,
8285			type: method,
8286			dataType: type,
8287			data: data,
8288			success: callback
8289		});
8290	};
8291});
8292
8293/* Handles responses to an ajax request:
8294 * - finds the right dataType (mediates between content-type and expected dataType)
8295 * - returns the corresponding response
8296 */
8297function ajaxHandleResponses( s, jqXHR, responses ) {
8298	var firstDataType, ct, finalDataType, type,
8299		contents = s.contents,
8300		dataTypes = s.dataTypes;
8301
8302	// Remove auto dataType and get content-type in the process
8303	while( dataTypes[ 0 ] === "*" ) {
8304		dataTypes.shift();
8305		if ( ct === undefined ) {
8306			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8307		}
8308	}
8309
8310	// Check if we're dealing with a known content-type
8311	if ( ct ) {
8312		for ( type in contents ) {
8313			if ( contents[ type ] && contents[ type ].test( ct ) ) {
8314				dataTypes.unshift( type );
8315				break;
8316			}
8317		}
8318	}
8319
8320	// Check to see if we have a response for the expected dataType
8321	if ( dataTypes[ 0 ] in responses ) {
8322		finalDataType = dataTypes[ 0 ];
8323	} else {
vendor: 7,605 bytes, lines 8324-8613
8324		// Try convertible dataTypes
8325		for ( type in responses ) {
8326			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8327				finalDataType = type;
8328				break;
8329			}
8330			if ( !firstDataType ) {
8331				firstDataType = type;
8332			}
8333		}
8334		// Or just use first one
8335		finalDataType = finalDataType || firstDataType;
8336	}
8337
8338	// If we found a dataType
8339	// We add the dataType to the list if needed
8340	// and return the corresponding response
8341	if ( finalDataType ) {
8342		if ( finalDataType !== dataTypes[ 0 ] ) {
8343			dataTypes.unshift( finalDataType );
8344		}
8345		return responses[ finalDataType ];
8346	}
8347}
8348
8349/* Chain conversions given the request and the original response
8350 * Also sets the responseXXX fields on the jqXHR instance
8351 */
8352function ajaxConvert( s, response, jqXHR, isSuccess ) {
8353	var conv2, current, conv, tmp, prev,
8354		converters = {},
8355		// Work with a copy of dataTypes in case we need to modify it for conversion
8356		dataTypes = s.dataTypes.slice();
8357
8358	// Create converters map with lowercased keys
8359	if ( dataTypes[ 1 ] ) {
8360		for ( conv in s.converters ) {
8361			converters[ conv.toLowerCase() ] = s.converters[ conv ];
8362		}
8363	}
8364
8365	current = dataTypes.shift();
8366
8367	// Convert to each sequential dataType
8368	while ( current ) {
8369
8370		if ( s.responseFields[ current ] ) {
8371			jqXHR[ s.responseFields[ current ] ] = response;
8372		}
8373
8374		// Apply the dataFilter if provided
8375		if ( !prev && isSuccess && s.dataFilter ) {
8376			response = s.dataFilter( response, s.dataType );
8377		}
8378
8379		prev = current;
8380		current = dataTypes.shift();
8381
8382		if ( current ) {
8383
8384			// There's only work to do if current dataType is non-auto
8385			if ( current === "*" ) {
8386
8387				current = prev;
8388
8389			// Convert response if prev dataType is non-auto and differs from current
8390			} else if ( prev !== "*" && prev !== current ) {
8391
8392				// Seek a direct converter
8393				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8394
8395				// If none found, seek a pair
8396				if ( !conv ) {
8397					for ( conv2 in converters ) {
8398
8399						// If conv2 outputs current
8400						tmp = conv2.split( " " );
8401						if ( tmp[ 1 ] === current ) {
8402
8403							// If prev can be converted to accepted input
8404							conv = converters[ prev + " " + tmp[ 0 ] ] ||
8405								converters[ "* " + tmp[ 0 ] ];
8406							if ( conv ) {
8407								// Condense equivalence converters
8408								if ( conv === true ) {
8409									conv = converters[ conv2 ];
8410
8411								// Otherwise, insert the intermediate dataType
8412								} else if ( converters[ conv2 ] !== true ) {
8413									current = tmp[ 0 ];
8414									dataTypes.unshift( tmp[ 1 ] );
8415								}
8416								break;
8417							}
8418						}
8419					}
8420				}
8421
8422				// Apply converter (if not an equivalence)
8423				if ( conv !== true ) {
8424
8425					// Unless errors are allowed to bubble, catch and return them
8426					if ( conv && s[ "throws" ] ) {
8427						response = conv( response );
8428					} else {
8429						try {
8430							response = conv( response );
8431						} catch ( e ) {
8432							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8433						}
8434					}
8435				}
8436			}
8437		}
8438	}
8439
8440	return { state: "success", data: response };
8441}
8442// Install script dataType
8443jQuery.ajaxSetup({
8444	accepts: {
8445		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8446	},
8447	contents: {
8448		script: /(?:java|ecma)script/
8449	},
8450	converters: {
8451		"text script": function( text ) {
8452			jQuery.globalEval( text );
8453			return text;
8454		}
8455	}
8456});
8457
8458// Handle cache's special case and global
8459jQuery.ajaxPrefilter( "script", function( s ) {
8460	if ( s.cache === undefined ) {
8461		s.cache = false;
8462	}
8463	if ( s.crossDomain ) {
8464		s.type = "GET";
8465		s.global = false;
8466	}
8467});
8468
8469// Bind script tag hack transport
8470jQuery.ajaxTransport( "script", function(s) {
8471
8472	// This transport only deals with cross domain requests
8473	if ( s.crossDomain ) {
8474
8475		var script,
8476			head = document.head || jQuery("head")[0] || document.documentElement;
8477
8478		return {
8479
8480			send: function( _, callback ) {
8481
8482				script = document.createElement("script");
8483
8484				script.async = true;
8485
8486				if ( s.scriptCharset ) {
8487					script.charset = s.scriptCharset;
8488				}
8489
8490				script.src = s.url;
8491
8492				// Attach handlers for all browsers
8493				script.onload = script.onreadystatechange = function( _, isAbort ) {
8494
8495					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8496
8497						// Handle memory leak in IE
8498						script.onload = script.onreadystatechange = null;
8499
8500						// Remove the script
8501						if ( script.parentNode ) {
8502							script.parentNode.removeChild( script );
8503						}
8504
8505						// Dereference the script
8506						script = null;
8507
8508						// Callback if not abort
8509						if ( !isAbort ) {
8510							callback( 200, "success" );
8511						}
8512					}
8513				};
8514
8515				// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
8516				// Use native DOM manipulation to avoid our domManip AJAX trickery
8517				head.insertBefore( script, head.firstChild );
8518			},
8519
8520			abort: function() {
8521				if ( script ) {
8522					script.onload( undefined, true );
8523				}
8524			}
8525		};
8526	}
8527});
8528var oldCallbacks = [],
8529	rjsonp = /(=)\?(?=&|$)|\?\?/;
8530
8531// Default jsonp settings
8532jQuery.ajaxSetup({
8533	jsonp: "callback",
8534	jsonpCallback: function() {
8535		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
8536		this[ callback ] = true;
8537		return callback;
8538	}
8539});
8540
8541// Detect, normalize options and install callbacks for jsonp requests
8542jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8543
8544	var callbackName, overwritten, responseContainer,
8545		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8546			"url" :
8547			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8548		);
8549
8550	// Handle iff the expected data type is "jsonp" or we have a parameter to set
8551	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8552
8553		// Get callback name, remembering preexisting value associated with it
8554		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8555			s.jsonpCallback() :
8556			s.jsonpCallback;
8557
8558		// Insert callback into url or form data
8559		if ( jsonProp ) {
8560			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8561		} else if ( s.jsonp !== false ) {
8562			s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8563		}
8564
8565		// Use data converter to retrieve json after script execution
8566		s.converters["script json"] = function() {
8567			if ( !responseContainer ) {
8568				jQuery.error( callbackName + " was not called" );
8569			}
8570			return responseContainer[ 0 ];
8571		};
8572
8573		// force json dataType
8574		s.dataTypes[ 0 ] = "json";
8575
8576		// Install callback
8577		overwritten = window[ callbackName ];
8578		window[ callbackName ] = function() {
8579			responseContainer = arguments;
8580		};
8581
8582		// Clean-up function (fires after converters)
8583		jqXHR.always(function() {
8584			// Restore preexisting value
8585			window[ callbackName ] = overwritten;
8586
8587			// Save back as free
8588			if ( s[ callbackName ] ) {
8589				// make sure that re-using the options doesn't screw things around
8590				s.jsonpCallback = originalSettings.jsonpCallback;
8591
8592				// save the callback name for future use
8593				oldCallbacks.push( callbackName );
8594			}
8595
8596			// Call if it was a function and we have a response
8597			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8598				overwritten( responseContainer[ 0 ] );
8599			}
8600
8601			responseContainer = overwritten = undefined;
8602		});
8603
8604		// Delegate to script
8605		return "script";
8606	}
8607});
8608var xhrCallbacks, xhrSupported,
8609	xhrId = 0,
8610	// #5280: Internet Explorer will keep connections alive if we don't abort on unload
8611	xhrOnUnloadAbort = window.ActiveXObject && function() {
8612		// Abort all pending requests
8613		var key;
8614		for ( key in xhrCallbacks ) {
8615			xhrCallbacks[ key ]( undefined, true );
8616		}
8617	};
8618
8619// Functions to create xhrs
8620function createStandardXHR() {
8621	try {
8622		return new window.XMLHttpRequest();
8623	} catch( e ) {}
8624}
8625
8626function createActiveXHR() {
8627	try {
8628		return new window.ActiveXObject("Microsoft.XMLHTTP");
8629	} catch( e ) {}
8630}
8631
8632// Create the request object
8633// (This is still attached to ajaxSettings for backward compatibility)
8634jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8635	/* Microsoft failed to properly
8636	 * implement the XMLHttpRequest in IE7 (can't request local files),
8637	 * so we use the ActiveXObject when it is available
8638	 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8639	 * we need a fallback.
8640	 */
8641	function() {
8642		return !this.isLocal && createStandardXHR() || createActiveXHR();
8643	} :
8644	// For all other browsers, use the standard XMLHttpRequest object
8645	createStandardXHR;
8646
8647// Determine support properties
8648xhrSupported = jQuery.ajaxSettings.xhr();
8649jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8650xhrSupported = jQuery.support.ajax = !!xhrSupported;
8651
8652// Create transport if the browser can provide an xhr
8653if ( xhrSupported ) {
8654
8655	jQuery.ajaxTransport(function( s ) {
8656		// Cross domain only allowed if supported through XMLHttpRequest
8657		if ( !s.crossDomain || jQuery.support.cors ) {
8658
8659			var callback;
8660
8661			return {
8662				send: function( headers, complete ) {
8663
8664					// Get a new xhr
8665					var handle, i,
8666						xhr = s.xhr();
8667
8668					// Open the socket
8669					// Passing null username, generates a login popup on Opera (#2865)
8670					if ( s.username ) {
8671						xhr.open( s.type, s.url, s.async, s.username, s.password );
8672					} else {
8673						xhr.open( s.type, s.url, s.async );
8674					}
8675
8676					// Apply custom fields if provided
8677					if ( s.xhrFields ) {
8678						for ( i in s.xhrFields ) {
8679							xhr[ i ] = s.xhrFields[ i ];
8680						}
8681					}
8682
8683					// Override mime type if needed
8684					if ( s.mimeType && xhr.overrideMimeType ) {
8685						xhr.overrideMimeType( s.mimeType );
8686					}
8687
8688					// X-Requested-With header
8689					// For cross-domain requests, seeing as conditions for a preflight are
8690					// akin to a jigsaw puzzle, we simply never set it to be sure.
8691					// (it can always be set on a per-request basis or even using ajaxSetup)
8692					// For same-domain requests, won't change header if already provided.
8693					if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8694						headers["X-Requested-With"] = "XMLHttpRequest";
8695					}
8696
8697					// Need an extra try/catch for cross domain requests in Firefox 3
8698					try {
8699						for ( i in headers ) {
8700							xhr.setRequestHeader( i, headers[ i ] );
8701						}
8702					} catch( err ) {}
8703
8704					// Do send the request
8705					// This may raise an exception which is actually
8706					// handled in jQuery.ajax (so no try/catch here)
8707					xhr.send( ( s.hasContent && s.data ) || null );
8708
8709					// Listener
8710					callback = function( _, isAbort ) {
8711						var status, responseHeaders, statusText, responses;
8712
8713						// Firefox throws exceptions when accessing properties
8714						// of an xhr when a network error occurred
8715						// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8716						try {
8717
8718							// Was never called and is aborted or complete
8719							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8720
8721								// Only called once
8722								callback = undefined;
8723
8724								// Do not keep as active anymore
8725								if ( handle ) {
8726									xhr.onreadystatechange = jQuery.noop;
8727									if ( xhrOnUnloadAbort ) {
8728										delete xhrCallbacks[ handle ];
8729									}
8730								}
8731
8732								// If it's an abort
8733								if ( isAbort ) {
8734									// Abort it manually if needed
8735									if ( xhr.readyState !== 4 ) {
8736										xhr.abort();
8737									}
8738								} else {
8739									responses = {};
8740									status = xhr.status;
8741									responseHeaders = xhr.getAllResponseHeaders();
8742
8743									// When requesting binary data, IE6-9 will throw an exception
8744									// on any attempt to access responseText (#11426)
8745									if ( typeof xhr.responseText === "string" ) {
8746										responses.text = xhr.responseText;
8747									}
8748
8749									// Firefox throws an exception when accessing
8750									// statusText for faulty cross-domain requests
8751									try {
8752										statusText = xhr.statusText;
8753									} catch( e ) {
8754										// We normalize with Webkit giving an empty statusText
8755										statusText = "";
8756									}
8757
8758									// Filter status for non standard behaviors
8759
8760									// If the request is local and we have data: assume a success
8761									// (success with no data won't get notified, that's the best we
8762									// can do given current implementations)
8763									if ( !status && s.isLocal && !s.crossDomain ) {
8764										status = responses.text ? 200 : 404;
8765									// IE - #1450: sometimes returns 1223 when it should be 204
8766									} else if ( status === 1223 ) {
8767										status = 204;
8768									}
8769								}
8770							}
8771						} catch( firefoxAccessException ) {
8772							if ( !isAbort ) {
8773								complete( -1, firefoxAccessException );
8774							}
8775						}
8776
8777						// Call complete if needed
8778						if ( responses ) {
8779							complete( status, statusText, responses, responseHeaders );
8780						}
8781					};
8782
8783					if ( !s.async ) {
8784						// if we're in sync mode we fire the callback
8785						callback();
8786					} else if ( xhr.readyState === 4 ) {
8787						// (IE6 & IE7) if it's in cache and has been
8788						// retrieved directly we need to fire the callback
8789						setTimeout( callback );
8790					} else {
8791						handle = ++xhrId;
8792						if ( xhrOnUnloadAbort ) {
8793							// Create the active xhrs callbacks list if needed
8794							// and attach the unload handler
8795							if ( !xhrCallbacks ) {
8796								xhrCallbacks = {};
8797								jQuery( window ).unload( xhrOnUnloadAbort );
8798							}
8799							// Add to list of active xhrs callbacks
8800							xhrCallbacks[ handle ] = callback;
8801						}
8802						xhr.onreadystatechange = callback;
8803					}
8804				},
8805
8806				abort: function() {
8807					if ( callback ) {
8808						callback( undefined, true );
8809					}
8810				}
8811			};
8812		}
8813	});
8814}
8815var fxNow, timerId,
8816	rfxtypes = /^(?:toggle|show|hide)$/,
8817	rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
8818	rrun = /queueHooks$/,
8819	animationPrefilters = [ defaultPrefilter ],
8820	tweeners = {
8821		"*": [function( prop, value ) {
8822			var tween = this.createTween( prop, value ),
8823				target = tween.cur(),
8824				parts = rfxnum.exec( value ),
8825				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
vendor: 23,716 bytes, lines 8826-9717
8826
8827				// Starting value computation is required for potential unit mismatches
8828				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
8829					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
8830				scale = 1,
8831				maxIterations = 20;
8832
8833			if ( start && start[ 3 ] !== unit ) {
8834				// Trust units reported by jQuery.css
8835				unit = unit || start[ 3 ];
8836
8837				// Make sure we update the tween properties later on
8838				parts = parts || [];
8839
8840				// Iteratively approximate from a nonzero starting point
8841				start = +target || 1;
8842
8843				do {
8844					// If previous iteration zeroed out, double until we get *something*
8845					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
8846					scale = scale || ".5";
8847
8848					// Adjust and apply
8849					start = start / scale;
8850					jQuery.style( tween.elem, prop, start + unit );
8851
8852				// Update scale, tolerating zero or NaN from tween.cur()
8853				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8854				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8855			}
8856
8857			// Update tween properties
8858			if ( parts ) {
8859				start = tween.start = +start || +target || 0;
8860				tween.unit = unit;
8861				// If a +=/-= token was provided, we're doing a relative animation
8862				tween.end = parts[ 1 ] ?
8863					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
8864					+parts[ 2 ];
8865			}
8866
8867			return tween;
8868		}]
8869	};
8870
8871// Animations created synchronously will run synchronously
8872function createFxNow() {
8873	setTimeout(function() {
8874		fxNow = undefined;
8875	});
8876	return ( fxNow = jQuery.now() );
8877}
8878
8879function createTween( value, prop, animation ) {
8880	var tween,
8881		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8882		index = 0,
8883		length = collection.length;
8884	for ( ; index < length; index++ ) {
8885		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
8886
8887			// we're done with this property
8888			return tween;
8889		}
8890	}
8891}
8892
8893function Animation( elem, properties, options ) {
8894	var result,
8895		stopped,
8896		index = 0,
8897		length = animationPrefilters.length,
8898		deferred = jQuery.Deferred().always( function() {
8899			// don't match elem in the :animated selector
8900			delete tick.elem;
8901		}),
8902		tick = function() {
8903			if ( stopped ) {
8904				return false;
8905			}
8906			var currentTime = fxNow || createFxNow(),
8907				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8908				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8909				temp = remaining / animation.duration || 0,
8910				percent = 1 - temp,
8911				index = 0,
8912				length = animation.tweens.length;
8913
8914			for ( ; index < length ; index++ ) {
8915				animation.tweens[ index ].run( percent );
8916			}
8917
8918			deferred.notifyWith( elem, [ animation, percent, remaining ]);
8919
8920			if ( percent < 1 && length ) {
8921				return remaining;
8922			} else {
8923				deferred.resolveWith( elem, [ animation ] );
8924				return false;
8925			}
8926		},
8927		animation = deferred.promise({
8928			elem: elem,
8929			props: jQuery.extend( {}, properties ),
8930			opts: jQuery.extend( true, { specialEasing: {} }, options ),
8931			originalProperties: properties,
8932			originalOptions: options,
8933			startTime: fxNow || createFxNow(),
8934			duration: options.duration,
8935			tweens: [],
8936			createTween: function( prop, end ) {
8937				var tween = jQuery.Tween( elem, animation.opts, prop, end,
8938						animation.opts.specialEasing[ prop ] || animation.opts.easing );
8939				animation.tweens.push( tween );
8940				return tween;
8941			},
8942			stop: function( gotoEnd ) {
8943				var index = 0,
8944					// if we are going to the end, we want to run all the tweens
8945					// otherwise we skip this part
8946					length = gotoEnd ? animation.tweens.length : 0;
8947				if ( stopped ) {
8948					return this;
8949				}
8950				stopped = true;
8951				for ( ; index < length ; index++ ) {
8952					animation.tweens[ index ].run( 1 );
8953				}
8954
8955				// resolve when we played the last frame
8956				// otherwise, reject
8957				if ( gotoEnd ) {
8958					deferred.resolveWith( elem, [ animation, gotoEnd ] );
8959				} else {
8960					deferred.rejectWith( elem, [ animation, gotoEnd ] );
8961				}
8962				return this;
8963			}
8964		}),
8965		props = animation.props;
8966
8967	propFilter( props, animation.opts.specialEasing );
8968
8969	for ( ; index < length ; index++ ) {
8970		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
8971		if ( result ) {
8972			return result;
8973		}
8974	}
8975
8976	jQuery.map( props, createTween, animation );
8977
8978	if ( jQuery.isFunction( animation.opts.start ) ) {
8979		animation.opts.start.call( elem, animation );
8980	}
8981
8982	jQuery.fx.timer(
8983		jQuery.extend( tick, {
8984			elem: elem,
8985			anim: animation,
8986			queue: animation.opts.queue
8987		})
8988	);
8989
8990	// attach callbacks from options
8991	return animation.progress( animation.opts.progress )
8992		.done( animation.opts.done, animation.opts.complete )
8993		.fail( animation.opts.fail )
8994		.always( animation.opts.always );
8995}
8996
8997function propFilter( props, specialEasing ) {
8998	var index, name, easing, value, hooks;
8999
9000	// camelCase, specialEasing and expand cssHook pass
9001	for ( index in props ) {
9002		name = jQuery.camelCase( index );
9003		easing = specialEasing[ name ];
9004		value = props[ index ];
9005		if ( jQuery.isArray( value ) ) {
9006			easing = value[ 1 ];
9007			value = props[ index ] = value[ 0 ];
9008		}
9009
9010		if ( index !== name ) {
9011			props[ name ] = value;
9012			delete props[ index ];
9013		}
9014
9015		hooks = jQuery.cssHooks[ name ];
9016		if ( hooks && "expand" in hooks ) {
9017			value = hooks.expand( value );
9018			delete props[ name ];
9019
9020			// not quite $.extend, this wont overwrite keys already present.
9021			// also - reusing 'index' from above because we have the correct "name"
9022			for ( index in value ) {
9023				if ( !( index in props ) ) {
9024					props[ index ] = value[ index ];
9025					specialEasing[ index ] = easing;
9026				}
9027			}
9028		} else {
9029			specialEasing[ name ] = easing;
9030		}
9031	}
9032}
9033
9034jQuery.Animation = jQuery.extend( Animation, {
9035
9036	tweener: function( props, callback ) {
9037		if ( jQuery.isFunction( props ) ) {
9038			callback = props;
9039			props = [ "*" ];
9040		} else {
9041			props = props.split(" ");
9042		}
9043
9044		var prop,
9045			index = 0,
9046			length = props.length;
9047
9048		for ( ; index < length ; index++ ) {
9049			prop = props[ index ];
9050			tweeners[ prop ] = tweeners[ prop ] || [];
9051			tweeners[ prop ].unshift( callback );
9052		}
9053	},
9054
9055	prefilter: function( callback, prepend ) {
9056		if ( prepend ) {
9057			animationPrefilters.unshift( callback );
9058		} else {
9059			animationPrefilters.push( callback );
9060		}
9061	}
9062});
9063
9064function defaultPrefilter( elem, props, opts ) {
9065	/* jshint validthis: true */
9066	var prop, value, toggle, tween, hooks, oldfire,
9067		anim = this,
9068		orig = {},
9069		style = elem.style,
9070		hidden = elem.nodeType && isHidden( elem ),
9071		dataShow = jQuery._data( elem, "fxshow" );
9072
9073	// handle queue: false promises
9074	if ( !opts.queue ) {
9075		hooks = jQuery._queueHooks( elem, "fx" );
9076		if ( hooks.unqueued == null ) {
9077			hooks.unqueued = 0;
9078			oldfire = hooks.empty.fire;
9079			hooks.empty.fire = function() {
9080				if ( !hooks.unqueued ) {
9081					oldfire();
9082				}
9083			};
9084		}
9085		hooks.unqueued++;
9086
9087		anim.always(function() {
9088			// doing this makes sure that the complete handler will be called
9089			// before this completes
9090			anim.always(function() {
9091				hooks.unqueued--;
9092				if ( !jQuery.queue( elem, "fx" ).length ) {
9093					hooks.empty.fire();
9094				}
9095			});
9096		});
9097	}
9098
9099	// height/width overflow pass
9100	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
9101		// Make sure that nothing sneaks out
9102		// Record all 3 overflow attributes because IE does not
9103		// change the overflow attribute when overflowX and
9104		// overflowY are set to the same value
9105		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
9106
9107		// Set display property to inline-block for height/width
9108		// animations on inline elements that are having width/height animated
9109		if ( jQuery.css( elem, "display" ) === "inline" &&
9110				jQuery.css( elem, "float" ) === "none" ) {
9111
9112			// inline-level elements accept inline-block;
9113			// block-level elements need to be inline with layout
9114			if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
9115				style.display = "inline-block";
9116
9117			} else {
9118				style.zoom = 1;
9119			}
9120		}
9121	}
9122
9123	if ( opts.overflow ) {
9124		style.overflow = "hidden";
9125		if ( !jQuery.support.shrinkWrapBlocks ) {
9126			anim.always(function() {
9127				style.overflow = opts.overflow[ 0 ];
9128				style.overflowX = opts.overflow[ 1 ];
9129				style.overflowY = opts.overflow[ 2 ];
9130			});
9131		}
9132	}
9133
9134
9135	// show/hide pass
9136	for ( prop in props ) {
9137		value = props[ prop ];
9138		if ( rfxtypes.exec( value ) ) {
9139			delete props[ prop ];
9140			toggle = toggle || value === "toggle";
9141			if ( value === ( hidden ? "hide" : "show" ) ) {
9142				continue;
9143			}
9144			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
9145		}
9146	}
9147
9148	if ( !jQuery.isEmptyObject( orig ) ) {
9149		if ( dataShow ) {
9150			if ( "hidden" in dataShow ) {
9151				hidden = dataShow.hidden;
9152			}
9153		} else {
9154			dataShow = jQuery._data( elem, "fxshow", {} );
9155		}
9156
9157		// store state if its toggle - enables .stop().toggle() to "reverse"
9158		if ( toggle ) {
9159			dataShow.hidden = !hidden;
9160		}
9161		if ( hidden ) {
9162			jQuery( elem ).show();
9163		} else {
9164			anim.done(function() {
9165				jQuery( elem ).hide();
9166			});
9167		}
9168		anim.done(function() {
9169			var prop;
9170			jQuery._removeData( elem, "fxshow" );
9171			for ( prop in orig ) {
9172				jQuery.style( elem, prop, orig[ prop ] );
9173			}
9174		});
9175		for ( prop in orig ) {
9176			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
9177
9178			if ( !( prop in dataShow ) ) {
9179				dataShow[ prop ] = tween.start;
9180				if ( hidden ) {
9181					tween.end = tween.start;
9182					tween.start = prop === "width" || prop === "height" ? 1 : 0;
9183				}
9184			}
9185		}
9186	}
9187}
9188
9189function Tween( elem, options, prop, end, easing ) {
9190	return new Tween.prototype.init( elem, options, prop, end, easing );
9191}
9192jQuery.Tween = Tween;
9193
9194Tween.prototype = {
9195	constructor: Tween,
9196	init: function( elem, options, prop, end, easing, unit ) {
9197		this.elem = elem;
9198		this.prop = prop;
9199		this.easing = easing || "swing";
9200		this.options = options;
9201		this.start = this.now = this.cur();
9202		this.end = end;
9203		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
9204	},
9205	cur: function() {
9206		var hooks = Tween.propHooks[ this.prop ];
9207
9208		return hooks && hooks.get ?
9209			hooks.get( this ) :
9210			Tween.propHooks._default.get( this );
9211	},
9212	run: function( percent ) {
9213		var eased,
9214			hooks = Tween.propHooks[ this.prop ];
9215
9216		if ( this.options.duration ) {
9217			this.pos = eased = jQuery.easing[ this.easing ](
9218				percent, this.options.duration * percent, 0, 1, this.options.duration
9219			);
9220		} else {
9221			this.pos = eased = percent;
9222		}
9223		this.now = ( this.end - this.start ) * eased + this.start;
9224
9225		if ( this.options.step ) {
9226			this.options.step.call( this.elem, this.now, this );
9227		}
9228
9229		if ( hooks && hooks.set ) {
9230			hooks.set( this );
9231		} else {
9232			Tween.propHooks._default.set( this );
9233		}
9234		return this;
9235	}
9236};
9237
9238Tween.prototype.init.prototype = Tween.prototype;
9239
9240Tween.propHooks = {
9241	_default: {
9242		get: function( tween ) {
9243			var result;
9244
9245			if ( tween.elem[ tween.prop ] != null &&
9246				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
9247				return tween.elem[ tween.prop ];
9248			}
9249
9250			// passing an empty string as a 3rd parameter to .css will automatically
9251			// attempt a parseFloat and fallback to a string if the parse fails
9252			// so, simple values such as "10px" are parsed to Float.
9253			// complex values such as "rotate(1rad)" are returned as is.
9254			result = jQuery.css( tween.elem, tween.prop, "" );
9255			// Empty strings, null, undefined and "auto" are converted to 0.
9256			return !result || result === "auto" ? 0 : result;
9257		},
9258		set: function( tween ) {
9259			// use step hook for back compat - use cssHook if its there - use .style if its
9260			// available and use plain properties where available
9261			if ( jQuery.fx.step[ tween.prop ] ) {
9262				jQuery.fx.step[ tween.prop ]( tween );
9263			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
9264				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
9265			} else {
9266				tween.elem[ tween.prop ] = tween.now;
9267			}
9268		}
9269	}
9270};
9271
9272// Support: IE <=9
9273// Panic based approach to setting things on disconnected nodes
9274
9275Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
9276	set: function( tween ) {
9277		if ( tween.elem.nodeType && tween.elem.parentNode ) {
9278			tween.elem[ tween.prop ] = tween.now;
9279		}
9280	}
9281};
9282
9283jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9284	var cssFn = jQuery.fn[ name ];
9285	jQuery.fn[ name ] = function( speed, easing, callback ) {
9286		return speed == null || typeof speed === "boolean" ?
9287			cssFn.apply( this, arguments ) :
9288			this.animate( genFx( name, true ), speed, easing, callback );
9289	};
9290});
9291
9292jQuery.fn.extend({
9293	fadeTo: function( speed, to, easing, callback ) {
9294
9295		// show any hidden elements after setting opacity to 0
9296		return this.filter( isHidden ).css( "opacity", 0 ).show()
9297
9298			// animate to the value specified
9299			.end().animate({ opacity: to }, speed, easing, callback );
9300	},
9301	animate: function( prop, speed, easing, callback ) {
9302		var empty = jQuery.isEmptyObject( prop ),
9303			optall = jQuery.speed( speed, easing, callback ),
9304			doAnimation = function() {
9305				// Operate on a copy of prop so per-property easing won't be lost
9306				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9307
9308				// Empty animations, or finishing resolves immediately
9309				if ( empty || jQuery._data( this, "finish" ) ) {
9310					anim.stop( true );
9311				}
9312			};
9313			doAnimation.finish = doAnimation;
9314
9315		return empty || optall.queue === false ?
9316			this.each( doAnimation ) :
9317			this.queue( optall.queue, doAnimation );
9318	},
9319	stop: function( type, clearQueue, gotoEnd ) {
9320		var stopQueue = function( hooks ) {
9321			var stop = hooks.stop;
9322			delete hooks.stop;
9323			stop( gotoEnd );
9324		};
9325
9326		if ( typeof type !== "string" ) {
9327			gotoEnd = clearQueue;
9328			clearQueue = type;
9329			type = undefined;
9330		}
9331		if ( clearQueue && type !== false ) {
9332			this.queue( type || "fx", [] );
9333		}
9334
9335		return this.each(function() {
9336			var dequeue = true,
9337				index = type != null && type + "queueHooks",
9338				timers = jQuery.timers,
9339				data = jQuery._data( this );
9340
9341			if ( index ) {
9342				if ( data[ index ] && data[ index ].stop ) {
9343					stopQueue( data[ index ] );
9344				}
9345			} else {
9346				for ( index in data ) {
9347					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9348						stopQueue( data[ index ] );
9349					}
9350				}
9351			}
9352
9353			for ( index = timers.length; index--; ) {
9354				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9355					timers[ index ].anim.stop( gotoEnd );
9356					dequeue = false;
9357					timers.splice( index, 1 );
9358				}
9359			}
9360
9361			// start the next in the queue if the last step wasn't forced
9362			// timers currently will call their complete callbacks, which will dequeue
9363			// but only if they were gotoEnd
9364			if ( dequeue || !gotoEnd ) {
9365				jQuery.dequeue( this, type );
9366			}
9367		});
9368	},
9369	finish: function( type ) {
9370		if ( type !== false ) {
9371			type = type || "fx";
9372		}
9373		return this.each(function() {
9374			var index,
9375				data = jQuery._data( this ),
9376				queue = data[ type + "queue" ],
9377				hooks = data[ type + "queueHooks" ],
9378				timers = jQuery.timers,
9379				length = queue ? queue.length : 0;
9380
9381			// enable finishing flag on private data
9382			data.finish = true;
9383
9384			// empty the queue first
9385			jQuery.queue( this, type, [] );
9386
9387			if ( hooks && hooks.stop ) {
9388				hooks.stop.call( this, true );
9389			}
9390
9391			// look for any active animations, and finish them
9392			for ( index = timers.length; index--; ) {
9393				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
9394					timers[ index ].anim.stop( true );
9395					timers.splice( index, 1 );
9396				}
9397			}
9398
9399			// look for any animations in the old queue and finish them
9400			for ( index = 0; index < length; index++ ) {
9401				if ( queue[ index ] && queue[ index ].finish ) {
9402					queue[ index ].finish.call( this );
9403				}
9404			}
9405
9406			// turn off finishing flag
9407			delete data.finish;
9408		});
9409	}
9410});
9411
9412// Generate parameters to create a standard animation
9413function genFx( type, includeWidth ) {
9414	var which,
9415		attrs = { height: type },
9416		i = 0;
9417
9418	// if we include width, step value is 1 to do all cssExpand values,
9419	// if we don't include width, step value is 2 to skip over Left and Right
9420	includeWidth = includeWidth? 1 : 0;
9421	for( ; i < 4 ; i += 2 - includeWidth ) {
9422		which = cssExpand[ i ];
9423		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
9424	}
9425
9426	if ( includeWidth ) {
9427		attrs.opacity = attrs.width = type;
9428	}
9429
9430	return attrs;
9431}
9432
9433// Generate shortcuts for custom animations
9434jQuery.each({
9435	slideDown: genFx("show"),
9436	slideUp: genFx("hide"),
9437	slideToggle: genFx("toggle"),
9438	fadeIn: { opacity: "show" },
9439	fadeOut: { opacity: "hide" },
9440	fadeToggle: { opacity: "toggle" }
9441}, function( name, props ) {
9442	jQuery.fn[ name ] = function( speed, easing, callback ) {
9443		return this.animate( props, speed, easing, callback );
9444	};
9445});
9446
9447jQuery.speed = function( speed, easing, fn ) {
9448	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9449		complete: fn || !fn && easing ||
9450			jQuery.isFunction( speed ) && speed,
9451		duration: speed,
9452		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9453	};
9454
9455	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9456		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9457
9458	// normalize opt.queue - true/undefined/null -> "fx"
9459	if ( opt.queue == null || opt.queue === true ) {
9460		opt.queue = "fx";
9461	}
9462
9463	// Queueing
9464	opt.old = opt.complete;
9465
9466	opt.complete = function() {
9467		if ( jQuery.isFunction( opt.old ) ) {
9468			opt.old.call( this );
9469		}
9470
9471		if ( opt.queue ) {
9472			jQuery.dequeue( this, opt.queue );
9473		}
9474	};
9475
9476	return opt;
9477};
9478
9479jQuery.easing = {
9480	linear: function( p ) {
9481		return p;
9482	},
9483	swing: function( p ) {
9484		return 0.5 - Math.cos( p*Math.PI ) / 2;
9485	}
9486};
9487
9488jQuery.timers = [];
9489jQuery.fx = Tween.prototype.init;
9490jQuery.fx.tick = function() {
9491	var timer,
9492		timers = jQuery.timers,
9493		i = 0;
9494
9495	fxNow = jQuery.now();
9496
9497	for ( ; i < timers.length; i++ ) {
9498		timer = timers[ i ];
9499		// Checks the timer has not already been removed
9500		if ( !timer() && timers[ i ] === timer ) {
9501			timers.splice( i--, 1 );
9502		}
9503	}
9504
9505	if ( !timers.length ) {
9506		jQuery.fx.stop();
9507	}
9508	fxNow = undefined;
9509};
9510
9511jQuery.fx.timer = function( timer ) {
9512	if ( timer() && jQuery.timers.push( timer ) ) {
9513		jQuery.fx.start();
9514	}
9515};
9516
9517jQuery.fx.interval = 13;
9518
9519jQuery.fx.start = function() {
9520	if ( !timerId ) {
9521		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9522	}
9523};
9524
9525jQuery.fx.stop = function() {
9526	clearInterval( timerId );
9527	timerId = null;
9528};
9529
9530jQuery.fx.speeds = {
9531	slow: 600,
9532	fast: 200,
9533	// Default speed
9534	_default: 400
9535};
9536
9537// Back Compat <1.8 extension point
9538jQuery.fx.step = {};
9539
9540if ( jQuery.expr && jQuery.expr.filters ) {
9541	jQuery.expr.filters.animated = function( elem ) {
9542		return jQuery.grep(jQuery.timers, function( fn ) {
9543			return elem === fn.elem;
9544		}).length;
9545	};
9546}
9547jQuery.fn.offset = function( options ) {
9548	if ( arguments.length ) {
9549		return options === undefined ?
9550			this :
9551			this.each(function( i ) {
9552				jQuery.offset.setOffset( this, options, i );
9553			});
9554	}
9555
9556	var docElem, win,
9557		box = { top: 0, left: 0 },
9558		elem = this[ 0 ],
9559		doc = elem && elem.ownerDocument;
9560
9561	if ( !doc ) {
9562		return;
9563	}
9564
9565	docElem = doc.documentElement;
9566
9567	// Make sure it's not a disconnected DOM node
9568	if ( !jQuery.contains( docElem, elem ) ) {
9569		return box;
9570	}
9571
9572	// If we don't have gBCR, just use 0,0 rather than error
9573	// BlackBerry 5, iOS 3 (original iPhone)
9574	if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
9575		box = elem.getBoundingClientRect();
9576	}
9577	win = getWindow( doc );
9578	return {
9579		top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
9580		left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
9581	};
9582};
9583
9584jQuery.offset = {
9585
9586	setOffset: function( elem, options, i ) {
9587		var position = jQuery.css( elem, "position" );
9588
9589		// set position first, in-case top/left are set even on static elem
9590		if ( position === "static" ) {
9591			elem.style.position = "relative";
9592		}
9593
9594		var curElem = jQuery( elem ),
9595			curOffset = curElem.offset(),
9596			curCSSTop = jQuery.css( elem, "top" ),
9597			curCSSLeft = jQuery.css( elem, "left" ),
9598			calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9599			props = {}, curPosition = {}, curTop, curLeft;
9600
9601		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9602		if ( calculatePosition ) {
9603			curPosition = curElem.position();
9604			curTop = curPosition.top;
9605			curLeft = curPosition.left;
9606		} else {
9607			curTop = parseFloat( curCSSTop ) || 0;
9608			curLeft = parseFloat( curCSSLeft ) || 0;
9609		}
9610
9611		if ( jQuery.isFunction( options ) ) {
9612			options = options.call( elem, i, curOffset );
9613		}
9614
9615		if ( options.top != null ) {
9616			props.top = ( options.top - curOffset.top ) + curTop;
9617		}
9618		if ( options.left != null ) {
9619			props.left = ( options.left - curOffset.left ) + curLeft;
9620		}
9621
9622		if ( "using" in options ) {
9623			options.using.call( elem, props );
9624		} else {
9625			curElem.css( props );
9626		}
9627	}
9628};
9629
9630
9631jQuery.fn.extend({
9632
9633	position: function() {
9634		if ( !this[ 0 ] ) {
9635			return;
9636		}
9637
9638		var offsetParent, offset,
9639			parentOffset = { top: 0, left: 0 },
9640			elem = this[ 0 ];
9641
9642		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
9643		if ( jQuery.css( elem, "position" ) === "fixed" ) {
9644			// we assume that getBoundingClientRect is available when computed position is fixed
9645			offset = elem.getBoundingClientRect();
9646		} else {
9647			// Get *real* offsetParent
9648			offsetParent = this.offsetParent();
9649
9650			// Get correct offsets
9651			offset = this.offset();
9652			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9653				parentOffset = offsetParent.offset();
9654			}
9655
9656			// Add offsetParent borders
9657			parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9658			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9659		}
9660
9661		// Subtract parent offsets and element margins
9662		// note: when an element has margin: auto the offsetLeft and marginLeft
9663		// are the same in Safari causing offset.left to incorrectly be 0
9664		return {
9665			top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9666			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
9667		};
9668	},
9669
9670	offsetParent: function() {
9671		return this.map(function() {
9672			var offsetParent = this.offsetParent || docElem;
9673			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
9674				offsetParent = offsetParent.offsetParent;
9675			}
9676			return offsetParent || docElem;
9677		});
9678	}
9679});
9680
9681
9682// Create scrollLeft and scrollTop methods
9683jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
9684	var top = /Y/.test( prop );
9685
9686	jQuery.fn[ method ] = function( val ) {
9687		return jQuery.access( this, function( elem, method, val ) {
9688			var win = getWindow( elem );
9689
9690			if ( val === undefined ) {
9691				return win ? (prop in win) ? win[ prop ] :
9692					win.document.documentElement[ method ] :
9693					elem[ method ];
9694			}
9695
9696			if ( win ) {
9697				win.scrollTo(
9698					!top ? val : jQuery( win ).scrollLeft(),
9699					top ? val : jQuery( win ).scrollTop()
9700				);
9701
9702			} else {
9703				elem[ method ] = val;
9704			}
9705		}, method, val, arguments.length, null );
9706	};
9707});
9708
9709function getWindow( elem ) {
9710	return jQuery.isWindow( elem ) ?
9711		elem :
9712		elem.nodeType === 9 ?
9713			elem.defaultView || elem.parentWindow :
9714			false;
9715}
9716// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9717jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9718	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9719		// margin is only for outerHeight, outerWidth
9720		jQuery.fn[ funcName ] = function( margin, value ) {
9721			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9722				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9723
9724			return jQuery.access( this, function( elem, type, value ) {
9725				var doc;
9726
9727				if ( jQuery.isWindow( elem ) ) {
9728					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9729					// isn't a whole lot we can do. See pull request at this URL for discussion:
9730					// https://github.com/jquery/jquery/pull/764
9731					return elem.document.documentElement[ "client" + name ];
9732				}
9733
9734				// Get document width or height
9735				if ( elem.nodeType === 9 ) {
9736					doc = elem.documentElement;
9737
9738					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
9739					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
9740					return Math.max(
9741						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9742						elem.body[ "offset" + name ], doc[ "offset" + name ],
9743						doc[ "client" + name ]
9744					);
9745				}
9746
9747				return value === undefined ?
9748					// Get width or height on the element, requesting but not forcing parseFloat
9749					jQuery.css( elem, type, extra ) :
9750
9751					// Set width or height on the element
9752					jQuery.style( elem, type, value, extra );
9753			}, type, chainable ? margin : undefined, chainable, null );
9754		};
9755	});
9756});
9757// Limit scope pollution from any deprecated API
9758// (function() {
9759
9760// The number of elements contained in the matched element set
9761jQuery.fn.size = function() {
9762	return this.length;
9763};
9764
9765jQuery.fn.andSelf = jQuery.fn.addBack;
9766
9767// })();
9768if ( typeof module === "object" && module && typeof module.exports === "object" ) {
9769	// Expose jQuery as module.exports in loaders that implement the Node
9770	// module pattern (including browserify). Do not create the global, since
9771	// the user will be storing it themselves locally, and globals are frowned
9772	// upon in the Node module world.
9773	module.exports = jQuery;
9774} else {
9775	// Otherwise expose jQuery to the global object as usual
9776	window.jQuery = window.$ = jQuery;
9777
9778	// Register as a named AMD module, since jQuery can be concatenated with other
9779	// files that may use define, but not via a proper concatenation script that
9780	// understands anonymous AMD modules. A named AMD is safest and most robust
9781	// way to register. Lowercase jquery is used because AMD module names are
9782	// derived from file names, and jQuery is normally delivered in a lowercase
9783	// file name. Do this after creating the global so that if an AMD module wants
9784	// to call noConflict to hide this version of jQuery, it will work.
9785	if ( typeof define === "function" && define.amd ) {
9786		define( "jquery", [], function () { return jQuery; } );
9787	}
9788}
9789
9790})( window );
9791/*
9792 * Hisrc jQuery Plugin
9793 *
9794 * Copyright (c) 2012
9795 * Licensed under the MIT license.
9796 *
9797 */
9798
9799
9800(function($){
9801	$.hisrc = {
9802		bandwidth: null,
9803		connectionTestResult: null,
9804		connectionKbps: null,
9805		connectionType: null,
9806		devicePixelRatio: null
9807	};
9808
9809	$.hisrc.defaults = {
9810		useTransparentGif: false,
9811		transparentGifSrc: 'data:image/gif;base64,R0lGODlhAQABAIAAAMz/AAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
9812		minKbpsForHighBandwidth: 300,
9813		speedTestUri: 'https://<use-your-own-domain>.com/put-a-50K-file-here/50K',
9814		speedTestKB: 50,
9815		speedTestExpireMinutes: 30,
9816		forcedBandwidth: false
9817	};
9818
9819	// for performance, run this right away (requires jQuery, but no need to wait for DOM to be ready)
9820	$.hisrc.speedTest = function() {
9821		$(window).hisrc();
9822	};
9823
9824	$.fn.hisrc = function(options) {
9825		var settings = $.extend({}, $.hisrc.defaults, options),
9826
9827			$els = $(this),
9828
9829			// check bandwidth via @Modernizr's network-connection.js
9830			connection = navigator.connection || { type: 0 }, // polyfill
9831
9832			isSlowConnection = connection.type == 3
9833								|| connection.type == 4
9834								|| /^[23]g$/.test(connection.type);
9835
9836
9837		// get pixel ratio
9838		$.hisrc.devicePixelRatio = 1;
9839		if(window.devicePixelRatio !== undefined) { $.hisrc.devicePixelRatio = window.devicePixelRatio; }
9840
9841
9842		// variables/functions below for speed test are taken from Foresight.js
9843		// Copyright (c) 2012 Adam Bradley
9844		// Licensed under the MIT license.
9845		// https://github.com/adamdbradley/foresight.js
9846		// Modified by Christopher Deutsch for hisrc.js
9847		var speedTestUri = settings.speedTestUri,
9848			STATUS_LOADING = 'loading',
9849			STATUS_COMPLETE = 'complete',
9850			LOCAL_STORAGE_KEY = 'fsjs', // may as well piggy-back on Forsight localstorage key since we're doing the same thing.
9851			speedConnectionStatus,
9852
9853			initSpeedTest = function () {
9854
9855				// only check the connection speed once, if there is a status then we've
9856				// already got info or it already started
9857				if ( speedConnectionStatus ) {
9858					return;
9859				}
9860
9861				// force that this device has a low or high bandwidth, used more so for debugging purposes
9862				if ( settings.forcedBandwidth ) {
9863					$.hisrc.bandwidth = settings.forcedBandwidth;
9864					$.hisrc.connectionTestResult = 'forced';
9865					speedConnectionStatus = STATUS_COMPLETE;
9866					$els.trigger('speedTestComplete.hisrc');
9867					return;
9868				}
9869
9870				// if the device pixel ratio is 1, then no need to do a network connection
9871				// speed test since it can't show hi-res anyways
9872				if ( $.hisrc.devicePixelRatio === 1 ) {
9873					$.hisrc.connectionTestResult = 'skip';
9874					speedConnectionStatus = STATUS_COMPLETE;
9875					$els.trigger('speedTestComplete.hisrc');
9876					return;
9877				}
9878
9879				// if we know the connection is 2g or 3g
9880				// don't even bother with the speed test, cuz its slow
9881				// Copyright (c) Faruk Ates, Paul Irish, Alex Sexton
9882				// Available under the BSD and MIT licenses: www.modernizr.com/license/
9883				// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/network-connection.js
9884				// Modified by Adam Bradley for Foresight.js
9885				$.hisrc.connectionType = connection.type;
9886				if ( isSlowConnection ) {
9887					// we know this connection is slow, don't bother even doing a speed test
9888					$.hisrc.connectionTestResult = 'connTypeSlow';
9889					speedConnectionStatus = STATUS_COMPLETE;
9890					$els.trigger('speedTestComplete.hisrc');
9891					return;
9892				}
9893
9894				// check if a speed test has recently been completed and its
9895				// results are saved in the local storage
9896				try {
9897					var fsData = JSON.parse( localStorage.getItem( LOCAL_STORAGE_KEY ) );
9898					if ( fsData !== null ) {
9899						if ( ( new Date() ).getTime() < fsData.exp ) {
9900							// already have connection data within our desired timeframe
9901							// use this recent data instead of starting another test
9902							$.hisrc.bandwidth = fsData.bw;
9903							$.hisrc.connectionKbps = fsData.kbps;
9904							$.hisrc.connectionTestResult = 'localStorage';
9905							speedConnectionStatus = STATUS_COMPLETE;
9906							$els.trigger('speedTestComplete.hisrc');
9907							return;
9908						}
9909					}
9910				} catch( e ) { }
9911
9912				var
9913				speedTestImg = document.createElement( 'img' ),
9914				endTime,
9915				startTime,
9916				speedTestTimeoutMS;
9917
9918				speedTestImg.onload = function () {
9919					// speed test image download completed
9920					// figure out how long it took and an estimated connection speed
9921					endTime = ( new Date() ).getTime();
9922
9923					var duration = ( endTime - startTime ) / 1000;
9924					duration = ( duration > 1 ? duration : 1 ); // just to ensure we don't divide by 0
9925
9926					$.hisrc.connectionKbps = ( ( settings.speedTestKB * 1024 * 8 ) / duration ) / 1024;
9927					$.hisrc.bandwidth = ( $.hisrc.connectionKbps >= settings.minKbpsForHighBandwidth ? 'high' : 'low' );
9928
9929					speedTestComplete( 'networkSuccess' );
9930				};
9931
9932				speedTestImg.onerror = function () {
9933					// fallback incase there was an error downloading the speed test image
9934					speedTestComplete( 'networkError', 5 );
9935				};
9936
9937				speedTestImg.onabort = function () {
9938					// fallback incase there was an abort during the speed test image
9939					speedTestComplete( 'networkAbort', 5 );
9940				};
9941
9942				// begin the network connection speed test image download
9943				startTime = ( new Date() ).getTime();
9944				speedConnectionStatus = STATUS_LOADING;
9945				if ( document.location.protocol === 'https:' ) {
9946					// if this current document is SSL, make sure this speed test request
9947					// uses https so there are no ugly security warnings from the browser
9948					speedTestUri = speedTestUri.replace( 'http:', 'https:' );
9949				}
9950				speedTestImg.src = speedTestUri + "?r=" + Math.random();
9951
9952				// calculate the maximum number of milliseconds it 'should' take to download an XX Kbps file
9953				// set a timeout so that if the speed test download takes too long
9954				// than it isn't a 'high-bandwidth' and ignore what the test image .onload has to say
9955				// this is used so we don't wait too long on a speed test response
9956				// Adding 350ms to account for TCP slow start, quickAndDirty === TRUE
9957				speedTestTimeoutMS = ( ( ( settings.speedTestKB * 8 ) / settings.minKbpsForHighBandwidth ) * 1000 ) + 350;
9958				setTimeout( function () {
9959					speedTestComplete( 'networkSlow' );
9960				}, speedTestTimeoutMS );
9961			},
9962
9963			speedTestComplete = function ( connTestResult, expireMinutes ) {
9964				// if we haven't already gotten a speed connection status then save the info
9965				if (speedConnectionStatus === STATUS_COMPLETE) { return; }
9966
9967				// first one with an answer wins
9968				speedConnectionStatus = STATUS_COMPLETE;
9969				$.hisrc.connectionTestResult = connTestResult;
9970
9971				try {
9972					if ( !expireMinutes ) {
9973						expireMinutes = settings.speedTestExpireMinutes;
9974					}
9975					var fsDataToSet = {
9976						kbps: $.hisrc.connectionKbps,
9977						bw: $.hisrc.bandwidth,
9978						exp: ( new Date() ).getTime() + (expireMinutes * 60000)
9979					};
9980					localStorage.setItem( LOCAL_STORAGE_KEY, JSON.stringify( fsDataToSet ) );
9981				} catch( e ) { }
9982
9983				// trigger swap once speedtest is complete.
9984				$els.trigger('speedTestComplete.hisrc');
9985			},
9986
9987			setImageSource = function ( $el, src ) {
9988				if ( settings.useTransparentGif ) {
9989					$el.attr('src', settings.transparentGifSrc)
9990						.css('max-height', '100%')
9991						.css('max-width', '100%')
9992						.css('background', 'url("' + src + '") no-repeat 0 0')
9993						.css('background-size', 'contain');
9994				} else {
9995					$el.attr( 'src', src );
9996				}
9997			};
9998
9999		$els.each(function(){
10000			var $el = $(this);
10001
10002			if (!$el.data('m1src')) {
10003				$el.data('m1src', $el.attr('src'));
10004			}
10005
10006			// check for zero which often happens in safari.
10007			if (!$el.attr('width') &&  $el.width() > 0) {
10008				$el.attr('width', $el.width());
10009			}
10010			if (!$el.attr('height') &&  $el.height() > 0) {
10011				$el.attr('height', $el.height());
10012			}
10013
10014			$el.on('speedTestComplete.hisrc', function(){
10015
10016				if (speedConnectionStatus === STATUS_COMPLETE) {
10017
10018					if (isSlowConnection) {
10019						$el.attr( 'src', $el.data('m1src') );
10020					} else {
10021
10022						// check if client can get high res image
10023						if ($.hisrc.devicePixelRatio > 1 && $.hisrc.bandwidth === 'high') {
10024							setImageSource( $el, $el.data('2x') );
10025						} else {
10026							setImageSource( $el, $el.data('1x') );
10027						}
10028					}
10029					// turn off so hisrc() can be called many times on same element.
10030					$el.off('speedTestComplete.hisrc');
10031				}
10032
10033			});
10034		});
10035
10036		initSpeedTest();
10037
10038		return $els;
10039	};
10040
10041})(jQuery);
10042
10043
10044// Underscore.js 1.4.4
10045// ===================
10046
10047// > http://underscorejs.org
10048// >
10048 (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
10049// > Underscore may be freely distributed under the MIT license.
10050
10051// Baseline setup
10052// --------------
10053(function() {
10054
10055  // Establish the root object, `window` in the browser, or `global` on the server.
10056  var root = this;
10057
10058  // Save the previous value of the `_` variable.
10059  var previousUnderscore = root._;
10060
10061  // Establish the object that gets returned to break out of a loop iteration.
10062  var breaker = {};
10063
10064  // Save bytes in the minified (but not gzipped) version:
10065  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
10066
10067  // Create quick reference variables for speed access to core prototypes.
10068  var push             = ArrayProto.push,
10069      slice            = ArrayProto.slice,
10070      concat           = ArrayProto.concat,
10071      toString         = ObjProto.toString,
10072      hasOwnProperty   = ObjProto.hasOwnProperty;
10073
10074  // All **ECMAScript 5** native function implementations that we hope to use
10075  // are declared here.
10076  var
10077    nativeForEach      = ArrayProto.forEach,
10078    nativeMap          = ArrayProto.map,
10079    nativeReduce       = ArrayProto.reduce,
10080    nativeReduceRight  = ArrayProto.reduceRight,
10081    nativeFilter       = ArrayProto.filter,
10082    nativeEvery        = ArrayProto.every,
10083    nativeSome         = ArrayProto.some,
10084    nativeIndexOf      = ArrayProto.indexOf,
10085    nativeLastIndexOf  = ArrayProto.lastIndexOf,
10086    nativeIsArray      = Array.isArray,
10087    nativeKeys         = Object.keys,
10088    nativeBind         = FuncProto.bind;
10089
10090  // Create a safe reference to the Underscore object for use below.
10091  var _ = function(obj) {
10092    if (obj instanceof _) return obj;
10093    if (!(this instanceof _)) return new _(obj);
10094    this._wrapped = obj;
10095  };
10096
10097  // Export the Underscore object for **Node.js**, with
10098  // backwards-compatibility for the old `require()` API. If we're in
10099  // the browser, add `_` as a global object via a string identifier,
10100  // for Closure Compiler "advanced" mode.
10101  if (typeof exports !== 'undefined') {
10102    if (typeof module !== 'undefined' && module.exports) {
10103      exports = module.exports = _;
10104    }
10105    exports._ = _;
10106  } else {
10107    root._ = _;
10108  }
10109
10110  // Current version.
10111  _.VERSION = '1.4.4';
10112
10113  // Collection Functions
10114  // --------------------
10115
10116  // The cornerstone, an `each` implementation, aka `forEach`.
10117  // Handles objects with the built-in `forEach`, arrays, and raw objects.
10118  // Delegates to **ECMAScript 5**'s native `forEach` if available.
10119  var each = _.each = _.forEach = function(obj, iterator, context) {
10120    if (obj == null) return;
10121    if (nativeForEach && obj.forEach === nativeForEach) {
10122      obj.forEach(iterator, context);
10123    } else if (obj.length === +obj.length) {
10124      for (var i = 0, l = obj.length; i < l; i++) {
10125        if (iterator.call(context, obj[i], i, obj) === breaker) return;
10126      }
10127    } else {
10128      for (var key in obj) {
10129        if (_.has(obj, key)) {
10130          if (iterator.call(context, obj[key], key, obj) === breaker) return;
10131        }
10132      }
10133    }
10134  };
10135
10136  // Return the results of applying the iterator to each element.
10137  // Delegates to **ECMAScript 5**'s native `map` if available.
10138  _.map = _.collect = function(obj, iterator, context) {
10139    var results = [];
10140    if (obj == null) return results;
10141    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
10142    each(obj, function(value, index, list) {
10143      results[results.length] = iterator.call(context, value, index, list);
10144    });
10145    return results;
10146  };
10147
10148  var reduceError = 'Reduce of empty array with no initial value';
10149
10150  // **Reduce** builds up a single result from a list of values, aka `inject`,
10151  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
10152  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
10153    var initial = arguments.length > 2;
10154    if (obj == null) obj = [];
10155    if (nativeReduce && obj.reduce === nativeReduce) {
10156      if (context) iterator = _.bind(iterator, context);
10157      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
10158    }
10159    each(obj, function(value, index, list) {
10160      if (!initial) {
10161        memo = value;
10162        initial = true;
10163      } else {
10164        memo = iterator.call(context, memo, value, index, list);
10165      }
10166    });
10167    if (!initial) throw new TypeError(reduceError);
10168    return memo;
10169  };
10170
10171  // The right-associative version of reduce, also known as `foldr`.
10172  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
10173  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
10174    var initial = arguments.length > 2;
10175    if (obj == null) obj = [];
10176    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
10177      if (context) iterator = _.bind(iterator, context);
10178      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
10179    }
10180    var length = obj.length;
10181    if (length !== +length) {
10182      var keys = _.keys(obj);
10183      length = keys.length;
10184    }
10185    each(obj, function(value, index, list) {
10186      index = keys ? keys[--length] : --length;
10187      if (!initial) {
10188        memo = obj[index];
10189        initial = true;
10190      } else {
10191        memo = iterator.call(context, memo, obj[index], index, list);
10192      }
10193    });
10194    if (!initial) throw new TypeError(reduceError);
10195    return memo;
10196  };
10197
10198  // Return the first value which passes a truth test. Aliased as `detect`.
10199  _.find = _.detect = function(obj, iterator, context) {
10200    var result;
10201    any(obj, function(value, index, list) {
10202      if (iterator.call(context, value, index, list)) {
10203        result = value;
10204        return true;
10205      }
10206    });
10207    return result;
10208  };
10209
10210  // Return all the elements that pass a truth test.
10211  // Delegates to **ECMAScript 5**'s native `filter` if available.
10212  // Aliased as `select`.
10213  _.filter = _.select = function(obj, iterator, context) {
10214    var results = [];
10215    if (obj == null) return results;
10216    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
10217    each(obj, function(value, index, list) {
10218      if (iterator.call(context, value, index, list)) results[results.length] = value;
10219    });
10220    return results;
10221  };
10222
10223  // Return all the elements for which a truth test fails.
10224  _.reject = function(obj, iterator, context) {
10225    return _.filter(obj, function(value, index, list) {
10226      return !iterator.call(context, value, index, list);
10227    }, context);
10228  };
10229
10230  // Determine whether all of the elements match a truth test.
10231  // Delegates to **ECMAScript 5**'s native `every` if available.
10232  // Aliased as `all`.
10233  _.every = _.all = function(obj, iterator, context) {
10234    iterator || (iterator = _.identity);
10235    var result = true;
10236    if (obj == null) return result;
10237    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
10238    each(obj, function(value, index, list) {
10239      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
10240    });
10241    return !!result;
10242  };
10243
10244  // Determine if at least one element in the object matches a truth test.
10245  // Delegates to **ECMAScript 5**'s native `some` if available.
10246  // Aliased as `any`.
10247  var any = _.some = _.any = function(obj, iterator, context) {
10248    iterator || (iterator = _.identity);
10249    var result = false;
10250    if (obj == null) return result;
10251    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
10252    each(obj, function(value, index, list) {
10253      if (result || (result = iterator.call(context, value, index, list))) return breaker;
10254    });
10255    return !!result;
10256  };
10257
10258  // Determine if the array or object contains a given value (using `===`).
10259  // Aliased as `include`.
10260  _.contains = _.include = function(obj, target) {
10261    if (obj == null) return false;
10262    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
10263    return any(obj, function(value) {
10264      return value === target;
10265    });
10266  };
10267
10268  // Invoke a method (with arguments) on every item in a collection.
10269  _.invoke = function(obj, method) {
10270    var args = slice.call(arguments, 2);
10271    var isFunc = _.isFunction(method);
10272    return _.map(obj, function(value) {
10273      return (isFunc ? method : value[method]).apply(value, args);
10274    });
10275  };
10276
10277  // Convenience version of a common use case of `map`: fetching a property.
10278  _.pluck = function(obj, key) {
10279    return _.map(obj, function(value){ return value[key]; });
10280  };
10281
10282  // Convenience version of a common use case of `filter`: selecting only objects
10283  // containing specific `key:value` pairs.
10284  _.where = function(obj, attrs, first) {
10285    if (_.isEmpty(attrs)) return first ? null : [];
10286    return _[first ? 'find' : 'filter'](obj, function(value) {
10287      for (var key in attrs) {
10288        if (attrs[key] !== value[key]) return false;
10289      }
10290      return true;
10291    });
10292  };
10293
10294  // Convenience version of a common use case of `find`: getting the first object
10295  // containing specific `key:value` pairs.
10296  _.findWhere = function(obj, attrs) {
10297    return _.where(obj, attrs, true);
10298  };
10299
10300  // Return the maximum element or (element-based computation).
10301  // Can't optimize arrays of integers longer than 65,535 elements.
10302  // See: https://bugs.webkit.org/show_bug.cgi?id=80797
10303  _.max = function(obj, iterator, context) {
10304    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
10305      return Math.max.apply(Math, obj);
10306    }
10307    if (!iterator && _.isEmpty(obj)) return -Infinity;
10308    var result = {computed : -Infinity, value: -Infinity};
10309    each(obj, function(value, index, list) {
10310      var computed = iterator ? iterator.call(context, value, index, list) : value;
10311      computed >= result.computed && (result = {value : value, computed : computed});
10312    });
10313    return result.value;
10314  };
10315
10316  // Return the minimum element (or element-based computation).
10317  _.min = function(obj, iterator, context) {
10318    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
10319      return Math.min.apply(Math, obj);
10320    }
10321    if (!iterator && _.isEmpty(obj)) return Infinity;
10322    var result = {computed : Infinity, value: Infinity};
10323    each(obj, function(value, index, list) {
10324      var computed = iterator ? iterator.call(context, value, index, list) : value;
10325      computed < result.computed && (result = {value : value, computed : computed});
10326    });
10327    return result.value;
10328  };
10329
10330  // Shuffle an array.
10331  _.shuffle = function(obj) {
10332    var rand;
10333    var index = 0;
10334    var shuffled = [];
10335    each(obj, function(value) {
10336      rand = _.random(index++);
10337      shuffled[index - 1] = shuffled[rand];
10338      shuffled[rand] = value;
10339    });
10340    return shuffled;
10341  };
10342
10343  // An internal function to generate lookup iterators.
10344  var lookupIterator = function(value) {
10345    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
10346  };
10347
10348  // Sort the object's values by a criterion produced by an iterator.
10349  _.sortBy = function(obj, value, context) {
10350    var iterator = lookupIterator(value);
10351    return _.pluck(_.map(obj, function(value, index, list) {
10352      return {
10353        value : value,
10354        index : index,
10355        criteria : iterator.call(context, value, index, list)
10356      };
10357    }).sort(function(left, right) {
10358      var a = left.criteria;
10359      var b = right.criteria;
10360      if (a !== b) {
10361        if (a > b || a === void 0) return 1;
10362        if (a < b || b === void 0) return -1;
10363      }
10364      return left.index < right.index ? -1 : 1;
10365    }), 'value');
10366  };
10367
10368  // An internal function used for aggregate "group by" operations.
10369  var group = function(obj, value, context, behavior) {
10370    var result = {};
10371    var iterator = lookupIterator(value || _.identity);
10372    each(obj, function(value, index) {
10373      var key = iterator.call(context, value, index, obj);
10374      behavior(result, key, value);
10375    });
10376    return result;
10377  };
10378
10379  // Groups the object's values by a criterion. Pass either a string attribute
10380  // to group by, or a function that returns the criterion.
10381  _.groupBy = function(obj, value, context) {
10382    return group(obj, value, context, function(result, key, value) {
10383      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
10384    });
10385  };
10386
10387  // Counts instances of an object that group by a certain criterion. Pass
10388  // either a string attribute to count by, or a function that returns the
10389  // criterion.
10390  _.countBy = function(obj, value, context) {
10391    return group(obj, value, context, function(result, key) {
10392      if (!_.has(result, key)) result[key] = 0;
10393      result[key]++;
10394    });
10395  };
10396
10397  // Use a comparator function to figure out the smallest index at which
10398  // an object should be inserted so as to maintain order. Uses binary search.
10399  _.sortedIndex = function(array, obj, iterator, context) {
10400    iterator = iterator == null ? _.identity : lookupIterator(iterator);
10401    var value = iterator.call(context, obj);
10402    var low = 0, high = array.length;
10403    while (low < high) {
10404      var mid = (low + high) >>> 1;
10405      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
10406    }
10407    return low;
10408  };
10409
10410  // Safely convert anything iterable into a real, live array.
10411  _.toArray = function(obj) {
10412    if (!obj) return [];
10413    if (_.isArray(obj)) return slice.call(obj);
10414    if (obj.length === +obj.length) return _.map(obj, _.identity);
10415    return _.values(obj);
10416  };
10417
10418  // Return the number of elements in an object.
10419  _.size = function(obj) {
10420    if (obj == null) return 0;
10421    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
10422  };
10423
10424  // Array Functions
10425  // ---------------
10426
10427  // Get the first element of an array. Passing **n** will return the first N
10428  // values in the array. Aliased as `head` and `take`. The **guard** check
10429  // allows it to work with `_.map`.
10430  _.first = _.head = _.take = function(array, n, guard) {
10431    if (array == null) return void 0;
10432    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
10433  };
10434
10435  // Returns everything but the last entry of the array. Especially useful on
10436  // the arguments object. Passing **n** will return all the values in
10437  // the array, excluding the last N. The **guard** check allows it to work with
10438  // `_.map`.
10439  _.initial = function(array, n, guard) {
10440    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
10441  };
10442
10443  // Get the last element of an array. Passing **n** will return the last N
10444  // values in the array. The **guard** check allows it to work with `_.map`.
10445  _.last = function(array, n, guard) {
10446    if (array == null) return void 0;
10447    if ((n != null) && !guard) {
10448      return slice.call(array, Math.max(array.length - n, 0));
10449    } else {
10450      return array[array.length - 1];
10451    }
10452  };
10453
10454  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
10455  // Especially useful on the arguments object. Passing an **n** will return
10456  // the rest N values in the array. The **guard**
10457  // check allows it to work with `_.map`.
10458  _.rest = _.tail = _.drop = function(array, n, guard) {
10459    return slice.call(array, (n == null) || guard ? 1 : n);
10460  };
10461
10462  // Trim out all falsy values from an array.
10463  _.compact = function(array) {
10464    return _.filter(array, _.identity);
10465  };
10466
10467  // Internal implementation of a recursive `flatten` function.
10468  var flatten = function(input, shallow, output) {
10469    each(input, function(value) {
10470      if (_.isArray(value)) {
10471        shallow ? push.apply(output, value) : flatten(value, shallow, output);
10472      } else {
10473        output.push(value);
10474      }
10475    });
10476    return output;
10477  };
10478
10479  // Return a completely flattened version of an array.
10480  _.flatten = function(array, shallow) {
10481    return flatten(array, shallow, []);
10482  };
10483
10484  // Return a version of the array that does not contain the specified value(s).
10485  _.without = function(array) {
10486    return _.difference(array, slice.call(arguments, 1));
10487  };
10488
10489  // Produce a duplicate-free version of the array. If the array has already
10490  // been sorted, you have the option of using a faster algorithm.
10491  // Aliased as `unique`.
10492  _.uniq = _.unique = function(array, isSorted, iterator, context) {
10493    if (_.isFunction(isSorted)) {
10494      context = iterator;
10495      iterator = isSorted;
10496      isSorted = false;
10497    }
10498    var initial = iterator ? _.map(array, iterator, context) : array;
10499    var results = [];
10500    var seen = [];
10501    each(initial, function(value, index) {
10502      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
10503        seen.push(value);
10504        results.push(array[index]);
10505      }
10506    });
10507    return results;
10508  };
10509
10510  // Produce an array that contains the union: each distinct element from all of
10511  // the passed-in arrays.
10512  _.union = function() {
10513    return _.uniq(concat.apply(ArrayProto, arguments));
10514  };
10515
10516  // Produce an array that contains every item shared between all the
10517  // passed-in arrays.
10518  _.intersection = function(array) {
10519    var rest = slice.call(arguments, 1);
10520    return _.filter(_.uniq(array), function(item) {
10521      return _.every(rest, function(other) {
10522        return _.indexOf(other, item) >= 0;
10523      });
10524    });
10525  };
10526
10527  // Take the difference between one array and a number of other arrays.
10528  // Only the elements present in just the first array will remain.
10529  _.difference = function(array) {
10530    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
10531    return _.filter(array, function(value){ return !_.contains(rest, value); });
10532  };
10533
10534  // Zip together multiple lists into a single array -- elements that share
10535  // an index go together.
10536  _.zip = function() {
10537    var args = slice.call(arguments);
10538    var length = _.max(_.pluck(args, 'length'));
10539    var results = new Array(length);
10540    for (var i = 0; i < length; i++) {
10541      results[i] = _.pluck(args, "" + i);
10542    }
10543    return results;
10544  };
10545
10546  // Converts lists into objects. Pass either a single array of `[key, value]`
10547  // pairs, or two parallel arrays of the same length -- one of keys, and one of
10548  // the corresponding values.
10549  _.object = function(list, values) {
10550    if (list == null) return {};
10551    var result = {};
10552    for (var i = 0, l = list.length; i < l; i++) {
10553      if (values) {
10554        result[list[i]] = values[i];
10555      } else {
10556        result[list[i][0]] = list[i][1];
10557      }
10558    }
10559    return result;
10560  };
10561
10562  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
10563  // we need this function. Return the position of the first occurrence of an
10564  // item in an array, or -1 if the item is not included in the array.
10565  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
10566  // If the array is large and already in sort order, pass `true`
10567  // for **isSorted** to use binary search.
10568  _.indexOf = function(array, item, isSorted) {
10569    if (array == null) return -1;
10570    var i = 0, l = array.length;
10571    if (isSorted) {
10572      if (typeof isSorted == 'number') {
10573        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
10574      } else {
10575        i = _.sortedIndex(array, item);
10576        return array[i] === item ? i : -1;
10577      }
10578    }
10579    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
10580    for (; i < l; i++) if (array[i] === item) return i;
10581    return -1;
10582  };
10583
10584  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
10585  _.lastIndexOf = function(array, item, from) {
10586    if (array == null) return -1;
10587    var hasIndex = from != null;
10588    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
10589      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
10590    }
10591    var i = (hasIndex ? from : array.length);
10592    while (i--) if (array[i] === item) return i;
10593    return -1;
10594  };
10595
10596  // Generate an integer Array containing an arithmetic progression. A port of
10597  // the native Python `range()` function. See
10598  // [the Python documentation](http://docs.python.org/library/functions.html#range).
10599  _.range = function(start, stop, step) {
10600    if (arguments.length <= 1) {
10601      stop = start || 0;
10602      start = 0;
10603    }
10604    step = arguments[2] || 1;
10605
10606    var len = Math.max(Math.ceil((stop - start) / step), 0);
10607    var idx = 0;
10608    var range = new Array(len);
10609
10610    while(idx < len) {
10611      range[idx++] = start;
10612      start += step;
10613    }
10614
10615    return range;
10616  };
10617
10618  // Function (ahem) Functions
10619  // ------------------
10620
10621  // Create a function bound to a given object (assigning `this`, and arguments,
10622  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
10623  // available.
10624  _.bind = function(func, context) {
10625    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
10626    var args = slice.call(arguments, 2);
10627    return function() {
10628      return func.apply(context, args.concat(slice.call(arguments)));
10629    };
10630  };
10631
10632  // Partially apply a function by creating a version that has had some of its
10633  // arguments pre-filled, without changing its dynamic `this` context.
10634  _.partial = function(func) {
10635    var args = slice.call(arguments, 1);
10636    return function() {
10637      return func.apply(this, args.concat(slice.call(arguments)));
10638    };
10639  };
10640
10641  // Bind all of an object's methods to that object. Useful for ensuring that
10642  // all callbacks defined on an object belong to it.
10643  _.bindAll = function(obj) {
10644    var funcs = slice.call(arguments, 1);
10645    if (funcs.length === 0) funcs = _.functions(obj);
10646    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
10647    return obj;
10648  };
10649
10650  // Memoize an expensive function by storing its results.
10651  _.memoize = function(func, hasher) {
10652    var memo = {};
10653    hasher || (hasher = _.identity);
10654    return function() {
10655      var key = hasher.apply(this, arguments);
10656      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
10657    };
10658  };
10659
10660  // Delays a function for the given number of milliseconds, and then calls
10661  // it with the arguments supplied.
10662  _.delay = function(func, wait) {
10663    var args = slice.call(arguments, 2);
10664    return setTimeout(function(){ return func.apply(null, args); }, wait);
10665  };
10666
10667  // Defers a function, scheduling it to run after the current call stack has
10668  // cleared.
10669  _.defer = function(func) {
10670    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
10671  };
10672
10673  // Returns a function, that, when invoked, will only be triggered at most once
10674  // during a given window of time.
10675  _.throttle = function(func, wait) {
10676    var context, args, timeout, result;
10677    var previous = 0;
10678    var later = function() {
10679      previous = new Date;
10680      timeout = null;
10681      result = func.apply(context, args);
10682    };
10683    return function() {
10684      var now = new Date;
10685      var remaining = wait - (now - previous);
10686      context = this;
10687      args = arguments;
10688      if (remaining <= 0) {
10689        clearTimeout(timeout);
10690        timeout = null;
10691        previous = now;
10692        result = func.apply(context, args);
10693      } else if (!timeout) {
10694        timeout = setTimeout(later, remaining);
10695      }
10696      return result;
10697    };
10698  };
10699
10700  // Returns a function, that, as long as it continues to be invoked, will not
10701  // be triggered. The function will be called after it stops being called for
10702  // N milliseconds. If `immediate` is passed, trigger the function on the
10703  // leading edge, instead of the trailing.
10704  _.debounce = function(func, wait, immediate) {
10705    var timeout, result;
10706    return function() {
10707      var context = this, args = arguments;
10708      var later = function() {
10709        timeout = null;
10710        if (!immediate) result = func.apply(context, args);
10711      };
10712      var callNow = immediate && !timeout;
10713      clearTimeout(timeout);
10714      timeout = setTimeout(later, wait);
10715      if (callNow) result = func.apply(context, args);
10716      return result;
10717    };
10718  };
10719
10720  // Returns a function that will be executed at most one time, no matter how
10721  // often you call it. Useful for lazy initialization.
10722  _.once = function(func) {
10723    var ran = false, memo;
10724    return function() {
10725      if (ran) return memo;
10726      ran = true;
10727      memo = func.apply(this, arguments);
10728      func = null;
10729      return memo;
10730    };
10731  };
10732
10733  // Returns the first function passed as an argument to the second,
10734  // allowing you to adjust arguments, run code before and after, and
10735  // conditionally execute the original function.
10736  _.wrap = function(func, wrapper) {
10737    return function() {
10738      var args = [func];
10739      push.apply(args, arguments);
10740      return wrapper.apply(this, args);
10741    };
10742  };
10743
10744  // Returns a function that is the composition of a list of functions, each
10745  // consuming the return value of the function that follows.
10746  _.compose = function() {
10747    var funcs = arguments;
10748    return function() {
10749      var args = arguments;
10750      for (var i = funcs.length - 1; i >= 0; i--) {
10751        args = [funcs[i].apply(this, args)];
10752      }
10753      return args[0];
10754    };
10755  };
10756
10757  // Returns a function that will only be executed after being called N times.
10758  _.after = function(times, func) {
10759    if (times <= 0) return func();
10760    return function() {
10761      if (--times < 1) {
10762        return func.apply(this, arguments);
10763      }
10764    };
10765  };
10766
10767  // Object Functions
10768  // ----------------
10769
10770  // Retrieve the names of an object's properties.
10771  // Delegates to **ECMAScript 5**'s native `Object.keys`
10772  _.keys = nativeKeys || function(obj) {
10773    if (obj !== Object(obj)) throw new TypeError('Invalid object');
10774    var keys = [];
10775    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
10776    return keys;
10777  };
10778
10779  // Retrieve the values of an object's properties.
10780  _.values = function(obj) {
10781    var values = [];
10782    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
10783    return values;
10784  };
10785
10786  // Convert an object into a list of `[key, value]` pairs.
10787  _.pairs = function(obj) {
10788    var pairs = [];
10789    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
10790    return pairs;
10791  };
10792
10793  // Invert the keys and values of an object. The values must be serializable.
10794  _.invert = function(obj) {
10795    var result = {};
10796    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
10797    return result;
10798  };
10799
10800  // Return a sorted list of the function names available on the object.
10801  // Aliased as `methods`
10802  _.functions = _.methods = function(obj) {
10803    var names = [];
10804    for (var key in obj) {
10805      if (_.isFunction(obj[key])) names.push(key);
10806    }
10807    return names.sort();
10808  };
10809
10810  // Extend a given object with all the properties in passed-in object(s).
10811  _.extend = function(obj) {
10812    each(slice.call(arguments, 1), function(source) {
10813      if (source) {
10814        for (var prop in source) {
10815          obj[prop] = source[prop];
10816        }
10817      }
10818    });
10819    return obj;
10820  };
10821
10822  // Return a copy of the object only containing the whitelisted properties.
10823  _.pick = function(obj) {
10824    var copy = {};
10825    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
10826    each(keys, function(key) {
10827      if (key in obj) copy[key] = obj[key];
10828    });
10829    return copy;
10830  };
10831
10832   // Return a copy of the object without the blacklisted properties.
10833  _.omit = function(obj) {
10834    var copy = {};
10835    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
10836    for (var key in obj) {
10837      if (!_.contains(keys, key)) copy[key] = obj[key];
10838    }
10839    return copy;
10840  };
10841
10842  // Fill in a given object with default properties.
10843  _.defaults = function(obj) {
10844    each(slice.call(arguments, 1), function(source) {
10845      if (source) {
10846        for (var prop in source) {
10847          if (obj[prop] == null) obj[prop] = source[prop];
10848        }
10849      }
10850    });
10851    return obj;
10852  };
10853
10854  // Create a (shallow-cloned) duplicate of an object.
10855  _.clone = function(obj) {
10856    if (!_.isObject(obj)) return obj;
10857    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
10858  };
10859
10860  // Invokes interceptor with the obj, and then returns obj.
10861  // The primary purpose of this method is to "tap into" a method chain, in
10862  // order to perform operations on intermediate results within the chain.
10863  _.tap = function(obj, interceptor) {
10864    interceptor(obj);
10865    return obj;
10866  };
10867
10868  // Internal recursive comparison function for `isEqual`.
10869  var eq = function(a, b, aStack, bStack) {
10870    // Identical objects are equal. `0 === -0`, but they aren't identical.
10871    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
10872    if (a === b) return a !== 0 || 1 / a == 1 / b;
10873    // A strict comparison is necessary because `null == undefined`.
10874    if (a == null || b == null) return a === b;
10875    // Unwrap any wrapped objects.
10876    if (a instanceof _) a = a._wrapped;
10877    if (b instanceof _) b = b._wrapped;
10878    // Compare `[[Class]]` names.
10879    var className = toString.call(a);
10880    if (className != toString.call(b)) return false;
10881    switch (className) {
10882      // Strings, numbers, dates, and booleans are compared by value.
10883      case '[object String]':
10884        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
10885        // equivalent to `new String("5")`.
10886        return a == String(b);
10887      case '[object Number]':
10888        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
10889        // other numeric values.
10890        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
10891      case '[object Date]':
10892      case '[object Boolean]':
10893        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
10894        // millisecond representations. Note that invalid dates with millisecond representations
10895        // of `NaN` are not equivalent.
10896        return +a == +b;
10897      // RegExps are compared by their source patterns and flags.
10898      case '[object RegExp]':
10899        return a.source == b.source &&
10900               a.global == b.global &&
10901               a.multiline == b.multiline &&
10902               a.ignoreCase == b.ignoreCase;
10903    }
10904    if (typeof a != 'object' || typeof b != 'object') return false;
10905    // Assume equality for cyclic structures. The algorithm for detecting cyclic
10906    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
10907    var length = aStack.length;
10908    while (length--) {
10909      // Linear search. Performance is inversely proportional to the number of
10910      // unique nested structures.
10911      if (aStack[length] == a) return bStack[length] == b;
10912    }
10913    // Add the first object to the stack of traversed objects.
10914    aStack.push(a);
10915    bStack.push(b);
10916    var size = 0, result = true;
10917    // Recursively compare objects and arrays.
10918    if (className == '[object Array]') {
10919      // Compare array lengths to determine if a deep comparison is necessary.
10920      size = a.length;
10921      result = size == b.length;
10922      if (result) {
10923        // Deep compare the contents, ignoring non-numeric properties.
10924        while (size--) {
10925          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
10926        }
10927      }
10928    } else {
10929      // Objects with different constructors are not equivalent, but `Object`s
10930      // from different frames are.
10931      var aCtor = a.constructor, bCtor = b.constructor;
10932      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
10933                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
10934        return false;
10935      }
10936      // Deep compare objects.
10937      for (var key in a) {
10938        if (_.has(a, key)) {
10939          // Count the expected number of properties.
10940          size++;
10941          // Deep compare each member.
10942          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
10943        }
10944      }
10945      // Ensure that both objects contain the same number of properties.
10946      if (result) {
10947        for (key in b) {
10948          if (_.has(b, key) && !(size--)) break;
10949        }
10950        result = !size;
10951      }
10952    }
10953    // Remove the first object from the stack of traversed objects.
10954    aStack.pop();
10955    bStack.pop();
10956    return result;
10957  };
10958
10959  // Perform a deep comparison to check if two objects are equal.
10960  _.isEqual = function(a, b) {
10961    return eq(a, b, [], []);
10962  };
10963
10964  // Is a given array, string, or object empty?
10965  // An "empty" object has no enumerable own-properties.
10966  _.isEmpty = function(obj) {
10967    if (obj == null) return true;
10968    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
10969    for (var key in obj) if (_.has(obj, key)) return false;
10970    return true;
10971  };
10972
10973  // Is a given value a DOM element?
10974  _.isElement = function(obj) {
10975    return !!(obj && obj.nodeType === 1);
10976  };
10977
10978  // Is a given value an array?
10979  // Delegates to ECMA5's native Array.isArray
10980  _.isArray = nativeIsArray || function(obj) {
10981    return toString.call(obj) == '[object Array]';
10982  };
10983
10984  // Is a given variable an object?
10985  _.isObject = function(obj) {
10986    return obj === Object(obj);
10987  };
10988
10989  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
10990  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
10991    _['is' + name] = function(obj) {
10992      return toString.call(obj) == '[object ' + name + ']';
10993    };
10994  });
10995
10996  // Define a fallback version of the method in browsers (ahem, IE), where
10997  // there isn't any inspectable "Arguments" type.
10998  if (!_.isArguments(arguments)) {
10999    _.isArguments = function(obj) {
11000      return !!(obj && _.has(obj, 'callee'));
11001    };
11002  }
11003
11004  // Optimize `isFunction` if appropriate.
11005  if (typeof (/./) !== 'function') {
11006    _.isFunction = function(obj) {
11007      return typeof obj === 'function';
11008    };
11009  }
11010
11011  // Is a given object a finite number?
11012  _.isFinite = function(obj) {
11013    return isFinite(obj) && !isNaN(parseFloat(obj));
11014  };
11015
11016  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
11017  _.isNaN = function(obj) {
11018    return _.isNumber(obj) && obj != +obj;
11019  };
11020
11021  // Is a given value a boolean?
11022  _.isBoolean = function(obj) {
11023    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
11024  };
11025
11026  // Is a given value equal to null?
11027  _.isNull = function(obj) {
11028    return obj === null;
11029  };
11030
11031  // Is a given variable undefined?
11032  _.isUndefined = function(obj) {
11033    return obj === void 0;
11034  };
11035
11036  // Shortcut function for checking if an object has a given property directly
11037  // on itself (in other words, not on a prototype).
11038  _.has = function(obj, key) {
11039    return hasOwnProperty.call(obj, key);
11040  };
11041
11042  // Utility Functions
11043  // -----------------
11044
11045  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
11046  // previous owner. Returns a reference to the Underscore object.
11047  _.noConflict = function() {
11048    root._ = previousUnderscore;
11049    return this;
11050  };
11051
11052  // Keep the identity function around for default iterators.
11053  _.identity = function(value) {
11054    return value;
11055  };
11056
11057  // Run a function **n** times.
11058  _.times = function(n, iterator, context) {
11059    var accum = Array(n);
11060    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
11061    return accum;
11062  };
11063
11064  // Return a random integer between min and max (inclusive).
11065  _.random = function(min, max) {
11066    if (max == null) {
11067      max = min;
11068      min = 0;
11069    }
11070    return min + Math.floor(Math.random() * (max - min + 1));
11071  };
11072
11073  // List of HTML entities for escaping.
11074  var entityMap = {
11075    escape: {
11076      '&': '&amp;',
11077      '<': '&lt;',
11078      '>': '&gt;',
11079      '"': '&quot;',
11080      "'": '&#x27;',
11081      '/': '&#x2F;'
11082    }
11083  };
11084  entityMap.unescape = _.invert(entityMap.escape);
11085
11086  // Regexes containing the keys and values listed immediately above.
11087  var entityRegexes = {
11088    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
11089    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
11090  };
11091
11092  // Functions for escaping and unescaping strings to/from HTML interpolation.
11093  _.each(['escape', 'unescape'], function(method) {
11094    _[method] = function(string) {
11095      if (string == null) return '';
11096      return ('' + string).replace(entityRegexes[method], function(match) {
11097        return entityMap[method][match];
11098      });
11099    };
11100  });
11101
11102  // If the value of the named property is a function then invoke it;
11103  // otherwise, return it.
11104  _.result = function(object, property) {
11105    if (object == null) return null;
11106    var value = object[property];
11107    return _.isFunction(value) ? value.call(object) : value;
11108  };
11109
11110  // Add your own custom functions to the Underscore object.
11111  _.mixin = function(obj) {
11112    each(_.functions(obj), function(name){
11113      var func = _[name] = obj[name];
11114      _.prototype[name] = function() {
11115        var args = [this._wrapped];
11116        push.apply(args, arguments);
11117        return result.call(this, func.apply(_, args));
11118      };
11119    });
11120  };
11121
11122  // Generate a unique integer id (unique within the entire client session).
11123  // Useful for temporary DOM ids.
11124  var idCounter = 0;
11125  _.uniqueId = function(prefix) {
11126    var id = ++idCounter + '';
11127    return prefix ? prefix + id : id;
11128  };
11129
11130  // By default, Underscore uses ERB-style template delimiters, change the
11131  // following template settings to use alternative delimiters.
11132  _.templateSettings = {
11133    evaluate    : /<%([\s\S]+?)%>/g,
11134    interpolate : /<%=([\s\S]+?)%>/g,
11135    escape      : /<%-([\s\S]+?)%>/g
11136  };
11137
11138  // When customizing `templateSettings`, if you don't want to define an
11139  // interpolation, evaluation or escaping regex, we need one that is
11140  // guaranteed not to match.
11141  var noMatch = /(.)^/;
11142
11143  // Certain characters need to be escaped so that they can be put into a
11144  // string literal.
11145  var escapes = {
11146    "'":      "'",
11147    '\\':     '\\',
11148    '\r':     'r',
11149    '\n':     'n',
11150    '\t':     't',
11151    '\u2028': 'u2028',
11152    '\u2029': 'u2029'
11153  };
11154
11155  var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
11156
11157  // JavaScript micro-templating, similar to John Resig's implementation.
11158  // Underscore templating handles arbitrary delimiters, preserves whitespace,
11159  // and correctly escapes quotes within interpolated code.
11160  _.template = function(text, data, settings) {
11161    var render;
11162    settings = _.defaults({}, settings, _.templateSettings);
11163
11164    // Combine delimiters into one regular expression via alternation.
11165    var matcher = new RegExp([
11166      (settings.escape || noMatch).source,
11167      (settings.interpolate || noMatch).source,
11168      (settings.evaluate || noMatch).source
11169    ].join('|') + '|$', 'g');
11170
11171    // Compile the template source, escaping string literals appropriately.
11172    var index = 0;
11173    var source = "__p+='";
11174    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
11175      source += text.slice(index, offset)
11176        .replace(escaper, function(match) { return '\\' + escapes[match]; });
11177
11178      if (escape) {
11179        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
11180      }
11181      if (interpolate) {
11182        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
11183      }
11184      if (evaluate) {
11185        source += "';\n" + evaluate + "\n__p+='";
11186      }
11187      index = offset + match.length;
11188      return match;
11189    });
11190    source += "';\n";
11191
11192    // If a variable is not specified, place data values in local scope.
11193    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
11194
11195    source = "var __t,__p='',__j=Array.prototype.join," +
11196      "print=function(){__p+=__j.call(arguments,'');};\n" +
11197      source + "return __p;\n";
11198
11199    try {
11200      render = new Function(settings.variable || 'obj', '_', source);
11201    } catch (e) {
11202      e.source = source;
11203      throw e;
11204    }
11205
11206    if (data) return render(data, _);
11207    var template = function(data) {
11208      return render.call(this, data, _);
11209    };
11210
11211    // Provide the compiled function source as a convenience for precompilation.
11212    template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
11213
11214    return template;
11215  };
11216
11217  // Add a "chain" function, which will delegate to the wrapper.
11218  _.chain = function(obj) {
11219    return _(obj).chain();
11220  };
11221
11222  // OOP
11223  // ---------------
11224  // If Underscore is called as a function, it returns a wrapped object that
11225  // can be used OO-style. This wrapper holds altered versions of all the
11226  // underscore functions. Wrapped objects may be chained.
11227
11228  // Helper function to continue chaining intermediate results.
11229  var result = function(obj) {
11230    return this._chain ? _(obj).chain() : obj;
11231  };
11232
11233  // Add all of the Underscore functions to the wrapper object.
11234  _.mixin(_);
11235
11236  // Add all mutator Array functions to the wrapper.
11237  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
11238    var method = ArrayProto[name];
11239    _.prototype[name] = function() {
11240      var obj = this._wrapped;
11241      method.apply(obj, arguments);
11242      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
11243      return result.call(this, obj);
11244    };
11245  });
11246
11247  // Add all accessor Array functions to the wrapper.
11248  each(['concat', 'join', 'slice'], function(name) {
11249    var method = ArrayProto[name];
11250    _.prototype[name] = function() {
11251      return result.call(this, method.apply(this._wrapped, arguments));
11252    };
11253  });
11254
11255  _.extend(_.prototype, {
11256
11257    // Start chaining a wrapped Underscore object.
11258    chain: function() {
11259      this._chain = true;
11260      return this;
11261    },
11262
11263    // Extracts the result from a wrapped and chained object.
11264    value: function() {
11265      return this._wrapped;
11266    }
11267
11268  });
11269
11270}).call(this);
11271$(function() {
11272  var batchedImages = [];
11273  var url = "https://widget.fotomoto.com/stores/photo_checkin";
11274
11275  var sendBatchRequest = function(fotomotoID) {
11276    // console.log("sending batch request with ", batchedImages.length, "images")
11277    var payload = {
11278      imgs: batchedImages,
11279      page_url: window.location.href,
11280      store_key: fotomotoID,
11281    };
11282
11283    // console.log("payload", payload);
11284
11285    $.post(url, payload, function(data) {
11286      // console.log("FOTOMOTO RESPONSE", data)
11287    }, "json");
11288
11289    batchedImages = [];
11290  }
11291  var throttled = _.debounce(sendBatchRequest, 2000, false);
11292
11293  function batchCheckin(image) {
11294    // Bail if no fotomoto ID
11295    var fotomotoID = window.FOTOMOTO_CONFIG.app_widget_id;
11296    if(!fotomotoID || fotomotoID == '') {
11297      console.log("Error! Fotomoto ID should be set.");
11298      return;
11299    };
11300
11301    var $image = $(image);
11302    var src = $image.data('original') || $image.attr('src');
11303    if (src.match(/^\/\//)) {
11304      src = "http:" + src;
11305    }
11306    var originalImageUrl = $image.data('hires-url') || $image.attr('id').split('-')[1];
11307    // if we have a url, prepend http to it. otherwise, leave it as is
11308    originalImageUrl = (originalImageUrl && originalImageUrl.match(/^\/\//)) ? ("http:" + originalImageUrl) : originalImageUrl;
11309    batchedImages.push({
11310      img: src,
11311      original_image_url: originalImageUrl
11312    });
11313    // console.log("queueing image");
11314    throttled(fotomotoID);
11315  }
11316
11317  // Check in the Image with the FOTOMOTO API.
11318  function checkinImage(image) {
11319    if (window.FOTOMOTO) {
11320      var $image = $(image);
11321      batchCheckin(image);
11322      // FOTOMOTO.API.checkinImage($image.data('original'));
11323    } else {
11324      window.setTimeout(function() {
11325        checkinImage(image);
11326      }, 100);
11327    }
11328  }
11329
11330  var hasSlider = !!$('.bxslider').length;
11331
11332  var toolbarifyImage = function(img) {
11333    if (window.FOTOMOTO) {
11334      var id = img.id.split("-")[1];
11335
11336      if (hasSlider) {
11337        // If we are dealing with a bxslider, we need to only look at
11338        // toolbars on the original slide elements.
11339        // (Elements are cloned at the start and end.)
11340        var toolbarEl = $('.bx-orig #fotomoto-toolbar-' + id);
11341      } else {
11342        var toolbarEl = $('#fotomoto-toolbar-' + id);
11343      }
11344      FOTOMOTO.API.showToolbar(toolbarEl, img.id);
11345    } else {
11346      setTimeout(function() { toolbarifyImage(img) }, 500);
11347    }
11348  }
11349
11350  // If there are less than x images, load them all.
11351  if ($("img.lazy").length <= 10) {
11352    var imagesToLoad = $("img.lazy");
11353  } else {
11354    // We always want to immediately load the first image in the gallery
11355    var imagesToLoad = $("img.lazy").eq(0);
11356  }
11357
11358  if (window.image_ids.length) {
11359    $('img.actual-image').load(function() {
11360      toolbarifyImage(this);
11361      checkinImage(this);
11362    });
11363  }
11364});
11365
11366function setupGalleryHomepage(delay, displayImgId, queueDivId){
11367    $(function () {
11368        var nextidx = 0;
11369
11370        var nextimg = $(queueDivId + " img")[nextidx];
11371        $(displayImgId).attr("src", $(nextimg).attr("src"));
11372        //$(displayImgId).show();
11373
11374        setInterval(function () {
11375
11376            if (nextidx++ >= $(queueDivId + " img").length - 1) {
11377                nextidx = 0;
11378            }
11379
11380            nextimg = $(queueDivId + " img")[nextidx];
11381
11382            if ($(queueDivId + " img").length > 1) {
11383                $(displayImgId).fadeToggle(250, function(){ $(displayImgId).attr("src", $(nextimg).attr("src")); resizeHomepageImage() });
11384            }
11385
11386        }, delay);
11387    });
11388}
11389
11390function playVideo() {
11391  $('iframe').load(function() {
11392    this.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
11393    this.contentWindow.postMessage('{"method":"play","value":""}', '*');
11394  });
11395}
11396;
11397$(function() {
11398  // pure JS
11399  var $elem = $('#mySwipe');
11400  if ($elem.size > 0) {
11401    var $bullets = $('#position li');
11402    var currentIndex = 0;
11403
11404    if (window.location.hash != '') {
11405      hash = window.location.hash;
11406      hash = hash.slice(1);
11407      if (hash.substr(0, 6) == 'old-id') {
11408        var old_id = hash.split('=')[1];
11409        currentIndex = $bullets.index($('li[data-old-id=' + old_id + ']'));
11410      } else {
11411        currentIndex = $bullets.index($('#' + hash));
11412      }
11413    } else {
11414      var path = window.location.pathname.split('/');
11415      if (path.length == 3) {
11416        path = path[2];
11417        currentIndex = $bullets.index($("#" + path));
11418      }
11419    }
11420
11421    var swipeCallback = function(pos) {
11422      var i = $bullets.length;
11423      while (i--) {
11424        $($bullets.get(i)).removeClass('on');
11425        // $(bullets[i]).removeClass('on');
11426      }
11427
11428      var $bullet = $($bullets.get(pos));
11429
11430      var path = window.location.pathname.match(/(\/.*)\//);
11431      if (path) {
11432        path = path[1];
11433      } else {
11434        path = window.location.pathname;
11435      }
11436      window.history.pushState({}, $bullet.attr('id'), path + '/' + $bullet.attr('id'));
11437
11438      $bullet.addClass('on');
11439      $($bullets.get(pos)).addClass('on');
11440
11441      $('.item iframe').each(function (ind) {
11442        this.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
11443        this.contentWindow.postMessage('{"method":"pause","value":""}', '*');
11444      });
11445    }
11446
11447    var preslide = function(index, element) {
11448      if ($(element).size() > 0) {
11449        var $img = $(element).find('img');
11450        if ($img.size() > 0) {
11451          if ($img[0].naturalHeight > $('.swipe-wrap div').height()) {
11452            $('.swipe-wrap div').height($img[0].naturalHeight);
11453          }
11454        } else {
11455          $('.swipe-wrap div').height('100%');
11456        }
11457      }
11458    }
11459
11460    var transitionEnd = function(index, element) {
11461      var $img = $(element).find('img');
11462      if ($img.size() > 0) {
11463        $img[0].onload = function() {
11464          $('.swipe-wrap div').height(this.naturalHeight);
11465        }
11466      } else {
11467        $('.swipe-wrap div').height('100%');
11468      }
11469    }
11470
11471    var swipeOptions = {
11472      startSlide: currentIndex,
11473      callback: swipeCallback,
11474      preslide: preslide,
11475      transitionEnd: transitionEnd
11476    }
11477
11478    if ($elem.hasClass('auto')) {
11479      swipeOptions.auto = 3000;
11480    }
11481    window.mySwipe = Swipe($elem[0], swipeOptions);
11482
11483    transitionEnd(currentIndex, $('div[data-index=' + currentIndex + ']'));
11484
11485    var $thumbs = $('#position li');
11486    $thumbs.on('click', function(e) {
11487      var el = e.currentTarget;
11488      window.mySwipe.slide($thumbs.index(el));
11489    });
11490
11491    $(window).on('keydown', function(e) {
11492      switch(e.keyCode) {
11493        case 37: // left
11494          e.preventDefault();
11495          window.mySwipe.prev();
11496          break;
11497        case 39: // right
11498          e.preventDefault();
11499          window.mySwipe.next();
11500          break;
11501      }
11502    })
11503
11504    // Handle Left and Right keyboard arrows for next and prev
11505    $('.gallery article').on('click', function(e) {
11506      if(window.mySwipe.getPos() == (window.mySwipe.getNumSlides() - 1)) {
11507        // last slide, reset to the first slide
11508        window.mySwipe.slide(0);
11509      } else {
11510        window.mySwipe.next();
11511      }
11512    });
11513
11514    if ($elem.hasClass('homepage')) {
11515      $('.item iframe').load(function() {
11516        this.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
11517        this.contentWindow.postMessage('{"method":"play","value":""}', '*');
11518      });
11519    }
11520  }
11521
11522
11523});
11524$(function () {
11525    var db = document.body;
11526    var holder = document.getElementById('holder');
11527    if (holder === null) {
11528      return false;
11529    }
11530    var img = holder.getElementsByTagName('img')[0];
11531
11532    if (!img) { return false; }
11533
11534    var dbsize = {}; //needed to store body size
11535    var imgsrc = img.src; //needed to store images src
11536    var keyStop = function (e) {
11537        var e = window.event || e || {};
11538        var tag = e.target.tagName.toLowerCase();
11539        if (tag != 'textarea' && !(tag == 'input' && (e.target.type == 'text' || e.target.type == 'password'))) {
11540            if (e.keyCode == 32 || e.keyCode == 39 || e.keyCode == 40) {
11541                if (e.preventDefault) e.preventDefault();
11542                else e.returnValue = false;
11543            }
11544        }
11545    }
11546
11547    if (this.addEventListener) window.addEventListener('keydown', keyStop, false);
11548    else window.attachEvent('onkeydown', keyStop);
11549
11550    resizeHomepageImage = function () {
11551        window.scrollTo(0, 0);
11552        if (img.complete) { //check if image has loaded
11553
11554            $("#holder-image").fadeIn(250);
11555            $("#loading").hide();
11556
11557            if (db.clientWidth != dbsize.w || db.clientHeight != dbsize.h || img.src != imgsrc) { //check if size or img size has changed
11558                imgsrc = img.src; //store current src
11559                dbsize.w = db.clientWidth; //store current body width
11560                dbsize.h = db.clientHeight; //store current body height
11561
11562                var newwidth = Math.round(dbsize.h * (img.offsetWidth / img.offsetHeight)); //calculate new width based on height
11563
11564                img.style.width = (dbsize.w > newwidth ? dbsize.w : newwidth) + 'px'; //use the largest value of body-width and newwidht
11565                //and this is the real trick: if there's no specified height, the height is automaticly calculated relative to the with
11566            }
11567        } else {
11568            setTimeout(resizeHomepageImage, 300);
11569        }
11570    };
11571
11572    setTimeout(resizeHomepageImage, 300);
11573    $(window).bind("resize", function () {
11574        resizeHomepageImage();
11575    });
11576});
11577/*
11578 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
11579 *
11580 * Uses the built in easing capabilities added In jQuery 1.1
11581 * to offer multiple easing options
11582 *
11583 * TERMS OF USE - jQuery Easing
11584 * 
11585 * Open source under the BSD License. 
11586 * 
11587 * Copyright © 2008 George McGinley Smith
11588 * All rights reserved.
11589 * 
11590 * Redistribution and use in source and binary forms, with or without modification, 
11591 * are permitted provided that the following conditions are met:
11592 * 
11593 * Redistributions of source code must retain the above copyright notice, this list of 
11594 * conditions and the following disclaimer.
11595 * Redistributions in binary form must reproduce the above copyright notice, this list 
11596 * of conditions and the following disclaimer in the documentation and/or other materials 
11597 * provided with the distribution.
11598 * 
11599 * Neither the name of the author nor the names of contributors may be used to endorse 
11600 * or promote products derived from this software without specific prior written permission.
11601 * 
11602 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
11603 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
11604 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
11605 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
11606 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
11607 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
11608 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
11609 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
11610 * OF THE POSSIBILITY OF SUCH DAMAGE. 
11611 *
11612*/
11613
11614// t: current time, b: begInnIng value, c: change In value, d: duration
11615jQuery.easing['jswing'] = jQuery.easing['swing'];
11616
11617jQuery.extend( jQuery.easing,
11618{
11619	def: 'easeOutQuad',
11620	swing: function (x, t, b, c, d) {
11621		//alert(jQuery.easing.default);
11622		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
11623	},
11624	easeInQuad: function (x, t, b, c, d) {
11625		return c*(t/=d)*t + b;
11626	},
11627	easeOutQuad: function (x, t, b, c, d) {
11628		return -c *(t/=d)*(t-2) + b;
11629	},
11630	easeInOutQuad: function (x, t, b, c, d) {
11631		if ((t/=d/2) < 1) return c/2*t*t + b;
11632		return -c/2 * ((--t)*(t-2) - 1) + b;
11633	},
11634	easeInCubic: function (x, t, b, c, d) {
vendor: 5,241 bytes, lines 11635-11774
11635		return c*(t/=d)*t*t + b;
11636	},
11637	easeOutCubic: function (x, t, b, c, d) {
11638		return c*((t=t/d-1)*t*t + 1) + b;
11639	},
11640	easeInOutCubic: function (x, t, b, c, d) {
11641		if ((t/=d/2) < 1) return c/2*t*t*t + b;
11642		return c/2*((t-=2)*t*t + 2) + b;
11643	},
11644	easeInQuart: function (x, t, b, c, d) {
11645		return c*(t/=d)*t*t*t + b;
11646	},
11647	easeOutQuart: function (x, t, b, c, d) {
11648		return -c * ((t=t/d-1)*t*t*t - 1) + b;
11649	},
11650	easeInOutQuart: function (x, t, b, c, d) {
11651		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
11652		return -c/2 * ((t-=2)*t*t*t - 2) + b;
11653	},
11654	easeInQuint: function (x, t, b, c, d) {
11655		return c*(t/=d)*t*t*t*t + b;
11656	},
11657	easeOutQuint: function (x, t, b, c, d) {
11658		return c*((t=t/d-1)*t*t*t*t + 1) + b;
11659	},
11660	easeInOutQuint: function (x, t, b, c, d) {
11661		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
11662		return c/2*((t-=2)*t*t*t*t + 2) + b;
11663	},
11664	easeInSine: function (x, t, b, c, d) {
11665		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
11666	},
11667	easeOutSine: function (x, t, b, c, d) {
11668		return c * Math.sin(t/d * (Math.PI/2)) + b;
11669	},
11670	easeInOutSine: function (x, t, b, c, d) {
11671		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
11672	},
11673	easeInExpo: function (x, t, b, c, d) {
11674		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
11675	},
11676	easeOutExpo: function (x, t, b, c, d) {
11677		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
11678	},
11679	easeInOutExpo: function (x, t, b, c, d) {
11680		if (t==0) return b;
11681		if (t==d) return b+c;
11682		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
11683		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
11684	},
11685	easeInCirc: function (x, t, b, c, d) {
11686		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
11687	},
11688	easeOutCirc: function (x, t, b, c, d) {
11689		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
11690	},
11691	easeInOutCirc: function (x, t, b, c, d) {
11692		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
11693		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
11694	},
11695	easeInElastic: function (x, t, b, c, d) {
11696		var s=1.70158;var p=0;var a=c;
11697		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
11698		if (a < Math.abs(c)) { a=c; var s=p/4; }
11699		else var s = p/(2*Math.PI) * Math.asin (c/a);
11700		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
11701	},
11702	easeOutElastic: function (x, t, b, c, d) {
11703		var s=1.70158;var p=0;var a=c;
11704		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
11705		if (a < Math.abs(c)) { a=c; var s=p/4; }
11706		else var s = p/(2*Math.PI) * Math.asin (c/a);
11707		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
11708	},
11709	easeInOutElastic: function (x, t, b, c, d) {
11710		var s=1.70158;var p=0;var a=c;
11711		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
11712		if (a < Math.abs(c)) { a=c; var s=p/4; }
11713		else var s = p/(2*Math.PI) * Math.asin (c/a);
11714		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
11715		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
11716	},
11717	easeInBack: function (x, t, b, c, d, s) {
11718		if (s == undefined) s = 1.70158;
11719		return c*(t/=d)*t*((s+1)*t - s) + b;
11720	},
11721	easeOutBack: function (x, t, b, c, d, s) {
11722		if (s == undefined) s = 1.70158;
11723		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
11724	},
11725	easeInOutBack: function (x, t, b, c, d, s) {
11726		if (s == undefined) s = 1.70158; 
11727		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
11728		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
11729	},
11730	easeInBounce: function (x, t, b, c, d) {
11731		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
11732	},
11733	easeOutBounce: function (x, t, b, c, d) {
11734		if ((t/=d) < (1/2.75)) {
11735			return c*(7.5625*t*t) + b;
11736		} else if (t < (2/2.75)) {
11737			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
11738		} else if (t < (2.5/2.75)) {
11739			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
11740		} else {
11741			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
11742		}
11743	},
11744	easeInOutBounce: function (x, t, b, c, d) {
11745		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
11746		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
11747	}
11748});
11749
11750/*
11751 *
11752 * TERMS OF USE - EASING EQUATIONS
11753 * 
11754 * Open source under the BSD License. 
11755 * 
11756 * Copyright © 2001 Robert Penner
11757 * All rights reserved.
11758 * 
11759 * Redistribution and use in source and binary forms, with or without modification, 
11760 * are permitted provided that the following conditions are met:
11761 * 
11762 * Redistributions of source code must retain the above copyright notice, this list of 
11763 * conditions and the following disclaimer.
11764 * Redistributions in binary form must reproduce the above copyright notice, this list 
11765 * of conditions and the following disclaimer in the documentation and/or other materials 
11766 * provided with the distribution.
11767 * 
11768 * Neither the name of the author nor the names of contributors may be used to endorse 
11769 * or promote products derived from this software without specific prior written permission.
11770 * 
11771 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
11772 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
11773 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
11774 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
11775 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
11776 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
11777 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
11778 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
11779 * OF THE POSSIBILITY OF SUCH DAMAGE. 
11780 *
11781 */
11782;
11783/*global jQuery */
11784/*jshint multistr:true browser:true */
11785/*!
11786* FitVids 1.0
11787*
11788* Copyright 2011, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com
11789* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
11790* Released under the WTFPL license - http://sam.zoy.org/wtfpl/
11791*
11792* Date: Thu Sept 01 18:00:00 2011 -0500
11793*/
11794
11795
11796(function( $ ){
11797
11798  "use strict";
11799
11800  $.fn.fitVids = function( options ) {
11801    var settings = {
11802      customSelector: null
11803    };
11804
11805    var div = document.createElement('div'),
11806        ref = document.getElementsByTagName('base')[0] || document.getElementsByTagName('script')[0];
11807
11808    div.className = 'fit-vids-style';
11809    div.innerHTML = '&shy;<style>         \
11810      .fluid-width-video-wrapper {        \
11811         width: 100%;                     \
11812         position: relative;              \
11813         padding: 0;                      \
11814      }                                   \
11815                                          \
11816      .fluid-width-video-wrapper iframe,  \
11817      .fluid-width-video-wrapper object,  \
11818      .fluid-width-video-wrapper embed {  \
11819         position: absolute;              \
11820         top: 0;                          \
11821         left: 0;                         \
11822         width: 100%;                     \
11823         height: 100%;                    \
11824      }                                   \
11825    </style>';
11826
11827    ref.parentNode.insertBefore(div,ref);
11828
11829    if ( options ) {
11830      $.extend( settings, options );
11831    }
11832
11833    return this.each(function(){
11834      var selectors = [
11835        "iframe[src*='player.vimeo.com']",
11836        "iframe[src*='www.youtube.com']",
11837        "iframe[src*='www.kickstarter.com']",
11838        "object",
11839        "embed"
11840      ];
11841
11842      if (settings.customSelector) {
11843        selectors.push(settings.customSelector);
11844      }
11845
11846      var $allVideos = $(this).find(selectors.join(','));
11847
11848      $allVideos.each(function(){
11849        var $this = $(this);
11850        if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; }
11851        var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(),
11852            width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(),
11853            aspectRatio = height / width;
11854        if(!$this.attr('id')){
11855          var videoID = 'fitvid' + Math.floor(Math.random()*999999);
11856          $this.attr('id', videoID);
11857        }
11858        $this.wrap('<div class="fluid-width-video-wrapper"></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+"%");
11859        $this.removeAttr('height').removeAttr('width');
11860      });
11861    });
11862  };
11863})( jQuery );
11864/*!
11865 * Lazy Load - jQuery plugin for lazy loading images
11866 *
11867 * Copyright (c) 2007-2015 Mika Tuupola
11868 *
11869 * Licensed under the MIT license:
11870 *   http://www.opensource.org/licenses/mit-license.php
11871 *
11872 * Project home:
11873 *   http://www.appelsiini.net/projects/lazyload
11874 *
11875 * Version:  1.9.7
11876 *
11877 */
11878
11879
11880(function($, window, document, undefined) {
11881    var $window = $(window);
11882
11883    $.fn.lazyload = function(options) {
11884        var elements = this;
11885        var $container;
11886        var settings = {
11887            threshold       : 0,
11888            failure_limit   : 0,
11889            event           : "scroll",
11890            effect          : "show",
11891            container       : window,
11892            data_attribute  : "original",
11893            skip_invisible  : false,
11894            appear          : null,
11895            load            : null,
11896            placeholder     : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"
11897        };
11898
vendor: 5,182 bytes, lines 11899-12035
11899        function update() {
11900            var counter = 0;
11901
11902            elements.each(function() {
11903                var $this = $(this);
11904                if (settings.skip_invisible && !$this.is(":visible")) {
11905                    return;
11906                }
11907                if ($.abovethetop(this, settings) ||
11908                    $.leftofbegin(this, settings)) {
11909                        /* Nothing. */
11910                } else if (!$.belowthefold(this, settings) &&
11911                    !$.rightoffold(this, settings)) {
11912                        $this.trigger("appear");
11913                        /* if we found an image we'll load, reset the counter */
11914                        counter = 0;
11915                } else {
11916                    if (++counter > settings.failure_limit) {
11917                        return false;
11918                    }
11919                }
11920            });
11921
11922        }
11923
11924        if(options) {
11925            /* Maintain BC for a couple of versions. */
11926            if (undefined !== options.failurelimit) {
11927                options.failure_limit = options.failurelimit;
11928                delete options.failurelimit;
11929            }
11930            if (undefined !== options.effectspeed) {
11931                options.effect_speed = options.effectspeed;
11932                delete options.effectspeed;
11933            }
11934
11935            $.extend(settings, options);
11936        }
11937
11938        /* Cache container as jQuery as object. */
11939        $container = (settings.container === undefined ||
11940                      settings.container === window) ? $window : $(settings.container);
11941
11942        /* Fire one scroll event per scroll. Not one scroll event per image. */
11943        if (0 === settings.event.indexOf("scroll")) {
11944            $container.bind(settings.event, function() {
11945                return update();
11946            });
11947        }
11948
11949        this.each(function() {
11950            var self = this;
11951            var $self = $(self);
11952
11953            self.loaded = false;
11954
11955            /* If no src attribute given use data:uri. */
11956            if ($self.attr("src") === undefined || $self.attr("src") === false) {
11957                if ($self.is("img")) {
11958                    $self.attr("src", settings.placeholder);
11959                }
11960            }
11961
11962            /* When appear is triggered load original image. */
11963            $self.one("appear", function() {
11964                if (!this.loaded) {
11965                    if (settings.appear) {
11966                        var elements_left = elements.length;
11967                        settings.appear.call(self, elements_left, settings);
11968                    }
11969                    $("<img />")
11970                        .bind("load", function() {
11971
11972                            var original = $self.attr("data-" + settings.data_attribute);
11973                            $self.hide();
11974                            if ($self.is("img")) {
11975                                $self.attr("src", original);
11976                            } else {
11977                                $self.css("background-image", "url('" + original + "')");
11978                            }
11979                            $self[settings.effect](settings.effect_speed);
11980
11981                            self.loaded = true;
11982
11983                            /* Remove image from array so it is not looped next time. */
11984                            var temp = $.grep(elements, function(element) {
11985                                return !element.loaded;
11986                            });
11987                            elements = $(temp);
11988
11989                            if (settings.load) {
11990                                var elements_left = elements.length;
11991                                settings.load.call(self, elements_left, settings);
11992                            }
11993                        })
11994                        .attr("src", $self.attr("data-" + settings.data_attribute));
11995                }
11996            });
11997
11998            /* When wanted event is triggered load original image */
11999            /* by triggering appear.                              */
12000            if (0 !== settings.event.indexOf("scroll")) {
12001                $self.bind(settings.event, function() {
12002                    if (!self.loaded) {
12003                        $self.trigger("appear");
12004                    }
12005                });
12006            }
12007        });
12008
12009        /* Check if something appears when window is resized. */
12010        $window.bind("resize", function() {
12011            update();
12012        });
12013
12014        /* With IOS5 force loading images when navigating with back button. */
12015        /* Non optimal workaround. */
12016        if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) {
12017            $window.bind("pageshow", function(event) {
12018                if (event.originalEvent && event.originalEvent.persisted) {
12019                    elements.each(function() {
12020                        $(this).trigger("appear");
12021                    });
12022                }
12023            });
12024        }
12025
12026        /* Force initial check if images should appear. */
12027        $(document).ready(function() {
12028            update();
12029        });
12030
12031        return this;
12032    };
12033
12034    /* Convenience methods in jQuery namespace.           */
12035    /* Use as  $.belowthefold(element, {threshold : 100, container : window}
12035) */
12036
12037    $.belowthefold = function(element, settings) {
12038        var fold;
12039
12040        if (settings.container === undefined || settings.container === window) {
12041            fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop();
12042        } else {
12043            fold = $(settings.container).offset().top + $(settings.container).height();
12044        }
12045
12046        return fold <= $(element).offset().top - settings.threshold;
12047    };
12048
12049    $.rightoffold = function(element, settings) {
12050        var fold;
12051
12052        if (settings.container === undefined || settings.container === window) {
12053            fold = $window.width() + $window.scrollLeft();
12054        } else {
12055            fold = $(settings.container).offset().left + $(settings.container).width();
12056        }
12057
12058        return fold <= $(element).offset().left - settings.threshold;
12059    };
12060
12061    $.abovethetop = function(element, settings) {
12062        var fold;
12063
12064        if (settings.container === undefined || settings.container === window) {
12065            fold = $window.scrollTop();
12066        } else {
12067            fold = $(settings.container).offset().top;
12068        }
12069
12070        return fold >= $(element).offset().top + settings.threshold  + $(element).height();
12071    };
12072
12073    $.leftofbegin = function(element, settings) {
12074        var fold;
12075
12076        if (settings.container === undefined || settings.container === window) {
12077            fold = $window.scrollLeft();
12078        } else {
12079            fold = $(settings.container).offset().left;
12080        }
12081
12082        return fold >= $(element).offset().left + settings.threshold + $(element).width();
12083    };
12084
12085    $.inviewport = function(element, settings) {
12086         return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) &&
12087                !$.belowthefold(element, settings) && !$.abovethetop(element, settings);
12088     };
12089
12090    /* Custom selectors for your convenience.   */
12091    /* Use as $("img:below-the-fold").something() or */
12092    /* $("img").filter(":below-the-fold").something() which is faster */
12093
12094    $.extend($.expr[":"], {
12095        "below-the-fold" : function(a) { return $.belowthefold(a, {threshold : 0}); },
12096        "above-the-top"  : function(a) { return !$.belowthefold(a, {threshold : 0}); },
12097        "right-of-screen": function(a) { return $.rightoffold(a, {threshold : 0}); },
12098        "left-of-screen" : function(a) { return !$.rightoffold(a, {threshold : 0}); },
12099        "in-viewport"    : function(a) { return $.inviewport(a, {threshold : 0}); },
12100        /* Maintain BC for couple of versions. */
12101        "above-the-fold" : function(a) { return !$.belowthefold(a, {threshold : 0}); },
12102        "right-of-fold"  : function(a) { return $.rightoffold(a, {threshold : 0}); },
12103        "left-of-fold"   : function(a) { return !$.rightoffold(a, {threshold : 0}); }
12104    });
12105
12106})(jQuery, window, document);
12107/***
12108 * BxSlider v4.2.3 - Fully loaded, responsive content slider
12109 * http://bxslider.com
12110 *
12111 * Copyright 2014, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com
12112 * Written while drinking Belgian ales and listening to jazz
12113 *
12114 * Released under the MIT license - http://opensource.org/licenses/MIT
12115 ***/
12116
12117
12118;(function($){
12119	var isMobile = $(window).width() <= 768;
12120	var defaults = {
12121
12122		// GENERAL
12123		mode: 'horizontal',
12124		slideSelector: '',
12125		infiniteLoop: true,
12126		hideControlOnEnd: false,
12127		speed: 200,
12128		easing: null,
12129		slideMargin: 0,
12130		startSlide: 0,
12131		randomStart: false,
12132		captions: false,
12133		ticker: false,
12134		tickerHover: false,
12135		adaptiveHeight: false,
12136		adaptiveHeightSpeed: 500,
12137		video: false,
12138		useCSS: true,
12139		preloadImages: 'visible',
12140		responsive: true,
12141		slideZIndex: 50,
12142		wrapperClass: 'bx-wrapper',
12143
12144		touchEnabled: isMobile,
12145		oneToOneTouch: isMobile,
12146
12147		swipeThreshold: 50,
12148		preventDefaultSwipeX: true,
12149		preventDefaultSwipeY: false,
12150
12151    // ACCESSIBILITY
12152    ariaHidden: true,
12153
12154		// KEYBOARD
12155		keyboardEnabled: false,
12156
12157		// PAGER
12158		pager: true,
12159		pagerType: 'full',
12160		pagerShortSeparator: ' / ',
12161		pagerSelector: null,
12162		buildPager: null,
12163		pagerCustom: null,
12164
12165		// CONTROLS
12166		controls: true,
12167		nextText: 'Next',
12168		prevText: 'Prev',
12169		nextSelector: null,
12170		prevSelector: null,
12171		autoControls: false,
12172		startText: 'Start',
12173		stopText: 'Stop',
12174		autoControlsCombine: false,
12175		autoControlsSelector: null,
12176
12177		// AUTO
12178		auto: false,
12179		pause: 4000,
12180		autoStart: true,
12181		autoDirection: 'next',
12182		autoHover: false,
12183		autoDelay: 0,
12184		autoSlideForOnePage: false,
12185
12186		// CAROUSEL
12187		minSlides: 1,
12188		maxSlides: 1,
12189		moveSlides: 0,
12190		slideWidth: 0,
12191
12192		// CALLBACKS
12193		onSliderLoad: function(){ return true },
12194		onSlideBefore: function(){ return true },
12195		onSlideAfter: function(){ return true },
12196		onSlideNext: function(){ return true },
12197		onSlidePrev: function(){ return true },
12198		onSliderResize: function(){ return true }
12199	};
12200
12201	$.fn.bxSlider = function(options){
12202
12203		if(this.length === 0){
12204			return this;
12205		}
12206
12207		// support multiple elements
12208		if(this.length > 1){
12209			this.each(function(){
12210				$(this).bxSlider(options);
12211			});
12212			return this;
12213		}
12214
12215		// create a namespace to be used throughout the plugin
12216		var slider = {};
12217		// set a reference to our slider element
12218		var el = this;
12219
12220		/**
12221		 * Makes slideshow responsive
12222		 */
12223		// first get the original window dimens (thanks a lot IE)
12224		var windowWidth = $(window).width();
12225		var windowHeight = $(window).height();
12226
12227
12228
12229		/**
12230		 * ===================================================================================
12231		 * = PRIVATE FUNCTIONS
12232		 * ===================================================================================
12233		 */
12234
12235		/**
12236		 * Initializes namespace settings to be used throughout plugin
12237		 */
12238		var init = function(){
12239			// merge user-supplied options with the defaults
12240			slider.settings = $.extend({}, defaults, options);
12241			// parse slideWidth setting
12242			slider.settings.slideWidth = parseInt(slider.settings.slideWidth);
12243			// store the original children
12244			slider.children = el.children(slider.settings.slideSelector);
12245			// check if actual number of slides is less than minSlides / maxSlides
12246			if(slider.children.length < slider.settings.minSlides){ slider.settings.minSlides = slider.children.length; }
12247			if(slider.children.length < slider.settings.maxSlides){ slider.settings.maxSlides = slider.children.length; }
12248			// if random start, set the startSlide setting to random number
12249			if(slider.settings.randomStart){ slider.settings.startSlide = Math.floor(Math.random() * slider.children.length); }
12250			// store active slide information
12251			slider.active = { index: slider.settings.startSlide };
12252			// store if the slider is in carousel mode (displaying / moving multiple slides)
12253			slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1 ? true : false;
12254			// if carousel, force preloadImages = 'all'
12255			if(slider.carousel){ slider.settings.preloadImages = 'all'; }
12256			// calculate the min / max width thresholds based on min / max number of slides
12257			// used to setup and update carousel slides dimensions
12258			slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin);
12259			slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
12260			// store the current state of the slider (if currently animating, working is true)
12261			slider.working = false;
12262			// initialize the controls object
12263			slider.controls = {};
12264			// initialize an auto interval
12265			slider.interval = null;
12266			// determine which property to use for transitions
12267			slider.animProp = slider.settings.mode === 'vertical' ? 'top' : 'left';
12268			// determine if hardware acceleration can be used
12269			slider.usingCSS = slider.settings.useCSS && slider.settings.mode !== 'fade' && (function(){
12270				// create our test div element
12271				var div = document.createElement('div');
12272				// css transition properties
12273				var props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
12274				// test for each property
12275				for(var i in props){
12276					if(div.style[props[i]] !== undefined){
12277						slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase();
12278						slider.animProp = '-' + slider.cssPrefix + '-transform';
12279						return true;
12280					}
12281				}
12282				return false;
12283			}());
12284			// if vertical mode always make maxSlides and minSlides equal
12285			if(slider.settings.mode === 'vertical'){ slider.settings.maxSlides = slider.settings.minSlides; }
12286			// save original style data
12287			el.data("origStyle", el.attr("style"));
12288			el.children(slider.settings.slideSelector).each(function(){
12289			  $(this).data("origStyle", $(this).attr("style"));
12290			});
12291			// perform all DOM / CSS modifications
12292			setup();
12293		};
12294
12295		/**
12296		 * Performs all DOM and CSS modifications
12297		 */
12298		var setup = function(){
12299			// wrap el in a wrapper
vendor: 3,147 bytes, lines 12300-12366
12300			el.wrap('<div class="' + slider.settings.wrapperClass + '"><div class="bx-viewport"></div></div>');
12301			// store a namespace reference to .bx-viewport
12302			slider.viewport = el.parent();
12303			// add a loading div to display while images are loading
12304			slider.loader = $('<div class="bx-loading" />');
12305			slider.viewport.prepend(slider.loader);
12306			// set el to a massive width, to hold any needed slides
12307			// also strip any margin and padding from el
12308			el.css({
12309				width: slider.settings.mode === 'horizontal' ? (slider.children.length * 1000 + 215) + '%' : 'auto',
12310				position: 'absolute'
12311			});
12312			// if using CSS, add the easing property
12313			if(slider.usingCSS && slider.settings.easing){
12314				el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing);
12315			// if not using CSS and no easing value was supplied, use the default JS animation easing (swing)
12316			}else if(!slider.settings.easing){
12317				slider.settings.easing = 'swing';
12318			}
12319			var slidesShowing = getNumberSlidesShowing();
12320			// make modifications to the viewport (.bx-viewport)
12321			slider.viewport.css({
12322				width: '100%',
12323				overflow: 'hidden',
12324				position: 'relative'
12325			});
12326			slider.viewport.parent().css({
12327				maxWidth: getViewportMaxWidth()
12328			});
12329			// make modification to the wrapper (.bx-wrapper)
12330			if(!slider.settings.pager && !slider.settings.controls){
12331				slider.viewport.parent().css({
12332					margin: '0 auto 0px'
12333				});
12334			}
12335			// apply css to all slider children
12336			slider.children.css({
12337				'float': slider.settings.mode === 'horizontal' ? 'left' : 'none',
12338				listStyle: 'none',
12339				position: 'relative'
12340			});
12341			// apply the calculated width after the float is applied to prevent scrollbar interference
12342			slider.children.css('width', getSlideWidth());
12343			// if slideMargin is supplied, add the css
12344			if(slider.settings.mode === 'horizontal' && slider.settings.slideMargin > 0){ slider.children.css('marginRight', slider.settings.slideMargin); }
12345			if(slider.settings.mode === 'vertical' && slider.settings.slideMargin > 0){ slider.children.css('marginBottom', slider.settings.slideMargin); }
12346			// if "fade" mode, add positioning and z-index CSS
12347			if(slider.settings.mode === 'fade'){
12348				slider.children.css({
12349					position: 'absolute',
12350					zIndex: 0,
12351					display: 'none'
12352				});
12353				// prepare the z-index on the showing element
12354				slider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'});
12355			}
12356			// create an element to contain all slider controls (pager, start / stop, etc)
12357			slider.controls.el = $('<div class="bx-controls" />');
12358			// if captions are requested, add them
12359			if(slider.settings.captions){ appendCaptions(); }
12360			// check if startSlide is last slide
12361			slider.active.last = slider.settings.startSlide === getPagerQty() - 1;
12362			// if video is true, set up the fitVids plugin
12363			if(slider.settings.video){ el.fitVids(); }
12364			// set the default preload selector (visible)
12365			var preloadSelector = slider.children.eq(slider.settings.startSlide);
12366			if(slider.settings.preloadImages === "all" || slider.settings.ticker){ preloadSelector = slider.children; }
12367			// only check for control addition if not in "ticker" mode
12368			if(!slider.settings.ticker){
12369				// if controls are requested, add them
12370				if(slider.settings.controls){ appendControls(); }
12371				// if auto is true, and auto controls are requested, add them
12372				if(slider.settings.auto && slider.settings.autoControls){ appendControlsAuto(); }
12373				// if pager is requested, add it
12374				if(slider.settings.pager){ appendPager(); }
12375				// if any control option is requested, add the controls wrapper
12376				if(slider.settings.controls || slider.settings.autoControls || slider.settings.pager){ slider.viewport.after(slider.controls.el); }
12377			// if ticker mode, do not allow a pager
12378			} else {
12379				slider.settings.pager = false;
12380			}
12381			//loadElements(preloadSelector, start);
12382
12383			// Just show the images straight away!
12384			start();
12385		};
12386
12387		var loadElements = function(selector, callback){
12388			var total = selector.find('img:not([src=""]), iframe').length;
12389			if(total === 0){
12390				callback();
12391				return;
12392			}
12393			var count = 0;
12394			selector.find('img:not([src=""]), iframe').each(function(){
12395				$(this).one('load error', function(){
12396				  if(++count === total){ callback(); }
12397				}).each(function(){
12398				  if(this.complete){ $(this).load(); }
12399				});
12400			});
12401		};
12402
12403		/**
12404		 * Start the slider
12405		 */
12406		var start = function(){
12407			// if infinite loop, prepare additional slides
12408			if(slider.settings.infiniteLoop && slider.settings.mode !== 'fade' && !slider.settings.ticker){
12409				var slice = slider.settings.mode === 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides;
12410				slider.children.addClass('bx-orig');
12411				var sliceAppend = slider.children.slice(0, slice).clone(true).removeClass('bx-orig').addClass('bx-clone');
12412				var slicePrepend = slider.children.slice(-slice).clone(true).removeClass('bx-orig').addClass('bx-clone');
12413        if (slider.settings.ariaHidden) {
12414          sliceAppend.attr('aria-hidden', true);
12415          slicePrepend.attr('aria-hidden', true);
12416        }				
12417				el.append(sliceAppend).prepend(slicePrepend);
12418			}
12419			// remove the loading DOM element
12420			slider.loader.remove();
12421			// set the left / top position of "el"
12422			setSlidePosition();
12423			// if "vertical" mode, always use adaptiveHeight to prevent odd behavior
12424			if(slider.settings.mode === 'vertical'){ slider.settings.adaptiveHeight = true; }
12425			// set the viewport height
12426			slider.viewport.height(getViewportHeight());
12427			// make sure everything is positioned just right (same as a window resize)
12428			el.redrawSlider();
12429			// onSliderLoad callback
12430			slider.settings.onSliderLoad(slider,slider.active.index);
12431			// slider has been fully initialized
12432			slider.initialized = true;
vendor: 6,810 bytes, lines 12433-12591
12433			// bind the resize call to the window
12434			if(slider.settings.responsive){ $(window).bind('resize', resizeWindow); }
12435			// if auto is true and has more than 1 page, start the show
12436			if(slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)){ initAuto(); }
12437			// if ticker is true, start the ticker
12438			if(slider.settings.ticker){ initTicker(); }
12439			// if pager is requested, make the appropriate pager link active
12440			if(slider.settings.pager){ updatePagerActive(slider.settings.startSlide); }
12441			// check for any updates to the controls (like hideControlOnEnd updates)
12442			if(slider.settings.controls){ updateDirectionControls(); }
12443			// if touchEnabled is true, setup the touch events
12444			if(slider.settings.touchEnabled && !slider.settings.ticker){ initTouch(); }
12445			// if keyboardEnabled is true, setup the keyboard events
12446			if (slider.settings.keyboardEnabled && !slider.settings.ticker) {
12447				$(document).keydown(keyPress);
12448			}
12449		};
12450
12451		/**
12452		 * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value
12453		 */
12454		var getViewportHeight = function(){
12455			var height = 0;
12456			// first determine which children (slides) should be used in our height calculation
12457			var children = $();
12458			// if mode is not "vertical" and adaptiveHeight is false, include all children
12459			if(slider.settings.mode !== 'vertical' && !slider.settings.adaptiveHeight){
12460				children = slider.children;
12461			}else{
12462				// if not carousel, return the single active child
12463				if(!slider.carousel){
12464					children = slider.children.eq(slider.active.index);
12465				// if carousel, return a slice of children
12466				}else{
12467					// get the individual slide index
12468					var currentIndex = slider.settings.moveSlides === 1 ? slider.active.index : slider.active.index * getMoveBy();
12469					// add the current slide to the children
12470					children = slider.children.eq(currentIndex);
12471					// cycle through the remaining "showing" slides
12472					for (i = 1; i <= slider.settings.maxSlides - 1; i++){
12473						// if looped back to the start
12474						if(currentIndex + i >= slider.children.length){
12475							children = children.add(slider.children.eq(i - 1));
12476						}else{
12477							children = children.add(slider.children.eq(currentIndex + i));
12478						}
12479					}
12480				}
12481			}
12482			// if "vertical" mode, calculate the sum of the heights of the children
12483			if(slider.settings.mode === 'vertical'){
12484				children.each(function(index){
12485				  height += $(this).outerHeight();
12486				});
12487				// add user-supplied margins
12488				if(slider.settings.slideMargin > 0){
12489					height += slider.settings.slideMargin * (slider.settings.minSlides - 1);
12490				}
12491			// if not "vertical" mode, calculate the max height of the children
12492			}else{
12493				height = Math.max.apply(Math, children.map(function(){
12494					return $(this).outerHeight(false);
12495				}).get());
12496			}
12497
12498			if(slider.viewport.css('box-sizing') === 'border-box'){
12499				height +=	parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) +
12500							parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width'));
12501			}else if(slider.viewport.css('box-sizing') === 'padding-box'){
12502				height +=	parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom'));
12503			}
12504
12505			return height;
12506		};
12507
12508		/**
12509		 * Returns the calculated width to be used for the outer wrapper / viewport
12510		 */
12511		var getViewportMaxWidth = function(){
12512			var width = '100%';
12513			if(slider.settings.slideWidth > 0){
12514				if(slider.settings.mode === 'horizontal'){
12515					width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
12516				}else{
12517					width = slider.settings.slideWidth;
12518				}
12519			}
12520			return width;
12521		};
12522
12523		/**
12524		 * Returns the calculated width to be applied to each slide
12525		 */
12526		var getSlideWidth = function(){
12527			// start with any user-supplied slide width
12528			var newElWidth = slider.settings.slideWidth;
12529			// get the current viewport width
12530			var wrapWidth = slider.viewport.width();
12531			// if slide width was not supplied, or is larger than the viewport use the viewport width
12532			if(slider.settings.slideWidth === 0 ||
12533				(slider.settings.slideWidth > wrapWidth && !slider.carousel) ||
12534				slider.settings.mode === 'vertical'){
12535				newElWidth = wrapWidth;
12536			// if carousel, use the thresholds to determine the width
12537			}else if(slider.settings.maxSlides > 1 && slider.settings.mode === 'horizontal'){
12538				if(wrapWidth > slider.maxThreshold){
12539					// newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides;
12540				}else if(wrapWidth < slider.minThreshold){
12541					newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides;
12542				}
12543			}
12544			return newElWidth;
12545		};
12546
12547		/**
12548		 * Returns the number of slides currently visible in the viewport (includes partially visible slides)
12549		 */
12550		var getNumberSlidesShowing = function(){
12551			var slidesShowing = 1;
12552			if(slider.settings.mode === 'horizontal' && slider.settings.slideWidth > 0){
12553				// if viewport is smaller than minThreshold, return minSlides
12554				if(slider.viewport.width() < slider.minThreshold){
12555					slidesShowing = slider.settings.minSlides;
12556				// if viewport is larger than maxThreshold, return maxSlides
12557				}else if(slider.viewport.width() > slider.maxThreshold){
12558					slidesShowing = slider.settings.maxSlides;
12559				// if viewport is between min / max thresholds, divide viewport width by first child width
12560				}else{
12561					var childWidth = slider.children.first().width() + slider.settings.slideMargin;
12562					slidesShowing = Math.floor((slider.viewport.width() +
12563						slider.settings.slideMargin) / childWidth);
12564				}
12565			// if "vertical" mode, slides showing will always be minSlides
12566			}else if(slider.settings.mode === 'vertical'){
12567				slidesShowing = slider.settings.minSlides;
12568			}
12569			return slidesShowing;
12570		};
12571
12572		/**
12573		 * Returns the number of pages (one full viewport of slides is one "page")
12574		 */
12575		var getPagerQty = function(){
12576			var pagerQty = 0;
12577			// if moveSlides is specified by the user
12578			if(slider.settings.moveSlides > 0){
12579				if(slider.settings.infiniteLoop){
12580					pagerQty = Math.ceil(slider.children.length / getMoveBy());
12581				}else{
12582					// use a while loop to determine pages
12583					var breakPoint = 0;
12584					var counter = 0;
12585					// when breakpoint goes above children length, counter is the number of pages
12586					while (breakPoint < slider.children.length){
12587						++pagerQty;
12588						breakPoint = counter + getNumberSlidesShowing();
12589						counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing();
12590					}
12591				}
12592			// if moveSlides is 0 (auto) divide children length by sides showing, then round up
12593			}else{
12594				pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing());
12595			}
12596			return pagerQty;
12597		};
12598
12599		/**
12600		 * Returns the number of individual slides by which to shift the slider
12601		 */
12602		var getMoveBy = function(){
12603			// if moveSlides was set by the user and moveSlides is less than number of slides showing
12604			if(slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()){
12605				return slider.settings.moveSlides;
12606			}
12607			// if moveSlides is 0 (auto)
12608			return getNumberSlidesShowing();
12609		};
12610
12611    /**
12612     * Adds an aria-hidden=true attribute to each element
12613     *
12614     * @param startVisibleIndex (int)
12615     *  - the first visible element's index
12616     */
12617    var applyAriaHiddenAttributes = function(startVisibleIndex) {
12618      var numberOfSlidesShowing = getNumberSlidesShowing();
12619      // only apply attributes if the setting is enabled and not in ticker mode
12620      if (slider.settings.ariaHidden && !slider.settings.ticker) {
12621        // add aria-hidden=true to all elements
12622        slider.children.attr('aria-hidden', 'true');
12623        // get the visible elements and change to aria-hidden=false
12624        slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).attr('aria-hidden', 'false');
12625      }
12626    };		
12627
12628		/**
12629		 * Sets the slider's (el) left or top position
12630		 */
12631		var setSlidePosition = function(){
12632			var position;
12633			// if last slide, not infinite loop, and number of children is larger than specified maxSlides
12634			if(slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop){
12635				if(slider.settings.mode === 'horizontal'){
12636					// get the last child's position
12637					var lastChild = slider.children.last();
12638					position = lastChild.position();
12639					// set the left position
12640					setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0);
12641				}else if(slider.settings.mode === 'vertical'){
12642					// get the last showing index's position
12643					var lastShowingIndex = slider.children.length - slider.settings.minSlides;
12644					position = slider.children.eq(lastShowingIndex).position();
12645					// set the top position
12646					setPositionProperty(-position.top, 'reset', 0);
12647				}
12648			// if not last slide
12649			}else{
12650				// get the position of the first showing slide
12651				position = slider.children.eq(slider.active.index * getMoveBy()).position();
12652				// check for last slide
12653				if(slider.active.index === getPagerQty() - 1){ slider.active.last = true; }
12654				// set the respective position
12655				if(position !== undefined){
12656					if(slider.settings.mode === 'horizontal'){ setPositionProperty(-position.left, 'reset', 0); }
12657					else if(slider.settings.mode === 'vertical'){ setPositionProperty(-position.top, 'reset', 0); }
12658				}
12659			}
12660		};
12661
12662		/**
12663		 * Sets the el's animating property position (which in turn will sometimes animate el).
12664		 * If using CSS, sets the transform property. If not using CSS, sets the top / left property.
12665		 *
12666		 * @param value (int)
12667		 *  - the animating property's value
12668		 *
12669		 * @param type (string) 'slide', 'reset', 'ticker'
12670		 *  - the type of instance for which the function is being
12671		 *
12672		 * @param duration (int)
12673		 *  - the amount of time (in ms) the transition should occupy
12674		 *
12675		 * @param params (array) optional
12676		 *  - an optional parameter containing any variables that need to be passed in
12677		 */
12678		var setPositionProperty = function(value, type, duration, params){
12679			// use CSS transform
12680			if(slider.usingCSS){
12681				// determine the translate3d value
12682				var propValue = slider.settings.mode === 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)';
12683				// add the CSS transition-duration
12684				el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's');
12685				if(type === 'slide'){
12686					setTimeout(function() {
12687						// set the property value
12688						el.css(slider.animProp, propValue);
12689						// if value 0, just update
12690						if(value === 0) {
12691							updateAfterSlideTransition();
12692						} else {
12693							// bind a callback method - executes when CSS transition completes
12694							el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){
12695								// unbind the callback
12696								el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
12697								updateAfterSlideTransition();
12698							});
12699						}
12700					}, 0);
12701				}else if(type === 'reset'){
12702					el.css(slider.animProp, propValue);
12703				}else if(type === 'ticker'){
12704					// make the transition use 'linear'
12705					el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear');
12706					el.css(slider.animProp, propValue);
12707					// bind a callback method - executes when CSS transition completes
12708					el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){
12709						// unbind the callback
12710						el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
12711						// reset the position
12712						setPositionProperty(params.resetValue, 'reset', 0);
12713						// start the loop again
12714						tickerLoop();
12715					});
12716				}
12717			// use JS animate
12718			}else{
12719				var animateObj = {};
12720				animateObj[slider.animProp] = value;
12721				if(type === 'slide'){
12722					el.animate(animateObj, duration, slider.settings.easing, function(){
12723						updateAfterSlideTransition();
12724					});
12725				}else if(type === 'reset'){
12726					el.css(slider.animProp, value);
12727				}else if(type === 'ticker'){
12728					el.animate(animateObj, speed, 'linear', function(){
12729						setPositionProperty(params.resetValue, 'reset', 0);
12730						// run the recursive loop after animation
12731						tickerLoop();
12732					});
12733				}
12734			}
12735		};
12736
12737		/**
12738		 * Populates the pager with proper amount of pages
12739		 */
12740		var populatePager = function(){
12741			var pagerHtml = '';
12742			var pagerQty = getPagerQty();
12743			// loop through each pager item
12744			for(var i=0; i < pagerQty; i++){
12745				var linkContent = '';
12746				// if a buildPager function is supplied, use it to get pager link value, else use index + 1
12747				if(slider.settings.buildPager && $.isFunction(slider.settings.buildPager) || slider.settings.pagerCustom){
12748					linkContent = slider.settings.buildPager(i);
12749					slider.pagerEl.addClass('bx-custom-pager');
12750				}else{
12751					linkContent = i + 1;
12752					slider.pagerEl.addClass('bx-default-pager');
12753				}
12754				// var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1;
12755				// add the markup to the string
12756				pagerHtml += '<div class="bx-pager-item">
vendor: 8,252 bytes, lines 12756-12995
12756<a href="" data-slide-index="' + i + '" class="bx-pager-link">' + linkContent + '</a></div>';
12757			}
12758			// populate the pager element with pager links
12759			slider.pagerEl.html(pagerHtml);
12760		};
12761
12762		/**
12763		 * Appends the pager to the controls element
12764		 */
12765		var appendPager = function(){
12766			if(!slider.settings.pagerCustom){
12767				// create the pager DOM element
12768				slider.pagerEl = $('<div class="bx-pager" />');
12769				// if a pager selector was supplied, populate it with the pager
12770				if(slider.settings.pagerSelector){
12771					$(slider.settings.pagerSelector).html(slider.pagerEl);
12772				// if no pager selector was supplied, add it after the wrapper
12773				}else{
12774					slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl);
12775				}
12776				// populate the pager
12777				populatePager();
12778			}else{
12779				slider.pagerEl = $(slider.settings.pagerCustom);
12780			}
12781			// assign the pager click binding
12782			slider.pagerEl.on('click touchend', 'a', clickPagerBind);
12783		};
12784
12785		/**
12786		 * Appends prev / next controls to the controls element
12787		 */
12788		var appendControls = function(){
12789			slider.controls.next = $('<a class="bx-next" href="">' + slider.settings.nextText + '</a>');
12790			slider.controls.prev = $('<a class="bx-prev" href="">' + slider.settings.prevText + '</a>');
12791			// bind click actions to the controls
12792			slider.controls.next.bind('click touchend', clickNextBind);
12793			slider.controls.prev.bind('click touchend', clickPrevBind);
12794			// if nextSelector was supplied, populate it
12795			if(slider.settings.nextSelector){
12796				$(slider.settings.nextSelector).append(slider.controls.next);
12797			}
12798			// if prevSelector was supplied, populate it
12799			if(slider.settings.prevSelector){
12800				$(slider.settings.prevSelector).append(slider.controls.prev);
12801			}
12802			// if no custom selectors were supplied
12803			if(!slider.settings.nextSelector && !slider.settings.prevSelector){
12804				// add the controls to the DOM
12805				slider.controls.directionEl = $('<div class="bx-controls-direction" />');
12806				// add the control elements to the directionEl
12807				slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next);
12808				// slider.viewport.append(slider.controls.directionEl);
12809				slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl);
12810			}
12811		};
12812
12813		/**
12814		 * Appends start / stop auto controls to the controls element
12815		 */
12816		var appendControlsAuto = function(){
12817			slider.controls.start = $('<div class="bx-controls-auto-item"><a class="bx-start" href="">' + slider.settings.startText + '</a></div>');
12818			slider.controls.stop = $('<div class="bx-controls-auto-item"><a class="bx-stop" href="">' + slider.settings.stopText + '</a></div>');
12819			// add the controls to the DOM
12820			slider.controls.autoEl = $('<div class="bx-controls-auto" />');
12821			// bind click actions to the controls
12822			slider.controls.autoEl.on('click', '.bx-start', clickStartBind);
12823			slider.controls.autoEl.on('click', '.bx-stop', clickStopBind);
12824			// if autoControlsCombine, insert only the "start" control
12825			if(slider.settings.autoControlsCombine){
12826				slider.controls.autoEl.append(slider.controls.start);
12827			// if autoControlsCombine is false, insert both controls
12828			}else{
12829				slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop);
12830			}
12831			// if auto controls selector was supplied, populate it with the controls
12832			if(slider.settings.autoControlsSelector){
12833				$(slider.settings.autoControlsSelector).html(slider.controls.autoEl);
12834			// if auto controls selector was not supplied, add it after the wrapper
12835			}else{
12836				slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl);
12837			}
12838			// update the auto controls
12839			updateAutoControls(slider.settings.autoStart ? 'stop' : 'start');
12840		};
12841
12842		/**
12843		 * Appends image captions to the DOM
12844		 */
12845		var appendCaptions = function(){
12846			// cycle through each child
12847			slider.children.each(function(index){
12848				// get the image title attribute
12849				var title = $(this).find('img:first').attr('title');
12850				// append the caption
12851				if(title !== undefined && ('' + title).length){
12852					$(this).append('<div class="bx-caption"><span>' + title + '</span></div>');
12853				}
12854			});
12855		};
12856
12857		/**
12858		 * Click next binding
12859		 *
12860		 * @param e (event)
12861		 *  - DOM event object
12862		 */
12863		var clickNextBind = function(e){
12864			e.preventDefault();
12865			if (slider.controls.el.hasClass('disabled')) {
12866				return;
12867			}
12868			// if auto show is running, stop it
12869			if(slider.settings.auto){ el.stopAuto(); }
12870			el.goToNextSlide();
12871		};
12872
12873		/**
12874		 * Click prev binding
12875		 *
12876		 * @param e (event)
12877		 *  - DOM event object
12878		 */
12879		var clickPrevBind = function(e){
12880			e.preventDefault();
12881			if (slider.controls.el.hasClass('disabled')) {
12882				return;
12883			}
12884			// if auto show is running, stop it
12885			if(slider.settings.auto){ el.stopAuto(); }
12886			el.goToPrevSlide();
12887		};
12888
12889		/**
12890		 * Click start binding
12891		 *
12892		 * @param e (event)
12893		 *  - DOM event object
12894		 */
12895		var clickStartBind = function(e){
12896			el.startAuto();
12897			e.preventDefault();
12898		};
12899
12900		/**
12901		 * Click stop binding
12902		 *
12903		 * @param e (event)
12904		 *  - DOM event object
12905		 */
12906		var clickStopBind = function(e){
12907			el.stopAuto();
12908			e.preventDefault();
12909		};
12910
12911		/**
12912		 * Click pager binding
12913		 *
12914		 * @param e (event)
12915		 *  - DOM event object
12916		 */
12917		var clickPagerBind = function(e){
12918			e.preventDefault();
12919			if (slider.controls.el.hasClass('disabled')) {
12920				return;
12921			}
12922			// if auto show is running, stop it
12923			if(slider.settings.auto){ el.stopAuto(); }
12924			var pagerLink = $(e.currentTarget);
12925			if(pagerLink.attr('data-slide-index') !== undefined){
12926				var pagerIndex = parseInt(pagerLink.attr('data-slide-index'));
12927				// if clicked pager link is not active, continue with the goToSlide call
12928				if(pagerIndex !== slider.active.index){ el.goToSlide(pagerIndex); }
12929			}
12930		};
12931
12932		/**
12933		 * Updates the pager links with an active class
12934		 *
12935		 * @param slideIndex (int)
12936		 *  - index of slide to make active
12937		 */
12938		var updatePagerActive = function(slideIndex){
12939			// if "short" pager type
12940			var len = slider.children.length; // nb of children
12941			if(slider.settings.pagerType === 'short'){
12942				if(slider.settings.maxSlides > 1){
12943					len = Math.ceil(slider.children.length/slider.settings.maxSlides);
12944				}
12945				slider.pagerEl.html( (slideIndex + 1) + slider.settings.pagerShortSeparator + len);
12946				return;
12947			}
12948			// remove all pager active classes
12949			slider.pagerEl.find('a').removeClass('active');
12950			// apply the active class for all pagers
12951			slider.pagerEl.each(function(i, el){ $(el).find('a').eq(slideIndex).addClass('active'); });
12952		};
12953
12954		/**
12955		 * Performs needed actions after a slide transition
12956		 */
12957		var updateAfterSlideTransition = function(){
12958			// if infinite loop is true
12959			if(slider.settings.infiniteLoop){
12960				var position = '';
12961				// first slide
12962				if(slider.active.index === 0){
12963					// set the new position
12964					position = slider.children.eq(0).position();
12965				// carousel, last slide
12966				}else if(slider.active.index === getPagerQty() - 1 && slider.carousel){
12967					position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position();
12968				// last slide
12969				}else if(slider.active.index === slider.children.length - 1){
12970					position = slider.children.eq(slider.children.length - 1).position();
12971				}
12972				if(position){
12973					if(slider.settings.mode === 'horizontal'){ setPositionProperty(-position.left, 'reset', 0); }
12974					else if(slider.settings.mode === 'vertical'){ setPositionProperty(-position.top, 'reset', 0); }
12975				}
12976			}
12977			// declare that the transition is complete
12978			slider.working = false;
12979			// onSlideAfter callback
12980			slider.settings.onSlideAfter(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
12981		};
12982
12983		/**
12984		 * Updates the auto controls state (either active, or combined switch)
12985		 *
12986		 * @param state (string) "start", "stop"
12987		 *  - the new state of the auto show
12988		 */
12989		var updateAutoControls = function(state){
12990			// if autoControlsCombine is true, replace the current control with the new state
12991			if(slider.settings.autoControlsCombine){
12992				slider.controls.autoEl.html(slider.controls[state]);
12993			// if autoControlsCombine is false, apply the "active" class to the appropriate control
12994			}else{
12995				slider.controls.autoEl.find('a').removeClass('active');
12996				slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active');
12997			}
12998		};
12999
13000		/**
13001		 * Updates the direction controls (checks if either should be hidden)
13002		 */
13003		var updateDirectionControls = function(){
13004			if(getPagerQty() === 1){
13005				slider.controls.prev.addClass('disabled');
13006				slider.controls.next.addClass('disabled');
13007			}else if(!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd){
13008				// if first slide
13009				if(slider.active.index === 0){
13010					slider.controls.prev.addClass('disabled');
13011					slider.controls.next.removeClass('disabled');
13012				// if last slide
13013				}else if(slider.active.index === getPagerQty() - 1){
13014					slider.controls.next.addClass('disabled');
13015					slider.controls.prev.removeClass('disabled');
13016				// if any slide in the middle
13017				}else{
13018					slider.controls.prev.removeClass('disabled');
13019					slider.controls.next.removeClass('disabled');
13020				}
13021			}
13022		};
13023
13024		/**
13025		 * Initializes the auto process
13026		 */
13027		var initAuto = function(){
13028			// if autoDelay was supplied, launch the auto show using a setTimeout() call
13029			if(slider.settings.autoDelay > 0){
13030				var timeout = setTimeout(el.startAuto, slider.settings.autoDelay);
13031			// if autoDelay was not supplied, start the auto show normally
13032			}else{
13033				el.startAuto();
13034
13035				//add focus and blur events to ensure its running if timeout gets paused
13036				$(window).focus(function() {
13037					el.startAuto();
13038				}).blur(function() {
13039					el.stopAuto();
13040				});
13041
13042
13043			}
13044			// if autoHover is requested
13045			if(slider.settings.autoHover){
13046				// on el hover
13047				el.hover(function(){
13048					// if the auto show is currently playing (has an active interval)
13049					if(slider.interval){
13050						// stop the auto show and pass true argument which will prevent control update
13051						el.stopAuto(true);
13052						// create a new autoPaused value which will be used by the relative "mouseout" event
13053						slider.autoPaused = true;
13054					}
13055				}, function(){
13056					// if the autoPaused value was created be the prior "mouseover" event
13057					if(slider.autoPaused){
13058						// start the auto show and pass true argument which will prevent control update
13059						el.startAuto(true);
13060						// reset the autoPaused value
13061						slider.autoPaused = null;
13062					}
13063				});
13064			}
13065		};
13066
13067		/**
13068		 * Initializes the ticker process
13069		 */
13070		var initTicker = function(){
13071			var startPosition = 0;
13072			// if autoDirection is "next", append a clone of the entire slider
13073			if(slider.settings.autoDirection === 'next'){
13074				el.append(slider.children.clone().addClass('bx-clone'));
13075			// if autoDirection is "prev", prepend a clone of the entire slider, and set the left position
13076			}else{
13077				el.prepend(slider.children.clone().addClass('bx-clone'));
13078				var position = slider.children.first().position();
13079				startPosition = slider.settings.mode === 'horizontal' ? -position.left : -position.top;
13080			}
13081			setPositionProperty(startPosition, 'reset', 0);
13082			// do not allow controls in ticker mode
13083			slider.settings.pager = false;
13084			slider.settings.controls = false;
13085			slider.settings.autoControls = false;
13086			// if autoHover is requested
13087			if(slider.settings.tickerHover){
13088				if(slider.usingCSS){
13089					var value;
13090					var idx = slider.settings.mode == 'horizontal' ? 4 : 5;
13091					slider.viewport.hover(function(){
13092						var transform = el.css('-' + slider.cssPrefix + '-transform');
13093						value = parseFloat(transform.split(',')[idx]);
13094						setPositionProperty(value, 'reset', 0);
13095					}, function(){
13096						var totalDimens = 0;
13097						slider.children.each(function(index){
13098						  totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
13099						});
13100						// calculate the speed ratio (used to determine the new speed to finish the paused animation)
13101						var ratio = slider.settings.speed / totalDimens;
13102						// determine which property to use
13103						var property = slider.settings.mode == 'horizontal' ? 'left' : 'top';
13104						// calculate the new speed
13105						var newSpeed = ratio * (totalDimens - (Math.abs(parseInt(value))));
13106						tickerLoop(newSpeed);
13107					});
13108				} else {
13109					// on el hover
13110					slider.viewport.hover(function(){
13111						el.stop();
13112					}, function(){
13113						// calculate the total width of children (used to calculate the speed ratio)
13114						var totalDimens = 0;
13115						slider.children.each(function(index){
13116						  totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
13117						});
13118						// calculate the speed ratio (used to determine the new speed to finish the paused animation)
13119						var ratio = slider.settings.speed / totalDimens;
13120						// determine which property to use
13121						var property = slider.settings.mode == 'horizontal' ? 'left' : 'top';
13122						// calculate the new speed
13123						var newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property)))));
13124						tickerLoop(newSpeed);
13125					});
13126				}
13127			}
13128			// start the ticker loop
13129			tickerLoop();
13130		};
13131
13132		/**
13133		 * Runs a continuous loop, news ticker-style
13134		 */
13135		var tickerLoop = function(resumeSpeed){
13136			speed = resumeSpeed ? resumeSpeed : slider.settings.speed;
13137			var position = {left: 0, top: 0};
13138			var reset = {left: 0, top: 0};
13139			// if "next" animate left position to last child, then reset left to 0
13140			if(slider.settings.autoDirection === 'next'){
13141				position = el.find('.bx-clone').first().position();
13142			// if "prev" animate left position to 0, then reset left to first non-clone child
13143			}else{
13144				reset = slider.children.first().position();
13145			}
13146			var animateProperty = slider.settings.mode === 'horizontal' ? -position.left : -position.top;
13147			var resetValue = slider.settings.mode === 'horizontal' ? -reset.left : -reset.top;
13148			var params = {resetValue: resetValue};
13149			setPositionProperty(animateProperty, 'ticker', speed, params);
13150		};
13151
13152		/**
13153		 * Check if el is on screen
13154		 */
13155		var isOnScreen = function(el){
13156			var win = $(window);
13157			var viewport = {
13158				top : win.scrollTop(),
13159				left : win.scrollLeft()
13160			};
13161			viewport.right = viewport.left + win.width();
13162			viewport.bottom = viewport.top + win.height();
13163
13164			var bounds = el.offset();
13165			bounds.right = bounds.left + el.outerWidth();
13166			bounds.bottom = bounds.top + el.outerHeight();
13167
13168			return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
13169		};
13170
13171		/**
13172		 * Initializes keyboard events
13173		 */
13174		var keyPress = function(e){
13175			var activeElementTag = document.activeElement.tagName.toLowerCase();
13176			var tagFilters='input|textarea';
13177			var p = new RegExp(activeElementTag,["i"]);
13178			var result = p.exec(tagFilters);
13179			if (result == null && isOnScreen(el)) {
13180				if (e.keyCode == 39) {
13181					clickNextBind(e);
13182					return false;
13183				}
13184				else if (e.keyCode == 37) {
13185					clickPrevBind(e);
13186					return false;
13187				}
13188			}
13189		};
13190
13191		/**
13192		 * Initializes touch events
13193		 */
13194		var initTouch = function(){
13195			// initialize object to contain all touch values
13196			slider.touch = {
13197				start: {x: 0, y: 0},
13198				end: {x: 0, y: 0}
13199			};
13200			slider.viewport.bind('touchstart MSPointerDown pointerdown', onTouchStart);
13201
13202			//for browsers that have implemented pointer events and fire a click after
13203			//every pointerup regardless of whether pointerup is on same screen location as pointerdown or not
13204			slider.viewport.on('click', '.bxslider a', function(e) {
13205				if (slider.viewport.hasClass('click-disabled')) {
13206					e.preventDefault();
13207					slider.viewport.removeClass('click-disabled');
13208				}
13209			});
13210		};
13211
13212		/**
13213		 * Event handler for "touchstart"
13214		 *
13215		 * @param e (event)
13216		 *  - DOM event object
13217		 */
13218		var onTouchStart = function(e){
13219			//disable slider controls while user is interacting with slides to avoid slider freeze that happens on touch devices when a slide swipe happens immediately after interacting with slider controls
13220			slider.controls.el.addClass('disabled');
13221
13222			if(slider.working){
13223				e.preventDefault();
13224				slider.controls.el.removeClass('disabled');
13225			}else{
13226				// record the original position when touch starts
13227				slider.touch.originalPos = el.position();
13228				var orig = e.originalEvent;
13229				var touchPoints = (typeof orig.changedTouches != 'undefined') ? orig.changedTouches : [orig];
13230				// record the starting touch x, y coordinates
13231				slider.touch.start.x = touchPoints[0].pageX;
13232				slider.touch.start.y = touchPoints[0].pageY;
13233
13234				if (slider.viewport.get(0).setPointerCapture) {
13235					slider.pointerId = orig.pointerId;
13236					slider.viewport.get(0).setPointerCapture(slider.pointerId);
13237				}
13238				// bind a "touchmove" event to the viewport
13239				slider.viewport.bind('touchmove MSPointerMove pointermove', onTouchMove);
13240				// bind a "touchend" event to the viewport
13241				slider.viewport.bind('touchend MSPointerUp pointerup', onTouchEnd);
13242				slider.viewport.bind('MSPointerCancel pointercancel', onPointerCancel);
13243			}
13244		};
13245
13246		/**
13247		 * Cancel Pointer for Windows Phone
13248		 *
13249		 * @param e (event)
13250		 *  - DOM event object
13251		 */
13252		var onPointerCancel = function(e) {
13253		/* onPointerCancel handler is needed to deal with situations when a touchend
13254		doesn't fire after a touchstart (this happens on windows phones only) */
13255			setPositionProperty(slider.touch.originalPos.left, 'reset', 0);
13256
13257			//remove handlers
13258			slider.controls.el.removeClass('disabled');
13259			slider.viewport.unbind('MSPointerCancel pointercancel', onPointerCancel);
13260			slider.viewport.unbind('touchmove MSPointerMove pointermove', onTouchMove);
13261			slider.viewport.unbind('touchend MSPointerUp pointerup', onTouchEnd);
13262			if (slider.viewport.get(0).releasePointerCapture) {
13263				slider.viewport.get(0).releasePointerCapture(slider.pointerId);
13264 			}
13265		}
13266
13267		/**
13268		 * Event handler for "touchmove"
13269		 *
13270		 * @param e (event)
13271		 *  - DOM event object
13272		 */
13273		var onTouchMove = function(e){
13274			var orig = e.originalEvent;
13275			var touchPoints = (typeof orig.changedTouches != 'undefined') ? orig.changedTouches : [orig];
13276			// if scrolling on y axis, do not prevent default
13277			var xMovement = Math.abs(touchPoints[0].pageX - slider.touch.start.x);
13278			var yMovement = Math.abs(touchPoints[0].pageY - slider.touch.start.y);
13279			// x axis swipe
13280			if((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX){
13281				e.preventDefault();
13282			// y axis swipe
13283			}else if((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY){
13284				e.preventDefault();
13285			}
13286			if(slider.settings.mode !== 'fade' && slider.settings.oneToOneTouch){
13287				var value = 0, change = 0;
13288				// if horizontal, drag along x axis
13289				if(slider.settings.mode === 'horizontal'){
13290					change = touchPoints[0].pageX - slider.touch.start.x;
13291					value = slider.touch.originalPos.left + change;
13292				// if vertical, drag along y axis
13293				}else{
13294					change = touchPoints[0].pageY - slider.touch.start.y;
13295					value = slider.touch.originalPos.top + change;
13296				}
13297				setPositionProperty(value, 'reset', 0);
13298			}
13299		};
13300
13301		/**
13302		 * Event handler for "touchend"
13303		 *
13304		 * @param e (event)
13305		 *  - DOM event object
13306		 */
13307		var onTouchEnd = function(e){
13308			slider.viewport.unbind('touchmove MSPointerMove pointermove', onTouchMove);
13309			//enable slider controls as soon as user stops interacing with slides
13310			slider.controls.el.removeClass('disabled');
13311			var orig = e.originalEvent;
13312			var touchPoints = (typeof orig.changedTouches != 'undefined') ? orig.changedTouches : [orig];
13313			var value = 0;
13314			var distance = 0;
13315			// record end x, y positions
13316			slider.touch.end.x = touchPoints[0].pageX;
13317			slider.touch.end.y = touchPoints[0].pageY;
13318			// if fade mode, check if absolute x distance clears the threshold
13319			if(slider.settings.mode === 'fade'){
13320				distance = Math.abs(slider.touch.start.x - slider.touch.end.x);
13321				if(distance >= slider.settings.swipeThreshold){
13322					if(slider.touch.start.x > slider.touch.end.x){
13323						el.goToNextSlide();
13324					} else {
13325						el.goToPrevSlide();
13326					}
13327					el.stopAuto();
13328				}
13329			// not fade mode
13330			}else{
13331				// calculate distance and el's animate property
13332				if(slider.settings.mode === 'horizontal'){
13333					distance = slider.touch.end.x - slider.touch.start.x;
13334					value = slider.touch.originalPos.left;
13335				}else{
13336					distance = slider.touch.end.y - slider.touch.start.y;
13337					value = slider.touch.originalPos.top;
13338				}
13339				// if not infinite loop and first / last slide, do not attempt a slide transition
13340				if(!slider.settings.infiniteLoop && ((slider.active.index === 0 && distance > 0) || (slider.active.last && distance < 0))){
13341					setPositionProperty(value, 'reset', 200);
13342				}else{
13343					// check if distance clears threshold
13344					if(Math.abs(distance) >= slider.settings.swipeThreshold){
13345						if(distance < 0){
13346							el.goToNextSlide();
13347						} else {
13348							el.goToPrevSlide();
13349						}
13350						el.stopAuto();
13351					}else{
13352						// el.animate(property, 200);
13353						setPositionProperty(value, 'reset', 200);
13354					}
13355				}
13356			}
13357			slider.viewport.unbind('touchend MSPointerUp pointerup', onTouchEnd);
13358			if (slider.viewport.get(0).releasePointerCapture) {
13359				slider.viewport.get(0).releasePointerCapture(slider.pointerId);
13360			}
13361		};
13362
13363		/**
13364		 * Window resize event callback
13365		 */
13366		var resizeWindow = function(e){
13367			// don't do anything if slider isn't initialized.
13368			if(!slider.initialized){ return; }
13369			// Delay if slider working.
13370			if (slider.working) {
13371				window.setTimeout(resizeWindow, 10);
13372			} else {
13373				// get the new window dimens (again, thank you IE)
13374				var windowWidthNew = $(window).width();
13375				var windowHeightNew = $(window).height();
13376				// make sure that it is a true window resize
13377				// *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements
13378				// are resized. Can you just die already?*
13379				if(windowWidth !== windowWidthNew || windowHeight !== windowHeightNew){
13380					// set the new window dimens
13381					windowWidth = windowWidthNew;
13382					windowHeight = windowHeightNew;
13383					// update all dynamic elements
13384					el.redrawSlider();
13385					// Call user resize handler
13386					slider.settings.onSliderResize.call(el, slider.active.index);
13387				}
13388			}
13389		};
13390
13391		/**
13392		 * ===================================================================================
13393		 * = PUBLIC FUNCTIONS
13394		 * ===================================================================================
13395		 */
13396
13397		/*
13398		 * Animates the viewport adaptive height to the correct height
13399		 */
13400		el.animateViewportAdaptiveHeight = function() {
13401		  slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
13402		};
13403
13404		/**
13405		 * Performs slide transition to the specified slide
13406		 *
13407		 * @param slideIndex (int)
13408		 *  - the destination slide's index (zero-based)
13409		 *
13410		 * @param direction (string)
13411		 *  - INTERNAL USE ONLY - the direction of travel ("prev" / "next")
13412		 */
13413		el.goToSlide = function(slideIndex, direction){
13414			// if plugin is currently in motion, ignore request
13415			if(slider.working || slider.active.index === slideIndex){ return; }
13416			// declare that plugin is in motion
13417			slider.working = true;
13418			// store the old index
13419			slider.oldIndex = slider.active.index;
13420			// if slideIndex is less than zero, set active index to last child (this happens during infinite loop)
13421			if(slideIndex < 0){
13422				slider.active.index = getPagerQty() - 1;
13423			// if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop)
13424			}else if(slideIndex >= getPagerQty()){
13425				slider.active.index = 0;
13426			// set active index to requested slide
13427			}else{
13428				slider.active.index = slideIndex;
13429			}
13430			// onSlideBefore, onSlideNext, onSlidePrev callbacks
13431			// Allow transition canceling based on returned value
13432			var performTransition = true;
13433
13434			performTransition = slider.settings.onSlideBefore(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
13435
13436			if ( typeof(performTransition) !== "undefined" && !performTransition ) {
13437				slider.active.index = slider.oldIndex; // restore old index
13438				slider.working = false; // is not in motion
13439				return;
13440			}
13441			if(direction === 'next'){
13442				// Prevent canceling in future functions or lack there-of from negating previous commands to cancel
13443				if(!slider.settings.onSlideNext(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)){
13444					performTransition = false;
13445				}
13446			}else if(direction === 'prev'){
13447				// Prevent canceling in future functions or lack there-of from negating previous commands to cancel
13448				if(!slider.settings.onSlidePrev(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)){
13449					performTransition = false;
13450				}
13451			}
13452
13453			// If transitions canceled, reset and return
13454			if ( typeof(performTransition) !== "undefined" && !performTransition ) {
13455				slider.active.index = slider.oldIndex; // restore old index
13456				slider.working = false; // is not in motion
13457				return;
13458			}
13459
13460			// check if last slide
13461			slider.active.last = slider.active.index >= getPagerQty() - 1;
13462			// update the pager with active class
13463			if(slider.settings.pager || slider.settings.pagerCustom){ updatePagerActive(slider.active.index); }
13464			// // check for direction control update
13465			if(slider.settings.controls){ updateDirectionControls(); }
13466			// if slider is set to mode: "fade"
13467			if(slider.settings.mode === 'fade'){
13468				// if adaptiveHeight is true and next height is different from current height, animate to the new height
13469				if(slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()){
13470					el.animateViewportAdaptiveHeight();
13471				}
13472				// fade out the visible child and reset its z-index value
13473				slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0});
13474				// fade in the newly requested slide
13475				slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex+1).fadeIn(slider.settings.speed, function(){
13476					$(this).css('zIndex', slider.settings.slideZIndex);
13477					updateAfterSlideTransition();
13478				});
13479			// slider mode is not "fade"
13480			}else{
13481				// if adaptiveHeight is true and next height is different from current height, animate to the new height
13482				if(slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()){
13483					el.animateViewportAdaptiveHeight();
13484				}
13485				var moveBy = 0;
13486				var position = {left: 0, top: 0};
13487				var lastChild = null;
13488				// if carousel and not infinite loop
13489				if(!slider.settings.infiniteLoop && slider.carousel && slider.active.last){
13490					if(slider.settings.mode === 'horizontal'){
13491						// get the last child position
13492						lastChild = slider.children.eq(slider.children.length - 1);
13493						position = lastChild.position();
13494						// calculate the position of the last slide
13495						moveBy = slider.viewport.width() - lastChild.outerWidth();
13496					}else{
13497						// get last showing index position
13498						var lastShowingIndex = slider.children.length - slider.settings.minSlides;
13499						position = slider.children.eq(lastShowingIndex).position();
13500					}
13501					// horizontal carousel, going previous while on first slide (infiniteLoop mode)
13502				}else if(slider.carousel && slider.active.last && direction === 'prev'){
13503					// get the last child position
13504					var eq = slider.settings.moveSlides === 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides);
13505					lastChild = el.children('.bx-clone').eq(eq);
13506					position = lastChild.position();
13507				// if infinite loop and "Prev" is clicked on the first slide
13508				}else if(direction === 'prev' && slider.active.last){
13509					// get the first clone position
13510					position = el.find('> .bx-clone').eq(0).position();
13511					slider.active.last = true;
13512				// if infinite loop and "Next" is clicked on the last slide
13513				}else if(direction === 'next' && slider.active.index === 0){
13514					// get the last clone position
13515					position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position();
13516					slider.active.last = false;
13517				// normal non-zero requests
13518				}else if(slideIndex >= 0){
13519					var requestEl = slideIndex * getMoveBy();
13520					position = slider.children.eq(requestEl).position();
13521				}
13522
13523
13524				/* If the position doesn't exist
13525				 * (e.g. if you destroy the slider on a next click),
13526				 * it doesn't throw an error.
13527				 */
13528				if("undefined" !== typeof(position)){
13529					var value = slider.settings.mode === 'horizontal' ? -(position.left - moveBy) : -position.top;
13530					// plugin values to be animated
13531					setPositionProperty(value, 'slide', slider.settings.speed);
13532				}
13533			}
13534
13535			if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); }
13536		};
13537
13538		/**
13539		 * Transitions to the next slide in the show
13540		 */
13541		el.goToNextSlide = function(){
13542			// if infiniteLoop is false and last page is showing, disregard call
13543			if(!slider.settings.infiniteLoop && slider.active.last){ return; }
13544			var pagerIndex = parseInt(slider.active.index) + 1;
13545			el.goToSlide(pagerIndex, 'next');
13546		};
13547
13548		/**
13549		 * Transitions to the prev slide in the show
13550		 */
13551		el.goToPrevSlide = function(){
13552			// if infiniteLoop is false and last page is showing, disregard call
13553			if(!slider.settings.infiniteLoop && slider.active.index === 0){ return; }
13554			var pagerIndex = parseInt(slider.active.index) - 1;
13555			el.goToSlide(pagerIndex, 'prev');
13556		};
13557
13558		/**
13559		 * Starts the auto show
13560		 *
13561		 * @param preventControlUpdate (boolean)
13562		 *  - if true, auto controls state will not be updated
13563		 */
13564		el.startAuto = function(preventControlUpdate){
13565			// if an interval already exists, disregard call
13566			if(slider.interval){ return; }
13567			// create an interval
13568			slider.interval = setInterval(function(){
13569				if(slider.settings.autoDirection === 'next'){
13570					el.goToNextSlide();
13571				}else{
13572					el.goToPrevSlide();
13573				}
13574			}, slider.settings.pause);
13575			// if auto controls are displayed and preventControlUpdate is not true
13576			if(slider.settings.autoControls && preventControlUpdate !== true){ updateAutoControls('stop'); }
13577		};
13578
13579		/**
13580		 * Stops the auto show
13581		 *
13582		 * @param preventControlUpdate (boolean)
13583		 *  - if true, auto controls state will not be updated
13584		 */
13585		el.stopAuto = function(preventControlUpdate){
13586			// if no interval exists, disregard call
13587			if(!slider.interval){ return; }
13588			// clear the interval
13589			clearInterval(slider.interval);
13590			slider.interval = null;
13591			// if auto controls are displayed and preventControlUpdate is not true
13592			if(slider.settings.autoControls && preventControlUpdate !== true){ updateAutoControls('start'); }
13593		};
13594
13595		/**
13596		 * Returns current slide index (zero-based)
13597		 */
13598		el.getCurrentSlide = function(){
13599			return slider.active.index;
13600		};
13601
13602		/**
13603		 * Returns current slide element
13604		 */
13605		el.getCurrentSlideElement = function(){
13606			return slider.children.eq(slider.active.index);
13607		};
13608
13609		/**
13610		 * Returns number of slides in show
13611		 */
13612		el.getSlideCount = function(){
13613			return slider.children.length;
13614		};
13615
13616		/**
13617		 * Return slider.working variable
13618		 */
13619		el.isWorking = function() {
13620			return slider.working;
13621		}
13622
13623		/**
13624		 * Update all dynamic slider elements
13625		 */
13626		el.redrawSlider = function(){
13627			// resize all children in ratio to new screen size
13628			slider.children.add(el.find('.bx-clone')).outerWidth(getSlideWidth());
13629			// adjust the height
13630			slider.viewport.css('height', getViewportHeight());
13631			// update the slide position
13632			if(!slider.settings.ticker) { setSlidePosition(); }
13633			// if active.last was true before the screen resize, we want
13634			// to keep it last no matter what screen size we end on
13635			if (slider.active.last) { slider.active.index = getPagerQty() - 1; }
13636			// if the active index (page) no longer exists due to the resize, simply set the index as last
13637			if (slider.active.index >= getPagerQty()) { slider.active.last = true; }
13638			// if a pager is being displayed and a custom pager is not being used, update it
13639			if(slider.settings.pager && !slider.settings.pagerCustom){
13640				populatePager();
13641				updatePagerActive(slider.active.index);
13642			}
13643
13644			if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); }
13645		};
13646
13647		/**
13648		 * Destroy the current instance of the slider (revert everything back to original state)
13649		 */
13650		el.destroySlider = function(){
13651			// don't do anything if slider has already been destroyed
13652			if(!slider.initialized){ return; }
13653			slider.initialized = false;
13654			$('.bx-clone', this).remove();
13655			slider.children.each(function(){
13656				if($(this).data("origStyle") !== undefined){
13657					$(this).attr("style", $(this).data("origStyle"));
13658				} else {
13659					$(this).removeAttr('style');
13660				}
13661			});
13662			if($(this).data("origStyle") !== undefined){
13663				this.attr("style", $(this).data("origStyle"));
13664			} else {
13665				$(this).removeAttr('style');
13666			}
13667			$(this).unwrap().unwrap();
13668			if(slider.controls.el){ slider.controls.el.remove(); }
13669			if(slider.controls.next){ slider.controls.next.remove(); }
13670			if(slider.controls.prev){ slider.controls.prev.remove(); }
13671			if(slider.pagerEl && slider.settings.controls && !slider.settings.pagerCustom){ slider.pagerEl.remove(); }
13672			$('.bx-caption', this).remove();
13673			if(slider.controls.autoEl){ slider.controls.autoEl.remove(); }
13674			clearInterval(slider.interval);
13675			if(slider.settings.responsive){ $(window).unbind('resize', resizeWindow); }
13676			if(slider.settings.keyboardEnabled){ $(document).unbind('keydown', keyPress); }
13677		};
13678
13679		/**
13680		 * Reload the slider (revert all DOM changes, and re-initialize)
13681		 */
13682		el.reloadSlider = function(settings){
13683			if(settings !== undefined){ options = settings; }
13684			el.destroySlider();
13685			init();
13686		};
13687
13688		init();
13689
13690		// returns the current jQuery object
13691		return this;
13692	};
13693
13694})(jQuery);
13695window.image_ids = [];
13696$(function() {
13697
13698  var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
13699
13700  if ($('#controller').length) {
13701    function getW() {
13702      var w_w = $(window).width();
13703      var new_w = w_w - 60;
13704      if (new_w > 1920) new_w = 1920;
13705      if (new_w < 860) new_w = 860;
13706      return new_w;
13707    }
13708
13709    function getH() {
13710      var t_g = $(".bxslider").position().top;
13711      var h_w = window.innerHeight;
13712      var c_h = $('#controller').outerHeight(true);
13713      var header = $("header").outerHeight(true);
13714      var gal_t = $(".gallery-title").outerHeight(true);
13715      var gal_d = $(".gallery-description").outerHeight(true);
13716      var upgrade_bar = $(".upgrade-bar").outerHeight(true);
13717
13718      var new_h = h_w - header - gal_t - gal_d - upgrade_bar - 50;
13719      if (new_h > 1200) new_h = 1200;
13720      if (new_h < 400) new_h = 400;
13721
13722      return new_h;
13723    }
13724
13725    function sizeGallery() {
13726      var new_h = getH();
13727      var new_w = getW();
13728
13729      flow_h = new_h;
13730      flow_w = new_w;
13731
13732      $(".gallery img").css("max-height", flow_h + "px");
13733      // When we can't determine height (PDF / video), always set it to the max height.
13734      $(".gallery object, .gallery iframe").css("height", flow_h + "px");
13735
13736      // Set default width and height for lazy-loaded images
13737      $("img.lazy").css("margin-top", (flow_h / 2) + "px");
13738      $("img.lazy").css("margin-bottom", (flow_h / 2) + "px");
13739
13740      // $(".gallery img").css("max-width", flow_w + "px");
13741      $(".gallery iframe").css("max-width", flow_w + "px");
13742    }
13743
13744    function reloadGallerySize() {
13745      var new_h = getH();
13746      var new_w = getW();
13747
13748      if (Math.abs(new_h - orig_h) > 20 || Math.abs(new_w - orig_w) > 0) {
13749        sizeGallery();
13750      }
13751    }
13752
13753    // If there are less than x images, load them all.
13754    if ($("img.lazy").length <= 10) {
13755      var imagesToLoad = $("img.lazy");
13756    } else {
13757      // We always want to immediately load the first image in the gallery
13758      var imagesToLoad = $("img.lazy").eq(0);
13759    }
13760
13761    imagesToLoad.css('min-height', getH());
13762    imagesToLoad.load(function() {
13763      $(this).css('min-height', "");
13764      slider.animateViewportAdaptiveHeight();
13765    })
13766    imagesToLoad.each(function(i, img) {
13767      var $img = $(img);
13768      $img.attr('src', $img.data('original'));
13769    });
13770    imagesToLoad.removeClass('lazy');
13771
13772    // $('img.actual-image').each(function() {
13773    //   toolbarifyImage(this);
13774    // });
13775
13776    // Handle image loads
13777    $("img.lazy").load(function() {
13778      var $this = $(this);
13779      // Don't do anything if we loaded dummy image
13780      if (!$this.attr('src') || $this.attr('src').indexOf("loader") != -1)
13781        return;
13782
13783      // After image loads, remove margins, and remove lazy class so they don't get re-added
13784      $this.removeClass('lazy').css("margin-top", "").css("margin-bottom", "");
13785
13786      if ($this.closest('li').attr('aria-hidden') === "false") {
13787        slider.animateViewportAdaptiveHeight();
13788      }
13789    });
13790
13791    sizeGallery();
13792    $(window).resize(sizeGallery);
13793
13794    var slider = $('.bxslider').bxSlider({
13795      pagerCustom: '.bx-pager',
13796      adaptiveHeight: true,
13797      adaptiveHeightSpeed: 300,
13798      keyboardEnabled: false,
13799      // Responsiveness for videos doesn't seem to work.
13800      //video: true,
13801      onSlideBefore: function() {
13802        // Pause all youtube and video videos by using their API
13803        $('iframe').each(function() {
13804          this.contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
13805          this.contentWindow.postMessage('{"method":"pause","value":""}', '*');
13806        });
13807
13808        $(".swipe-info").addClass("fade-out");
13809      },
13810      onSlideAfter: function() {
13811        // Trigger window scroll so that lazyload plugin kicks in
13812        $('body,html').scroll();
13813
13814        // Update window location hash
13815        location.hash = $(".bx-pager a.active").attr("href");
13816
13817        // If we are showing a video, show control arrows, otherwise hide.
13818        if (supportsTouch) {
13819          var currentSlideEl = $('ul.bxslider > li').eq(slider.getCurrentSlide() + 1);
13820          if (currentSlideEl.find('.video-container').length) {
13821            $('.bx-controls').fadeIn();
13822          } else {
13823            $('.bx-controls').fadeOut();
13824          }
13825        }
13826      },
13827      onSliderLoad: function() {
13828        $('body,html').scroll();
13829
13830        // // Fade in gallery and thumbs once they are loaded
13831        // $('section.gallery').css('visibility', 'visible');
13832        // $('section.gallery').hide().fadeIn();
13833        // $('#controller').fadeIn();
13834        // $('.bx-controls').fadeIn();
13835      }
13836    });
13837
13838    // set custom keyboard listener
13839    $(document).keydown(function(e) {
13840      if (e.keyCode == 39) {          // Right arrow
13841        slider.goToNextSlide();
13842        return false;
13843      } else if (e.keyCode == 37) {   // Left arrow
13844        slider.goToPrevSlide();
13845        return false;
13846      }
13847    });
13848
13849    // Generate new loading spinners at: http://www.ajaxload.info/
13850    if ($('body').is('.bg-dark')) {
13851      var placeholderImage = "/assets/portfolio/loader-dark-e83d06e50eb9cb658b8b9a2a229b04f8.gif";
13852    } else {
13853      var placeholderImage = "/assets/portfolio/loader-light-83459654ba7ca9281de6552a097a81d7.gif";
13854    }
13855
13856    var new_w = getW();
13857    $("img.lazy").lazyload({
13858      effect: "fadeIn",
13859      // Load the next 4 images in the slider
13860      threshold: $(window).width() * 4,
13861      placeholder: placeholderImage
13862    });
13863
13864    // Hide gallery and thumbs so we can fade in when everything is loaded
13865    //$('section.gallery').css('visibility', 'hidden');
13866    // $('#controller').hide();
13867    // $('.bx-controls').hide();
13868
13869    if (!supportsTouch) {
13870      $('article.item img').click(function() {
13871        slider.goToNextSlide();
13872      });
13873    }
13874
13875
13876    // Port jflow window location code
13877    // -----------------------------------------------------
13878
13879    // initialize the bookmark in the url hash
13880    if (location.hash) {
13881      var jumpid = location.hash.substr(1);
13882
13883      if(jumpid.indexOf("old-id=")==0){
13884        // old legacy id
13885        var oldId = jumpid.substr(7);
13886        $(this).find("[data-old-id=" + oldId + ']').click();
13887      } else{
13888        if ($('#idx-' + jumpid).size() == 0) {
13889          $.get('/find/' + jumpid, function(data) {
13890            if (data && data.slug) {
13891              window.location = data.slug + "#" + jumpid;
13892            }
13893          });
13894        } else {
13895          $(this).find("#idx-" + jumpid).click();
13896        }
13897      }
13898    }
13899
13900    // Alerts every time the hash changes!
13901    $(window).bind('hashchange', function () {
13902      var jumpid = location.hash.substr(1);
13903      if (jumpid) {
13904        if(jumpid.indexOf("old-id=")==0){
13905          // old legacy id
13906          var oldId = jumpid.substr(7);
13907          $(this).find("[data-old-id=" + oldId + ']').click();
13908        } else{
13909          // go to specified image
13910          $("#idx-" + jumpid).click();
13911        }
13912      }
13913      else {
13914        // reset to first image (no hash tag = index 1)
13915        slider.goToSlide(0);
13916      }
13917    })
13918
13919    // --------------------------------------
13920    // End window location code
13921  }
13922
13923  if (supportsTouch) {
13924    // Hide bxslider control arrows
13925    $('.bx-controls').hide();
13926
13927    // Show "swipe to continue" message on first items if device supports touch.
13928    // Only show the swipe message if there are multiple items
13929    if ($('#slides figure').length > 1 && typeof localStorage !== 'undefined') {
13930      // Only show the message once.
13931      if (!localStorage.getItem('didShowSwipeInfo')) {
13932
13933        // safari private browsing doesn't allow use of localStorage
13934        try {
13935          localStorage.setItem('didShowSwipeInfo', "yes");
13936        } catch (e) {
13937          // swallow the error
13938        }
13939
13940        var swipeInfoHTML = '<div class="swipe-info"><span></span><h1>Swipe to Continue</h1></div>';
13941
13942        // Homepage
13943        $('#slides figure').eq(0).prepend(swipeInfoHTML);
13944
13945        // Gallery show
13946        if (typeof slider !== "undefined") {
13947          var currentSlideEl = $('ul.bxslider > li').eq(slider.getCurrentSlide() + 1);
13948          currentSlideEl.prepend(swipeInfoHTML);
13949        }
13950
13951        setTimeout(function() {
13952          $(".swipe-info").addClass("fade-out");
13953        }, 2500);
13954      }
13955    }
13956  }
13957});
13958
13959
13960
13961
13962
13963/*!
13964* jQuery imagesLoaded plugin v1.2.1
13965* http://github.com/desandro/imagesloaded
13966*
13967* MIT License. by Paul Irish et al.
13968*/
13969
13970
13971(function ($, undefined) {
13972
13973    // $('#my-container').imagesLoaded(myFunction)
13974    // or
13975    // $('img').imagesLoaded(myFunction)
13976
13977    // execute a callback when all images have loaded.
13978    // needed because .load() doesn't work on cached images
13979
13980    // callback is executed when all images has fineshed loading
13981    // callback function arguments: $all_images, $proper_images, $broken_images
13982    // `this` is the jQuery wrapped container
13983
13984    // returns previous jQuery wrapped container extended with deferred object
13985    // done method arguments: .done( function( $all_images ){ ... } )
13986    // fail method arguments: .fail( function( $all_images, $proper_images, $broken_images ){ ... } )
13987    // progress method arguments: .progress( function( images_count, loaded_count, proper_count, broken_count )
13988
13989    $.fn.imagesLoaded = function (callback) {
13990        var $this = this,
13991    deferred = $.Deferred(),
13992    $images = $this.find('img').add($this.filter('img')),
13993    len = $images.length,
13994    blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==',
13995    loaded = [],
13996    proper = [],
13997    broken = [];
13998
13999        function doneLoading() {
14000            var $proper = $(proper),
14001      $broken = $(broken);
14002
14003            if (broken.length) {
14004                deferred.reject($images, $proper, $broken);
14005            } else {
14006                deferred.resolve($images);
14007            }
14008
14009            callback.call($this, $images, $proper, $broken);
14010        }
14011
14012        function imgLoaded(event) {
14013            // dont proceed if img src is blank or if img is already loaded
14014            if (event.target.src === blank || $.inArray(this, loaded) !== -1) {
14015                return;
14016            }
14017
14018            loaded.push(this);
14019            // keep track of broken and properly loaded images
14020            if (event.type === 'error') {
14021                broken.push(this);
14022            } else {
14023                proper.push(this);
14024            }
14025
14026            deferred.notify($images.length, loaded.length, proper.length, broken.length);
14027
14028            if (--len <= 0) {
14029                setTimeout(doneLoading);
14030                $images.unbind('.imagesLoaded', imgLoaded);
14031            }
14032        }
14033
14034        // if no images, trigger immediately
14035        if (!len) {
14036            doneLoading();
14037        }
14038
14039        $images.bind('load.imagesLoaded error.imagesLoaded', imgLoaded).each(function () {
14040            // cached images don't fire load sometimes, so we reset src.
14041            var src = this.src;
14042            // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
14043            // data uri bypasses webkit log warning (thx doug jones)
14044            this.src = blank;
14045            this.src = src;
14046        });
14047
14048        return deferred.promise($this);
14049    };
14050
14051})(jQuery);
14052// Generated by CoffeeScript 1.6.1
14053(function() {
14054
14055  (function($, window, document) {
14056    var Plugin, defaults, pluginName;
14057    pluginName = "slidesjs";
14058    defaults = {
14059      width: 940,
14060      height: 528,
14061      start: 1,
14062      navigation: {
14063        active: true,
14064        effect: "slide"
14065      },
14066      pagination: {
14067        active: true,
14068        effect: "slide"
14069      },
14070      play: {
14071        active: false,
14072        effect: "slide",
14073        interval: 5000,
14074        auto: false,
14075        swap: true,
14076        pauseOnHover: false,
14077        restartDelay: 2500
14078      },
14079      effect: {
14080        slide: {
14081          speed: 500
14082        },
14083        fade: {
14084          speed: 300,
14085          crossfade: true
14086        }
14087      },
14088      callback: {
14089        loaded: function() {},
14090        start: function() {},
14091        complete: function() {}
14092      }
14093    };
14094    Plugin = (function() {
14095
14096      function Plugin(element, options) {
14097        this.element = element;
14098        this.options = $.extend(true, {}, defaults, options);
14099        this._defaults = defaults;
14100        this._name = pluginName;
14101        this.init();
14102      }
14103
14104      return Plugin;
14105
14106    })();
14107    Plugin.prototype.init = function() {
14108      var $element, nextButton, pagination, playButton, prevButton, stopButton,
14109        _this = this;
14110      $element = $(this.element);
14111      this.data = $.data(this);
14112      $.data(this, "animating", false);
14113      $.data(this, "total", $element.children().not(".slidesjs-navigation", $element).length);
14114      $.data(this, "current", this.options.start - 1);
14115      $.data(this, "vendorPrefix", this._getVendorPrefix());
14116      if (typeof TouchEvent !== "undefined") {
14117        $.data(this, "touch", true);
14118        this.options.effect.slide.speed = this.options.effect.slide.speed / 2;
14119      }
14120      $element.css({
14121        overflow: "hidden"
14122      });
14123      $element.slidesContainer = $element.children().not(".slidesjs-navigation", $element).wrapAll("<div class='slidesjs-container'>", $element).parent().css({
14124        overflow: "hidden",
14125        position: "relative"
14126      });
14127      $(".slidesjs-container", $element).wrapInner("<div class='slidesjs-control'>", $element).children();
14128      $(".slidesjs-control", $element).css({
14129        position: "relative",
14130        left: 0
14131      });
14132      $(".slidesjs-control", $element).children().addClass("slidesjs-slide").css({
14133        position: "absolute",
14134        top: 0,
14135        left: 0,
14136        width: "100%",
14137        zIndex: 0,
14138        display: "none",
14139        webkitBackfaceVisibility: "hidden"
14140      });
14141      $.each($(".slidesjs-control", $element).children(), function(i) {
14142        var $slide;
14143        $slide = $(this);
14144        return $slide.attr("slidesjs-index", i);
14145      });
14146      if (this.data.touch) {
14147        $(".slidesjs-control", $element).on("touchstart", function(e) {
14148          return _this._touchstart(e);
14149        });
14150        $(".slidesjs-control", $element).on("touchmove", function(e) {
14151          return _this._touchmove(e);
14152        });
14153        $(".slidesjs-control", $element).on("touchend", function(e) {
14154          return _this._touchend(e);
14155        });
14156      }
14157      $element.fadeIn(0);
14158      this.update();
14159      if (this.data.touch) {
14160        this._setuptouch();
14161      }
14162      $(".slidesjs-control", $element).children(":eq(" + this.data.current + ")").eq(0).fadeIn(0, function() {
14163        return $(this).css({
14164          zIndex: 10
14165        });
14166      });
14167      if (this.options.navigation.active) {
14168        prevButton = $("<a>", {
14169          "class": "slidesjs-previous slidesjs-navigation",
14170          href: "#",
14171          title: "Previous",
14172          text: "Previous"
14173        }).appendTo($element);
14174        nextButton = $("<a>", {
14175          "class": "slidesjs-next slidesjs-navigation",
14176          href: "#",
14177          title: "Next",
14178          text: "Next"
14179        }).appendTo($element);
14180      }
14181      $(".slidesjs-next", $element).click(function(e) {
14182        e.preventDefault();
14183        _this.stop(true);
14184        return _this.next(_this.options.navigation.effect);
14185      });
14186      $(".slidesjs-previous", $element).click(function(e) {
14187        e.preventDefault();
14188        _this.stop(true);
14189        return _this.previous(_this.options.navigation.effect);
14190      });
14191      if (this.options.play.active) {
14192        playButton = $("<a>", {
14193          "class": "slidesjs-play slidesjs-navigation",
14194          href: "#",
14195          title: "Play",
14196          text: "Play"
14197        }).appendTo($element);
14198        stopButton = $("<a>", {
14199          "class": "slidesjs-stop slidesjs-navigation",
14200          href: "#",
14201          title: "Stop",
14202          text: "Stop"
14203        }).appendTo($element);
14204        playButton.click(function(e) {
14205          e.preventDefault();
14206          return _this.play(true);
14207        });
14208        stopButton.click(function(e) {
14209          e.preventDefault();
14210          return _this.stop(true);
14211        });
14212        if (this.options.play.swap) {
14213          stopButton.css({
14214            display: "none"
14215          });
14216        }
14217      }
14218      if (this.options.pagination.active) {
14219        pagination = $("<ul>", {
14220          "class": "slidesjs-pagination"
14221        }).appendTo($element);
14222        $.each(new Array(this.data.total), function(i) {
14223          var paginationItem, paginationLink;
14224          paginationItem = $("<li>", {
14225            "class": "slidesjs-pagination-item"
14226          }).appendTo(pagination);
14227          paginationLink = $("<a>", {
14228            href: "#",
14229            "data-slidesjs-item": i,
14230            html: i + 1
14231          }).appendTo(paginationItem);
14232          return paginationLink.click(function(e) {
14233            e.preventDefault();
14234            _this.stop(true);
14235            return _this.goto(($(e.currentTarget).attr("data-slidesjs-item") * 1) + 1);
14236          });
14237        });
14238      }
14239      $(window).bind("resize", function() {
14240        return _this.update();
14241      });
14242      this._setActive();
14243      if (this.options.play.auto) {
14244        this.play();
14245      }
14246      return this.options.callback.loaded(this.options.start);
14247    };
14248    Plugin.prototype._setActive = function(number) {
14249      var $element, current;
14250      $element = $(this.element);
14251      this.data = $.data(this);
14252      current = number > -1 ? number : this.data.current;
14253      $(".active", $element).removeClass("active");
14254      return $(".slidesjs-pagination li:eq(" + current + ") a", $element).addClass("active");
14255    };
14256    Plugin.prototype.update = function() {
14257      var $element, height, width;
14258      $element = $(this.element);
14259      this.data = $.data(this);
14260      $(".slidesjs-control", $element).children(":not(:eq(" + this.data.current + "))").css({
14261        display: "none",
14262        left: 0,
14263        zIndex: 0
14264      });
14265      width = $element.width();
14266      height = (this.options.height / this.options.width) * width;
14267      this.options.width = width;
14268      this.options.height = height;
14269      return $(".slidesjs-control, .slidesjs-container", $element).css({
14270        width: width,
14271        height: "100%"
14272      });
14273    };
14274    Plugin.prototype.next = function(effect) {
14275      var $element;
14276      $element = $(this.element);
14277      this.data = $.data(this);
14278      $.data(this, "direction", "next");
14279      if (effect === void 0) {
14280        effect = this.options.navigation.effect;
14281      }
14282      if (effect === "fade") {
14283        return this._fade();
14284      } else {
14285        return this._slide();
14286      }
14287    };
14288    Plugin.prototype.previous = function(effect) {
14289      var $element;
14290      $element = $(this.element);
14291      this.data = $.data(this);
14292      $.data(this, "direction", "previous");
14293      if (effect === void 0) {
14294        effect = this.options.navigation.effect;
14295      }
14296      if (effect === "fade") {
14297        return this._fade();
14298      } else {
14299        return this._slide();
14300      }
14301    };
14302    Plugin.prototype.goto = function(number) {
14303      var $element, effect;
14304      $element = $(this.element);
14305      this.data = $.data(this);
14306      if (effect === void 0) {
14307        effect = this.options.pagination.effect;
14308      }
14309      if (number > this.data.total) {
14310        number = this.data.total;
14311      } else if (number < 1) {
14312        number = 1;
14313      }
14314      if (typeof number === "number") {
14315        if (effect === "fade") {
14316          return this._fade(number);
14317        } else {
14318          return this._slide(number);
14319        }
14320      } else if (typeof number === "string") {
14321        if (number === "first") {
14322          if (effect === "fade") {
14323            return this._fade(0);
14324          } else {
14325            return this._slide(0);
14326          }
14327        } else if (number === "last") {
14328          if (effect === "fade") {
14329            return this._fade(this.data.total);
14330          } else {
14331            return this._slide(this.data.total);
14332          }
14333        }
14334      }
14335    };
14336    Plugin.prototype._setuptouch = function() {
14337      var $element, next, previous, slidesControl;
14338      $element = $(this.element);
14339      this.data = $.data(this);
14340      slidesControl = $(".slidesjs-control", $element);
14341      next = this.data.current + 1;
14342      previous = this.data.current - 1;
14343      if (previous < 0) {
14344        previous = this.data.total - 1;
14345      }
14346      if (next > this.data.total - 1) {
14347        next = 0;
14348      }
14349      slidesControl.children(":eq(" + next + ")").css({
14350        display: "block",
14351        left: this.options.width
14352      });
14353      return slidesControl.children(":eq(" + previous + ")").css({
14354        display: "block",
14355        left: -this.options.width
14356      });
14357    };
14358    Plugin.prototype._touchstart = function(e) {
14359      var $element, touches;
14360      $element = $(this.element);
14361      this.data = $.data(this);
14362      touches = e.originalEvent.touches[0];
14363      this._setuptouch();
14364      $.data(this, "touchtimer", Number(new Date()));
14365      $.data(this, "touchstartx", touches.pageX);
14366      $.data(this, "touchstarty", touches.pageY);
14367      return e.stopPropagation();
14368    };
14369    Plugin.prototype._touchend = function(e) {
14370      var $element, duration, prefix, slidesControl, timing, touches, transform,
14371        _this = this;
14372      $element = $(this.element);
14373      this.data = $.data(this);
14374      touches = e.originalEvent.touches[0];
14375      slidesControl = $(".slidesjs-control", $element);
14376      if (slidesControl.position().left > this.options.width * 0.5 || slidesControl.position().left > this.options.width * 0.1 && (Number(new Date()) - this.data.touchtimer < 250)) {
14377        $.data(this, "direction", "previous");
14378        this._slide();
14379      } else if (slidesControl.position().left < -(this.options.width * 0.5) || slidesControl.position().left < -(this.options.width * 0.1) && (Number(new Date()) - this.data.touchtimer < 250)) {
14380        $.data(this, "direction", "next");
14381        this._slide();
14382      } else {
14383        prefix = this.data.vendorPrefix;
14384        transform = prefix + "Transform";
14385        duration = prefix + "TransitionDuration";
14386        timing = prefix + "TransitionTimingFunction";
14387        slidesControl[0].style[transform] = "translateX(0px)";
14388        slidesControl[0].style[duration] = this.options.effect.slide.speed * 0.85 + "ms";
14389      }
14390      slidesControl.on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", function() {
14391        prefix = _this.data.vendorPrefix;
14392        transform = prefix + "Transform";
14393        duration = prefix + "TransitionDuration";
14394        timing = prefix + "TransitionTimingFunction";
14395        slidesControl[0].style[transform] = "";
14396        slidesControl[0].style[duration] = "";
14397        return slidesControl[0].style[timing] = "";
14398      });
14399      return e.stopPropagation();
14400    };
14401    Plugin.prototype._touchmove = function(e) {
14402      var $element, prefix, slidesControl, touches, transform;
14403      $element = $(this.element);
14404      this.data = $.data(this);
14405      touches = e.originalEvent.touches[0];
14406      prefix = this.data.vendorPrefix;
14407      slidesControl = $(".slidesjs-control", $element);
14408      transform = prefix + "Transform";
14409      $.data(this, "scrolling", Math.abs(touches.pageX - this.data.touchstartx) < Math.abs(touches.pageY - this.data.touchstarty));
14410      if (!this.data.animating && !this.data.scrolling) {
14411        e.preventDefault();
14412        this._setuptouch();
14413        slidesControl[0].style[transform] = "translateX(" + (touches.pageX - this.data.touchstartx) + "px)";
14414      }
14415      return e.stopPropagation();
14416    };
14417    Plugin.prototype.play = function(next) {
14418      var $element, currentSlide, slidesContainer,
14419        _this = this;
14420      $element = $(this.element);
14421      this.data = $.data(this);
14422      if (!this.data.playInterval) {
14423        if (next) {
14424          currentSlide = this.data.current;
14425          this.data.direction = "next";
14426          if (this.options.play.effect === "fade") {
14427            this._fade();
14428          } else {
14429            this._slide();
14430          }
14431        }
14432        $.data(this, "playInterval", setInterval((function() {
14433          currentSlide = _this.data.current;
14434          _this.data.direction = "next";
14435          if (_this.options.play.effect === "fade") {
14436            return _this._fade();
14437          } else {
14438            return _this._slide();
14439          }
14440        }), this.options.play.interval));
14441        slidesContainer = $(".slidesjs-container", $element);
14442        if (this.options.play.pauseOnHover) {
14443          slidesContainer.unbind();
14444          slidesContainer.bind("mouseenter", function() {
14445            return _this.stop();
14446          });
14447          slidesContainer.bind("mouseleave", function() {
14448            if (_this.options.play.restartDelay) {
14449              return $.data(_this, "restartDelay", setTimeout((function() {
14450                return _this.play(true);
14451              }), _this.options.play.restartDelay));
14452            } else {
14453              return _this.play();
14454            }
14455          });
14456        }
14457        $.data(this, "playing", true);
14458        $(".slidesjs-play", $element).addClass("slidesjs-playing");
14459        if (this.options.play.swap) {
14460          $(".slidesjs-play", $element).hide();
14461          return $(".slidesjs-stop", $element).show();
14462        }
14463      }
14464    };
14465    Plugin.prototype.stop = function(clicked) {
14466      var $element;
14467      $element = $(this.element);
14468      this.data = $.data(this);
14469      clearInterval(this.data.playInterval);
14470      if (this.options.play.pauseOnHover && clicked) {
14471        $(".slidesjs-container", $element).unbind();
14472      }
14473      $.data(this, "playInterval", null);
14474      $.data(this, "playing", false);
14475      $(".slidesjs-play", $element).removeClass("slidesjs-playing");
14476      if (this.options.play.swap) {
14477        $(".slidesjs-stop", $element).hide();
14478        return $(".slidesjs-play", $element).show();
14479      }
14480    };
14481    Plugin.prototype._slide = function(number) {
14482      var $element, currentSlide, direction, duration, next, prefix, slidesControl, timing, transform, value,
14483        _this = this;
14484      $element = $(this.element);
14485      this.data = $.data(this);
14486      if (!this.data.animating && number !== this.data.current + 1) {
14487        $.data(this, "animating", true);
14488        currentSlide = this.data.current;
14489        if (number > -1) {
14490          number = number - 1;
14491          value = number > currentSlide ? 1 : -1;
14492          direction = number > currentSlide ? -this.options.width : this.options.width;
14493          next = number;
14494        } else {
14495          value = this.data.direction === "next" ? 1 : -1;
14496          direction = this.data.direction === "next" ? -this.options.width : this.options.width;
14497          next = currentSlide + value;
14498        }
14499        if (next === -1) {
14500          next = this.data.total - 1;
14501        }
14502        if (next === this.data.total) {
14503          next = 0;
14504        }
14505        this._setActive(next);
14506        slidesControl = $(".slidesjs-control", $element);
14507        if (number > -1) {
14508          slidesControl.children(":not(:eq(" + currentSlide + "))").css({
14509            display: "none",
14510            left: 0,
14511            zIndex: 0
14512          });
14513        }
14514        slidesControl.children(":eq(" + next + ")").css({
14515          display: "block",
14516          left: value * this.options.width,
14517          zIndex: 10
14518        });
14519        this.options.callback.start(currentSlide + 1);
14520        if (this.data.vendorPrefix) {
14521          prefix = this.data.vendorPrefix;
14522          transform = prefix + "Transform";
14523          duration = prefix + "TransitionDuration";
14524          timing = prefix + "TransitionTimingFunction";
14525          slidesControl[0].style[transform] = "translateX(" + direction + "px)";
14526          slidesControl[0].style[duration] = this.options.effect.slide.speed + "ms";
14527          return slidesControl.on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", function() {
14528            slidesControl[0].style[transform] = "";
14529            slidesControl[0].style[duration] = "";
14530            slidesControl.children(":eq(" + next + ")").css({
14531              left: 0
14532            });
14533            slidesControl.children(":eq(" + currentSlide + ")").css({
14534              display: "none",
14535              left: 0,
14536              zIndex: 0
14537            });
14538            $.data(_this, "current", next);
14539            $.data(_this, "animating", false);
14540            slidesControl.unbind("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd");
14541            slidesControl.children(":not(:eq(" + next + "))").css({
14542              display: "none",
14543              left: 0,
14544              zIndex: 0
14545            });
14546            if (_this.data.touch) {
14547              _this._setuptouch();
14548            }
14549            return _this.options.callback.complete(next + 1);
14550          });
14551        } else {
14552          return slidesControl.stop().animate({
14553            left: direction
14554          }, this.options.effect.slide.speed, (function() {
14555            slidesControl.css({
14556              left: 0
14557            });
14558            slidesControl.children(":eq(" + next + ")").css({
14559              left: 0
14560            });
14561            return slidesControl.children(":eq(" + currentSlide + ")").css({
14562              display: "none",
14563              left: 0,
14564              zIndex: 0
14565            }, $.data(_this, "current", next), $.data(_this, "animating", false), _this.options.callback.complete(next + 1));
14566          }));
14567        }
14568      }
14569    };
14570    Plugin.prototype._fade = function(number) {
14571      var $element, currentSlide, next, slidesControl, value,
14572        _this = this;
14573      $element = $(this.element);
14574      this.data = $.data(this);
14575      if (!this.data.animating && number !== this.data.current + 1) {
14576        $.data(this, "animating", true);
14577        currentSlide = this.data.current;
14578        if (number) {
14579          number = number - 1;
14580          value = number > currentSlide ? 1 : -1;
14581          next = number;
14582        } else {
14583          value = this.data.direction === "next" ? 1 : -1;
14584          next = currentSlide + value;
14585        }
14586        if (next === -1) {
14587          next = this.data.total - 1;
14588        }
14589        if (next === this.data.total) {
14590          next = 0;
14591        }
14592        this._setActive(next);
14593        slidesControl = $(".slidesjs-control", $element);
14594        slidesControl.children(":eq(" + next + ")").css({
14595          display: "none",
14596          left: 0,
14597          zIndex: 10
14598        });
14599        this.options.callback.start(currentSlide + 1);
14600        if (this.options.effect.fade.crossfade) {
14601          slidesControl.children(":eq(" + this.data.current + ")").stop().fadeOut(this.options.effect.fade.speed);
14602          return slidesControl.children(":eq(" + next + ")").stop().fadeIn(this.options.effect.fade.speed, (function() {
14603            slidesControl.children(":eq(" + next + ")").css({
14604              zIndex: 0
14605            });
14606            $.data(_this, "animating", false);
14607            $.data(_this, "current", next);
14608            return _this.options.callback.complete(next + 1);
14609          }));
14610        } else {
14611          return slidesControl.children(":eq(" + currentSlide + ")").stop().fadeOut(this.options.effect.fade.speed, (function() {
14612            slidesControl.children(":eq(" + next + ")").stop().fadeIn(_this.options.effect.fade.speed, (function() {
14613              return slidesControl.children(":eq(" + next + ")").css({
14614                zIndex: 10
14615              });
14616            }));
14617            $.data(_this, "animating", false);
14618            $.data(_this, "current", next);
14619            return _this.options.callback.complete(next + 1);
14620          }));
14621        }
14622      }
14623    };
14624    Plugin.prototype._getVendorPrefix = function() {
14625      var body, i, style, transition, vendor;
14626      body = document.body || document.documentElement;
14627      style = body.style;
14628      transition = "transition";
14629      vendor = ["Moz", "Webkit", "Khtml", "O", "ms"];
14630      transition = transition.charAt(0).toUpperCase() + transition.substr(1);
14631      i = 0;
14632      while (i < vendor.length) {
14633        if (typeof style[vendor[i] + transition] === "string") {
14634          return vendor[i];
14635        }
14636        i++;
14637      }
14638      return false;
14639    };
14640    return $.fn[pluginName] = function(options) {
14641      return this.each(function() {
14642        if (!$.data(this, "plugin_" + pluginName)) {
14643          return $.data(this, "plugin_" + pluginName, new Plugin(this, options));
14644        }
14645      });
14646    };
14647  })(jQuery, window, document);
14648
14649}).call(this);
14650function lazyLoadStackedGallery() {
14651  // Generate new loading spinners at: http://www.ajaxload.info/
14652  if ($('body').is('.bg-dark')) {
14653    var placeholderImage = "/assets/portfolio/loader-dark-e83d06e50eb9cb658b8b9a2a229b04f8.gif";
14654  } else {
14655    var placeholderImage = "/assets/portfolio/loader-light-83459654ba7ca9281de6552a097a81d7.gif";
14656  }
14657
14658  $("img.lazy").lazyload({
14659    effect: 'fadeIn',
14660    threshold: 500,
14661    skip_invisible: true,
14662    placeholder: placeholderImage,
14663    load: function(img) {
14664      $(this).parent().removeClass('placeholder');
14665    }
14666  });
14667
14668  $(window).load(function(){
14669    $("html,body").trigger("scroll");
14670  });
14671}
14672;
14673/*
14674 * Swipe 2.0
14675 *
14676 * Brad Birdsall
14677 * Copyright 2013, MIT License
14678 *
14679*/
14680
14681
14682function Swipe(container, options) {
14683
14684  "use strict";
14685
14686  // utilities
14687  var noop = function() {}; // simple no operation function
14688  var offloadFn = function(fn) { setTimeout(fn || noop, 0) }; // offload a functions execution
14689
14690  // check browser capabilities
14691  var browser = {
14692    addEventListener: !!window.addEventListener,
14693    touch: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch,
14694    transitions: (function(temp) {
14695      var props = ['transitionProperty', 'WebkitTransition', 'MozTransition', 'OTransition', 'msTransition'];
14696      for ( var i in props ) if (temp.style[ props[i] ] !== undefined) return true;
14697      return false;
14698    })(document.createElement('swipe'))
14699  };
14700
14701  // quit if no root element
14702  if (!container) return;
14703  var element = container.children[0];
14704  var slides, slidePos, width, length;
14705  options = options || {};
14706  var index = parseInt(options.startSlide, 10) || 0;
14707  var speed = options.speed || 300;
14708  options.continuous = options.continuous !== undefined ? options.continuous : true;
14709
14710  function setup() {
14711
14712    // cache slides
14713    slides = element.children;
14714    length = slides.length;
14715
14716    // set continuous to false if only one slide
14717    if (slides.length < 2) options.continuous = false;
14718
14719    //special case if two slides
14720    if (browser.transitions && options.continuous && slides.length < 3) {
14721      element.appendChild(slides[0].cloneNode(true));
14722      element.appendChild(element.children[1].cloneNode(true));
14723      slides = element.children;
14724    }
14725
14726    // create an array to store current positions of each slide
14727    slidePos = new Array(slides.length);
14728
14729    // determine width of each slide
14730    width = container.getBoundingClientRect().width || container.offsetWidth;
14731
14732    element.style.width = (slides.length * width) + 'px';
14733
14734    // stack elements
14735    var pos = slides.length;
14736    while(pos--) {
14737
14738      var slide = slides[pos];
14739
14740      slide.style.width = width + 'px';
14741      slide.setAttribute('data-index', pos);
14742
14743      if (browser.transitions) {
14744        slide.style.left = (pos * -width) + 'px';
14745        move(pos, index > pos ? -width : (index < pos ? width : 0), 0);
14746      }
14747
14748    }
14749
14750    // reposition elements before and after index
14751    if (options.continuous && browser.transitions) {
14752      move(circle(index-1), -width, 0);
14753      move(circle(index+1), width, 0);
14754    }
14755
14756    if (!browser.transitions) element.style.left = (index * -width) + 'px';
14757
14758    container.style.visibility = 'visible';
14759
14760  }
14761
14762  function prev() {
14763
14764    if (options.continuous) slide(index-1);
14765    else if (index) slide(index-1);
14766
14767  }
14768
14769  function next() {
14770
14771    if (options.continuous) slide(index+1);
14772    else if (index < slides.length - 1) slide(index+1);
14773
14774  }
14775
14776  function circle(index) {
14777
14778    // a simple positive modulo using slides.length
14779    return (slides.length + (index % slides.length)) % slides.length;
14780
14781  }
14782
14783  function slide(to, slideSpeed) {
14784
14785    // do nothing if already on requested slide
14786    if (index == to) return;
14787
14788    var preslideIndex = to;
14789    if (slides.length == to) {
14790      preslideIndex = 0;
14791    }
14792    if (options.preslide) options.preslide(preslideIndex, slides[preslideIndex]);
14793
14794    if (browser.transitions) {
14795
14796      var direction = Math.abs(index-to) / (index-to); // 1: backward, -1: forward
14797
14798      // get the actual position of the slide
14799      if (options.continuous) {
14800        var natural_direction = direction;
14801        direction = -slidePos[circle(to)] / width;
14802
14803        // if going forward but to < index, use to = slides.length + to
14804        // if going backward but to > index, use to = -slides.length + to
14805        if (direction !== natural_direction) to =  -direction * slides.length + to;
14806
14807      }
14808
14809      var diff = Math.abs(index-to) - 1;
14810
14811      // move all the slides between index and to in the right direction
14812      while (diff--) move( circle((to > index ? to : index) - diff - 1), width * direction, 0);
14813
14814      to = circle(to);
14815
14816      move(index, width * direction, slideSpeed || speed);
14817      move(to, 0, slideSpeed || speed);
14818
14819      if (options.continuous) move(circle(to - direction), -(width * direction), 0); // we need to get the next in place
14820
14821    } else {
14822
14823      to = circle(to);
14824      animate(index * -width, to * -width, slideSpeed || speed);
14825      //no fallback for a circular continuous if the browser does not accept transitions
14826    }
14827
14828    index = to;
14829    offloadFn(options.callback && options.callback(index, slides[index]));
14830  }
14831
14832  function move(index, dist, speed) {
14833
14834    translate(index, dist, speed);
14835    slidePos[index] = dist;
14836
14837  }
14838
14839  function translate(index, dist, speed) {
14840
14841    var slide = slides[index];
14842    var style = slide && slide.style;
14843
14844    if (!style) return;
14845
14846    style.webkitTransitionDuration =
14847    style.MozTransitionDuration =
14848    style.msTransitionDuration =
14849    style.OTransitionDuration =
14850    style.transitionDuration = speed + 'ms';
14851
14852    style.webkitTransform = 'translate(' + dist + 'px,0)' + 'translateZ(0)';
14853    style.msTransform =
14854    style.MozTransform =
14855    style.OTransform = 'translateX(' + dist + 'px)';
14856
14857  }
14858
14859  function animate(from, to, speed) {
14860
14861    // if not an animation, just reposition
14862    if (!speed) {
14863
14864      element.style.left = to + 'px';
14865      return;
14866
14867    }
14868
14869    var start = +new Date;
14870
14871    var timer = setInterval(function() {
14872
14873      var timeElap = +new Date - start;
14874
14875      if (timeElap > speed) {
14876
14877        element.style.left = to + 'px';
14878
14879        if (delay) begin();
14880
14881        options.transitionEnd && options.transitionEnd.call(event, index, slides[index]);
14882
14883        clearInterval(timer);
14884        return;
14885
14886      }
14887
14888      element.style.left = (( (to - from) * (Math.floor((timeElap / speed) * 100) / 100) ) + from) + 'px';
14889
14890    }, 4);
14891
14892  }
14893
14894  // setup auto slideshow
14895  var delay = options.auto || 0;
14896  var interval;
14897
14898  function begin() {
14899
14900    interval = setTimeout(next, delay);
14901
14902  }
14903
14904  function stop() {
14905
14906    delay = 0;
14907    clearTimeout(interval);
14908
14909  }
14910
14911
14912  // setup initial vars
14913  var start = {};
14914  var delta = {};
14915  var isScrolling;
14916
14917  // setup event capturing
14918  var events = {
14919
14920    handleEvent: function(event) {
14921
14922      switch (event.type) {
14923        case 'touchstart': this.start(event); break;
14924        case 'touchmove': this.move(event); break;
14925        case 'touchend': offloadFn(this.end(event)); break;
14926        case 'webkitTransitionEnd':
14927        case 'msTransitionEnd':
14928        case 'oTransitionEnd':
14929        case 'otransitionend':
14930        case 'transitionend': offloadFn(this.transitionEnd(event)); break;
14931        case 'resize': offloadFn(setup); break;
14932      }
14933
14934      if (options.stopPropagation) event.stopPropagation();
14935
14936    },
14937    start: function(event) {
14938
14939      var touches = event.touches[0];
14940
14941      // measure start values
14942      start = {
14943
14944        // get initial touch coords
14945        x: touches.pageX,
14946        y: touches.pageY,
14947
14948        // store time to determine touch duration
14949        time: +new Date
14950
14951      };
14952
14953      // used for testing first move event
14954      isScrolling = undefined;
14955
14956      // reset delta and end measurements
14957      delta = {};
14958
14959      // attach touchmove and touchend listeners
14960      element.addEventListener('touchmove', this, false);
14961      element.addEventListener('touchend', this, false);
14962
14963    },
14964    move: function(event) {
14965
14966      // ensure swiping with one touch and not pinching
14967      if ( event.touches.length > 1 || event.scale && event.scale !== 1) return
14968
14969      if (options.disableScroll) event.preventDefault();
14970
14971      var touches = event.touches[0];
14972
14973      // measure change in x and y
14974      delta = {
14975        x: touches.pageX - start.x,
14976        y: touches.pageY - start.y
14977      }
14978
14979      // determine if scrolling test has run - one time test
14980      if ( typeof isScrolling == 'undefined') {
14981        isScrolling = !!( isScrolling || Math.abs(delta.x) < Math.abs(delta.y) );
14982      }
14983
14984      // if user is not trying to scroll vertically
14985      if (!isScrolling) {
14986
14987        // prevent native scrolling
14988        event.preventDefault();
14989
14990        // stop slideshow
14991        stop();
14992
14993        // increase resistance if first or last slide
14994        if (options.continuous) { // we don't add resistance at the end
14995
14996          translate(circle(index-1), delta.x + slidePos[circle(index-1)], 0);
14997          translate(index, delta.x + slidePos[index], 0);
14998          translate(circle(index+1), delta.x + slidePos[circle(index+1)], 0);
14999
15000        } else {
15001
15002          delta.x =
15003            delta.x /
15004              ( (!index && delta.x > 0               // if first slide and sliding left
15005                || index == slides.length - 1        // or if last slide and sliding right
15006                && delta.x < 0                       // and if sliding at all
15007              ) ?
15008              ( Math.abs(delta.x) / width + 1 )      // determine resistance level
15009              : 1 );                                 // no resistance if false
15010
15011          // translate 1:1
15012          translate(index-1, delta.x + slidePos[index-1], 0);
15013          translate(index, delta.x + slidePos[index], 0);
15014          translate(index+1, delta.x + slidePos[index+1], 0);
15015        }
15016
15017      }
15018
15019    },
15020    end: function(event) {
15021
15022      // measure duration
15023      var duration = +new Date - start.time;
15024
15025      // determine if slide attempt triggers next/prev slide
15026      var isValidSlide =
15027            Number(duration) < 250               // if slide duration is less than 250ms
15028            && Math.abs(delta.x) > 20            // and if slide amt is greater than 20px
15029            || Math.abs(delta.x) > width/2;      // or if slide amt is greater than half the width
15030
15031      // determine if slide attempt is past start and end
15032      var isPastBounds =
15033            !index && delta.x > 0                            // if first slide and slide amt is greater than 0
15034            || index == slides.length - 1 && delta.x < 0;    // or if last slide and slide amt is less than 0
15035
15036      if (options.continuous) isPastBounds = false;
15037
15038      // determine direction of swipe (true:right, false:left)
15039      var direction = delta.x < 0;
15040
15041      // if not scrolling vertically
15042      if (!isScrolling) {
15043
15044        if (isValidSlide && !isPastBounds) {
15045
15046          if (direction) {
15047
15048            if (options.continuous) { // we need to get the next in this direction in place
15049
15050              move(circle(index-1), -width, 0);
15051              move(circle(index+2), width, 0);
15052
15053            } else {
15054              move(index-1, -width, 0);
15055            }
15056
15057            move(index, slidePos[index]-width, speed);
15058            move(circle(index+1), slidePos[circle(index+1)]-width, speed);
15059            index = circle(index+1);
15060
15061          } else {
15062            if (options.continuous) { // we need to get the next in this direction in place
15063
15064              move(circle(index+1), width, 0);
15065              move(circle(index-2), -width, 0);
15066
15067            } else {
15068              move(index+1, width, 0);
15069            }
15070
15071            move(index, slidePos[index]+width, speed);
15072            move(circle(index-1), slidePos[circle(index-1)]+width, speed);
15073            index = circle(index-1);
15074
15075          }
15076
15077          options.callback && options.callback(index, slides[index]);
15078
15079        } else {
15080
15081          if (options.continuous) {
15082
15083            move(circle(index-1), -width, speed);
15084            move(index, 0, speed);
15085            move(circle(index+1), width, speed);
15086
15087          } else {
15088
15089            move(index-1, -width, speed);
15090            move(index, 0, speed);
15091            move(index+1, width, speed);
15092          }
15093
15094        }
15095
15096      }
15097
15098      // kill touchmove and touchend event listeners until touchstart called again
15099      element.removeEventListener('touchmove', events, false)
15100      element.removeEventListener('touchend', events, false)
15101
15102    },
15103    transitionEnd: function(event) {
15104
15105      if (parseInt(event.target.getAttribute('data-index'), 10) == index) {
15106
15107        if (delay) begin();
15108
15109        options.transitionEnd && options.transitionEnd.call(event, index, slides[index]);
15110
15111      }
15112
15113    }
15114
15115  }
15116
15117  // trigger setup
15118  setup();
15119
15120  // start auto slideshow if applicable
15121  if (delay) begin();
15122
15123
15124  // add event listeners
15125  if (browser.addEventListener) {
15126
15127    // set touchstart event on element
15128    if (browser.touch) element.addEventListener('touchstart', events, false);
15129
15130    if (browser.transitions) {
15131      element.addEventListener('webkitTransitionEnd', events, false);
15132      element.addEventListener('msTransitionEnd', events, false);
15133      element.addEventListener('oTransitionEnd', events, false);
15134      element.addEventListener('otransitionend', events, false);
15135      element.addEventListener('transitionend', events, false);
15136    }
15137
15138    // set resize event on window
15139    window.addEventListener('resize', events, false);
15140
15141  } else {
15142
15143    window.onresize = function () { setup() }; // to play nice with old IE
15144
15145  }
15146
15147  // expose the Swipe API
15148  return {
15149    setup: function() {
15150
15151      setup();
15152
15153    },
15154    slide: function(to, speed) {
15155
15156      // cancel slideshow
15157      stop();
15158
15159      slide(to, speed);
15160
15161    },
15162    prev: function() {
15163
15164      // cancel slideshow
15165      stop();
15166
15167      prev();
15168
15169    },
15170    next: function() {
15171
15172      // cancel slideshow
15173      stop();
15174
15175      next();
15176
15177    },
15178    stop: function() {
15179
15180      // cancel slideshow
15181      stop();
15182
15183    },
15184    getPos: function() {
15185
15186      // return current index position
15187      return index;
15188
15189    },
15190    getNumSlides: function() {
15191
15192      // return total number of slides
15193      return length;
15194    },
15195    slides: function() {
15196      return slides;
15197    },
15198    kill: function() {
15199
15200      // cancel slideshow
15201      stop();
15202
15203      // reset element
15204      element.style.width = '';
15205      element.style.left = '';
15206
15207      // reset slides
15208      var pos = slides.length;
15209      while(pos--) {
15210
15211        var slide = slides[pos];
15212        slide.style.width = '';
15213        slide.style.left = '';
15214
15215        if (browser.transitions) translate(pos, 0, 0);
15216
15217      }
15218
15219      // removed event listeners
15220      if (browser.addEventListener) {
15221
15222        // remove current event listeners
15223        element.removeEventListener('touchstart', events, false);
15224        element.removeEventListener('webkitTransitionEnd', events, false);
15225        element.removeEventListener('msTransitionEnd', events, false);
15226        element.removeEventListener('oTransitionEnd', events, false);
15227        element.removeEventListener('otransitionend', events, false);
15228        element.removeEventListener('transitionend', events, false);
15229        window.removeEventListener('resize', events, false);
15230
15231      }
15232      else {
15233
15234        window.onresize = null;
15235
15236      }
15237
15238    }
15239  }
15240
15241}
15242
15243
15244if ( window.jQuery || window.Zepto ) {
15245  (function($) {
15246    $.fn.Swipe = function(params) {
15247      return this.each(function() {
15248        $(this).data('Swipe', new Swipe($(this)[0], params));
15249      });
15250    }
15251  })( window.jQuery || window.Zepto )
15252}
15253;
15254
15255
15256
15257
15258

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.