
/*!
 * jQuery JavaScript Library v1.11.1
 * http://jquery.com/
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 *
 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
 * Released under the MIT license
 * http://jquery.org/license
 *
 * Date: 2014-05-01T17:42Z
 */
(function(global,factory){if(typeof module==="object"&&typeof module.exports==="object"){module.exports=global.document?factory(global,!0):function(w){if(!w.document){throw new Error("jQuery requires a window with a document")}
return factory(w)}}else{factory(global)}}(typeof window!=="undefined"?window:this,function(window,noGlobal){var deletedIds=[];var slice=deletedIds.slice;var concat=deletedIds.concat;var push=deletedIds.push;var indexOf=deletedIds.indexOf;var class2type={};var toString=class2type.toString;var hasOwn=class2type.hasOwnProperty;var support={};var version="1.11.1",jQuery=function(selector,context){return new jQuery.fn.init(selector,context)},rtrim=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,rmsPrefix=/^-ms-/,rdashAlpha=/-([\da-z])/gi,fcamelCase=function(all,letter){return letter.toUpperCase()};jQuery.fn=jQuery.prototype={jquery:version,constructor:jQuery,selector:"",length:0,toArray:function(){return slice.call(this)},get:function(num){return num!=null?(num<0?this[num+this.length]:this[num]):slice.call(this)},pushStack:function(elems){var ret=jQuery.merge(this.constructor(),elems);ret.prevObject=this;ret.context=this.context;return ret},each:function(callback,args){return jQuery.each(this,callback,args)},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem)}))},slice:function(){return this.pushStack(slice.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(i){var len=this.length,j=+i+(i<0?len:0);return this.pushStack(j>=0&&j<len?[this[j]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:push,sort:deletedIds.sort,splice:deletedIds.splice};jQuery.extend=jQuery.fn.extend=function(){var src,copyIsArray,copy,name,options,clone,target=arguments[0]||{},i=1,length=arguments.length,deep=!1;if(typeof target==="boolean"){deep=target;target=arguments[i]||{};i++}
if(typeof target!=="object"&&!jQuery.isFunction(target)){target={}}
if(i===length){target=this;i--}
for(;i<length;i++){if((options=arguments[i])!=null){for(name in options){src=target[name];copy=options[name];if(target===copy){continue}
if(deep&&copy&&(jQuery.isPlainObject(copy)||(copyIsArray=jQuery.isArray(copy)))){if(copyIsArray){copyIsArray=!1;clone=src&&jQuery.isArray(src)?src:[]}else{clone=src&&jQuery.isPlainObject(src)?src:{}}
target[name]=jQuery.extend(deep,clone,copy)}else if(copy!==undefined){target[name]=copy}}}}
return target};jQuery.extend({expando:"jQuery"+(version+Math.random()).replace(/\D/g,""),isReady:!0,error:function(msg){throw new Error(msg)},noop:function(){},isFunction:function(obj){return jQuery.type(obj)==="function"},isArray:Array.isArray||function(obj){return jQuery.type(obj)==="array"},isWindow:function(obj){/* jshint eqeqeq: false */
			return obj != null && obj == obj.window;
		},

		isNumeric: function( obj ) {
			// parseFloat NaNs numeric-cast false positives (null|true|false|"")
			// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
			// subtraction forces infinities to NaN
			return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
		},

		isEmptyObject: function( obj ) {
			var name;
			for ( name in obj ) {
				return false;
			}
			return true;
		},

		isPlainObject: function( obj ) {
			var key;

			// Must be an Object.
			// Because of IE, we also have to check the presence of the constructor property.
			// Make sure that DOM nodes and window objects don't pass through, as well
			if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
				return false;
			}

			try {
				// Not own constructor property must be Object
				if ( obj.constructor &&
					!hasOwn.call(obj, "constructor") &&
					!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
					return false;
				}
			} catch ( e ) {
				// IE8,9 Will throw exceptions on certain host objects #9897
				return false;
			}

			// Support: IE<9
			// Handle iteration over inherited properties before own properties.
			if ( support.ownLast ) {
				for ( key in obj ) {
					return hasOwn.call( obj, key );
				}
			}

			// Own properties are enumerated firstly, so to speed up,
			// if last one is own, then all properties are own.
			for ( key in obj ) {}

			return key === undefined || hasOwn.call( obj, key );
		},

		type: function( obj ) {
			if ( obj == null ) {
				return obj + "";
			}
			return typeof obj === "object" || typeof obj === "function" ?
			class2type[ toString.call(obj) ] || "object" :
				typeof obj;
		},

		// Evaluates a script in a global context
		// Workarounds based on findings by Jim Driscoll
		// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
		globalEval: function( data ) {
			if ( data && jQuery.trim( data ) ) {
				// We use execScript on Internet Explorer
				// We use an anonymous function so that context is window
				// rather than jQuery in Firefox
				( window.execScript || function( data ) {
					window[ "eval" ].call( window, data );
				} )( data );
			}
		},

		// Convert dashed to camelCase; used by the css and data modules
		// Microsoft forgot to hump their vendor prefix (#9572)
		camelCase: function( string ) {
			return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
		},

		nodeName: function( elem, name ) {
			return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
		},

		// args is for internal usage only
		each: function( obj, callback, args ) {
			var value,
				i = 0,
				length = obj.length,
				isArray = isArraylike( obj );

			if ( args ) {
				if ( isArray ) {
					for ( ; i < length; i++ ) {
						value = callback.apply( obj[ i ], args );

						if ( value === false ) {
							break;
						}
					}
				} else {
					for ( i in obj ) {
						value = callback.apply( obj[ i ], args );

						if ( value === false ) {
							break;
						}
					}
				}

				// A special, fast, case for the most common use of each
			} else {
				if ( isArray ) {
					for ( ; i < length; i++ ) {
						value = callback.call( obj[ i ], i, obj[ i ] );

						if ( value === false ) {
							break;
						}
					}
				} else {
					for ( i in obj ) {
						value = callback.call( obj[ i ], i, obj[ i ] );

						if ( value === false ) {
							break;
						}
					}
				}
			}

			return obj;
		},

		// Support: Android<4.1, IE<9
		trim: function( text ) {
			return text == null ?
				"" :
				( text + "" ).replace( rtrim, "" );
		},

		// results is for internal usage only
		makeArray: function( arr, results ) {
			var ret = results || [];

			if ( arr != null ) {
				if ( isArraylike( Object(arr) ) ) {
					jQuery.merge( ret,
						typeof arr === "string" ?
							[ arr ] : arr
					);
				} else {
					push.call( ret, arr );
				}
			}

			return ret;
		},

		inArray: function( elem, arr, i ) {
			var len;

			if ( arr ) {
				if ( indexOf ) {
					return indexOf.call( arr, elem, i );
				}

				len = arr.length;
				i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

				for ( ; i < len; i++ ) {
					// Skip accessing in sparse arrays
					if ( i in arr && arr[ i ] === elem ) {
						return i;
					}
				}
			}

			return -1;
		},

		merge: function( first, second ) {
			var len = +second.length,
				j = 0,
				i = first.length;

			while ( j < len ) {
				first[ i++ ] = second[ j++ ];
			}

			// Support: IE<9
			// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
			if ( len !== len ) {
				while ( second[j] !== undefined ) {
					first[ i++ ] = second[ j++ ];
				}
			}

			first.length = i;

			return first;
		},

		grep: function( elems, callback, invert ) {
			var callbackInverse,
				matches = [],
				i = 0,
				length = elems.length,
				callbackExpect = !invert;

			// Go through the array, only saving the items
			// that pass the validator function
			for ( ; i < length; i++ ) {
				callbackInverse = !callback( elems[ i ], i );
				if ( callbackInverse !== callbackExpect ) {
					matches.push( elems[ i ] );
				}
			}

			return matches;
		},

		// arg is for internal usage only
		map: function( elems, callback, arg ) {
			var value,
				i = 0,
				length = elems.length,
				isArray = isArraylike( elems ),
				ret = [];

			// Go through the array, translating each of the items to their new values
			if ( isArray ) {
				for ( ; i < length; i++ ) {
					value = callback( elems[ i ], i, arg );

					if ( value != null ) {
						ret.push( value );
					}
				}

				// Go through every key on the object,
			} else {
				for ( i in elems ) {
					value = callback( elems[ i ], i, arg );

					if ( value != null ) {
						ret.push( value );
					}
				}
			}

			// Flatten any nested arrays
			return concat.apply( [], ret );
		},

		// A global GUID counter for objects
		guid: 1,

		// Bind a function to a context, optionally partially applying any
		// arguments.
		proxy: function( fn, context ) {
			var args, proxy, tmp;

			if ( typeof context === "string" ) {
				tmp = fn[ context ];
				context = fn;
				fn = tmp;
			}

			// Quick check to determine if target is callable, in the spec
			// this throws a TypeError, but we will just return undefined.
			if ( !jQuery.isFunction( fn ) ) {
				return undefined;
			}

			// Simulated bind
			args = slice.call( arguments, 2 );
			proxy = function() {
				return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
			};

			// Set the guid of unique handler to the same of original handler, so it can be removed
			proxy.guid = fn.guid = fn.guid || jQuery.guid++;

			return proxy;
		},

		now: function() {
			return +( new Date() );
		},

		// jQuery.support is not used in Core but other projects attach their
		// properties to it so it needs to exist.
		support: support
	});

// Populate the class2type map
	jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
		class2type[ "[object " + name + "]" ] = name.toLowerCase();
	});

	function isArraylike( obj ) {
		var length = obj.length,
			type = jQuery.type( obj );

		if ( type === "function" || jQuery.isWindow( obj ) ) {
			return false;
		}

		if ( obj.nodeType === 1 && length ) {
			return true;
		}

		return type === "array" || length === 0 ||
			typeof length === "number" && length > 0 && ( length - 1 ) in obj;
	}
	var Sizzle =
		/*!
		 * Sizzle CSS Selector Engine v1.10.19
		 * http://sizzlejs.com/
		 *
		 * Copyright 2013 jQuery Foundation, Inc. and other contributors
		 * Released under the MIT license
		 * http://jquery.org/license
		 *
		 * Date: 2014-04-18
		 */
		(function( window ) {

			var i,
				support,
				Expr,
				getText,
				isXML,
				tokenize,
				compile,
				select,
				outermostContext,
				sortInput,
				hasDuplicate,

			// Local document vars
				setDocument,
				document,
				docElem,
				documentIsHTML,
				rbuggyQSA,
				rbuggyMatches,
				matches,
				contains,

			// Instance-specific data
				expando = "sizzle" + -(new Date()),
				preferredDoc = window.document,
				dirruns = 0,
				done = 0,
				classCache = createCache(),
				tokenCache = createCache(),
				compilerCache = createCache(),
				sortOrder = function( a, b ) {
					if ( a === b ) {
						hasDuplicate = true;
					}
					return 0;
				},

			// General-purpose constants
				strundefined = typeof undefined,
				MAX_NEGATIVE = 1 << 31,

			// Instance methods
				hasOwn = ({}).hasOwnProperty,
				arr = [],
				pop = arr.pop,
				push_native = arr.push,
				push = arr.push,
				slice = arr.slice,
			// Use a stripped-down indexOf if we can't use a native one
				indexOf = arr.indexOf || function( elem ) {
						var i = 0,
							len = this.length;
						for ( ; i < len; i++ ) {
							if ( this[i] === elem ) {
								return i;
							}
						}
						return -1;
					},

				booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",

			// Regular expressions

			// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
				whitespace = "[\\x20\\t\\r\\n\\f]",
			// http://www.w3.org/TR/css3-syntax/#characters
				characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",

			// Loosely modeled on CSS identifier characters
			// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
			// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
				identifier = characterEncoding.replace( "w", "w#" ),

			// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
				attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
						// Operator (capture 2)
					"*([*^$|!~]?=)" + whitespace +
						// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
					"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
					"*\\]",

				pseudos = ":(" + characterEncoding + ")(?:\\((" +
						// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
						// 1. quoted (capture 3; capture 4 or capture 5)
					"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
						// 2. simple (capture 6)
					"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
						// 3. anything else (capture 2)
					".*" +
					")\\)|)",

			// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
				rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),

				rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
				rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),

				rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),

				rpseudo = new RegExp( pseudos ),
				ridentifier = new RegExp( "^" + identifier + "$" ),

				matchExpr = {
					"ID": new RegExp( "^#(" + characterEncoding + ")" ),
					"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
					"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
					"ATTR": new RegExp( "^" + attributes ),
					"PSEUDO": new RegExp( "^" + pseudos ),
					"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
					"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
					"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
					"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
					// For use in libraries implementing .is()
					// We use this for POS matching in `select`
					"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
					whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
				},

				rinputs = /^(?:input|select|textarea|button)$/i,
				rheader = /^h\d$/i,

				rnative = /^[^{]+\{\s*\[native \w/,

			// Easily-parseable/retrievable ID or TAG or CLASS selectors
				rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

				rsibling = /[+~]/,
				rescape = /'|\\/g,

			// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
				runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
				funescape = function( _, escaped, escapedWhitespace ) {
					var high = "0x" + escaped - 0x10000;
					// NaN means non-codepoint
					// Support: Firefox<24
					// Workaround erroneous numeric interpretation of +"0x"
					return high !== high || escapedWhitespace ?
						escaped :
						high < 0 ?
							// BMP codepoint
							String.fromCharCode( high + 0x10000 ) :
							// Supplemental Plane codepoint (surrogate pair)
							String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
				};

// Optimize for push.apply( _, NodeList )
			try {
				push.apply(
					(arr = slice.call( preferredDoc.childNodes )),
					preferredDoc.childNodes
				);
				// Support: Android<4.0
				// Detect silently failing push.apply
				arr[ preferredDoc.childNodes.length ].nodeType;
			} catch ( e ) {
				push = { apply: arr.length ?

					// Leverage slice if possible
					function( target, els ) {
						push_native.apply( target, slice.call(els) );
					} :

					// Support: IE<9
					// Otherwise append directly
					function( target, els ) {
						var j = target.length,
							i = 0;
						// Can't trust NodeList.length
						while ( (target[j++] = els[i++]) ) {}
						target.length = j - 1;
					}
				};
			}

			function Sizzle( selector, context, results, seed ) {
				var match, elem, m, nodeType,
				// QSA vars
					i, groups, old, nid, newContext, newSelector;

				if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
					setDocument( context );
				}

				context = context || document;
				results = results || [];

				if ( !selector || typeof selector !== "string" ) {
					return results;
				}

				if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
					return [];
				}

				if ( documentIsHTML && !seed ) {

					// Shortcuts
					if ( (match = rquickExpr.exec( selector )) ) {
						// Speed-up: Sizzle("#ID")
						if ( (m = match[1]) ) {
							if ( nodeType === 9 ) {
								elem = context.getElementById( m );
								// Check parentNode to catch when Blackberry 4.6 returns
								// nodes that are no longer in the document (jQuery #6963)
								if ( elem && elem.parentNode ) {
									// Handle the case where IE, Opera, and Webkit return items
									// by name instead of ID
									if ( elem.id === m ) {
										results.push( elem );
										return results;
									}
								} else {
									return results;
								}
							} else {
								// Context is not a document
								if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
									contains( context, elem ) && elem.id === m ) {
									results.push( elem );
									return results;
								}
							}

							// Speed-up: Sizzle("TAG")
						} else if ( match[2] ) {
							push.apply( results, context.getElementsByTagName( selector ) );
							return results;

							// Speed-up: Sizzle(".CLASS")
						} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
							push.apply( results, context.getElementsByClassName( m ) );
							return results;
						}
					}

					// QSA path
					if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
						nid = old = expando;
						newContext = context;
						newSelector = nodeType === 9 && selector;

						// qSA works strangely on Element-rooted queries
						// We can work around this by specifying an extra ID on the root
						// and working up from there (Thanks to Andrew Dupont for the technique)
						// IE 8 doesn't work on object elements
						if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
							groups = tokenize( selector );

							if ( (old = context.getAttribute("id")) ) {
								nid = old.replace( rescape, "\\$&" );
							} else {
								context.setAttribute( "id", nid );
							}
							nid = "[id='" + nid + "'] ";

							i = groups.length;
							while ( i-- ) {
								groups[i] = nid + toSelector( groups[i] );
							}
							newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
							newSelector = groups.join(",");
						}

						if ( newSelector ) {
							try {
								push.apply( results,
									newContext.querySelectorAll( newSelector )
								);
								return results;
							} catch(qsaError) {
							} finally {
								if ( !old ) {
									context.removeAttribute("id");
								}
							}
						}
					}
				}

				// All others
				return select( selector.replace( rtrim, "$1" ), context, results, seed );
			}

			/**
			 * Create key-value caches of limited size
			 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
			 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
			 *	deleting the oldest entry
			 */
			function createCache() {
				var keys = [];

				function cache( key, value ) {
					// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
					if ( keys.push( key + " " ) > Expr.cacheLength ) {
						// Only keep the most recent entries
						delete cache[ keys.shift() ];
					}
					return (cache[ key + " " ] = value);
				}
				return cache;
			}

			/**
			 * Mark a function for special use by Sizzle
			 * @param {Function} fn The function to mark
			 */
			function markFunction( fn ) {
				fn[ expando ] = true;
				return fn;
			}

			/**
			 * Support testing using an element
			 * @param {Function} fn Passed the created div and expects a boolean result
			 */
			function assert( fn ) {
				var div = document.createElement("div");

				try {
					return !!fn( div );
				} catch (e) {
					return false;
				} finally {
					// Remove from its parent by default
					if ( div.parentNode ) {
						div.parentNode.removeChild( div );
					}
					// release memory in IE
					div = null;
				}
			}

			/**
			 * Adds the same handler for all of the specified attrs
			 * @param {String} attrs Pipe-separated list of attributes
			 * @param {Function} handler The method that will be applied
			 */
			function addHandle( attrs, handler ) {
				var arr = attrs.split("|"),
					i = attrs.length;

				while ( i-- ) {
					Expr.attrHandle[ arr[i] ] = handler;
				}
			}

			/**
			 * Checks document order of two siblings
			 * @param {Element} a
			 * @param {Element} b
			 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
			 */
			function siblingCheck( a, b ) {
				var cur = b && a,
					diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
						( ~b.sourceIndex || MAX_NEGATIVE ) -
						( ~a.sourceIndex || MAX_NEGATIVE );

				// Use IE sourceIndex if available on both nodes
				if ( diff ) {
					return diff;
				}

				// Check if b follows a
				if ( cur ) {
					while ( (cur = cur.nextSibling) ) {
						if ( cur === b ) {
							return -1;
						}
					}
				}

				return a ? 1 : -1;
			}

			/**
			 * Returns a function to use in pseudos for input types
			 * @param {String} type
			 */
			function createInputPseudo( type ) {
				return function( elem ) {
					var name = elem.nodeName.toLowerCase();
					return name === "input" && elem.type === type;
				};
			}

			/**
			 * Returns a function to use in pseudos for buttons
			 * @param {String} type
			 */
			function createButtonPseudo( type ) {
				return function( elem ) {
					var name = elem.nodeName.toLowerCase();
					return (name === "input" || name === "button") && elem.type === type;
				};
			}

			/**
			 * Returns a function to use in pseudos for positionals
			 * @param {Function} fn
			 */
			function createPositionalPseudo( fn ) {
				return markFunction(function( argument ) {
					argument = +argument;
					return markFunction(function( seed, matches ) {
						var j,
							matchIndexes = fn( [], seed.length, argument ),
							i = matchIndexes.length;

						// Match elements found at the specified indexes
						while ( i-- ) {
							if ( seed[ (j = matchIndexes[i]) ] ) {
								seed[j] = !(matches[j] = seed[j]);
							}
						}
					});
				});
			}

			/**
			 * Checks a node for validity as a Sizzle context
			 * @param {Element|Object=} context
			 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
			 */
			function testContext( context ) {
				return context && typeof context.getElementsByTagName !== strundefined && context;
			}

// Expose support vars for convenience
			support = Sizzle.support = {};

			/**
			 * Detects XML nodes
			 * @param {Element|Object} elem An element or a document
			 * @returns {Boolean} True iff elem is a non-HTML XML node
			 */
			isXML = Sizzle.isXML = function( elem ) {
				// documentElement is verified for cases where it doesn't yet exist
				// (such as loading iframes in IE - #4833)
				var documentElement = elem && (elem.ownerDocument || elem).documentElement;
				return documentElement ? documentElement.nodeName !== "HTML" : false;
			};

			/**
			 * Sets document-related variables once based on the current document
			 * @param {Element|Object} [doc] An element or document object to use to set the document
			 * @returns {Object} Returns the current document
			 */
			setDocument = Sizzle.setDocument = function( node ) {
				var hasCompare,
					doc = node ? node.ownerDocument || node : preferredDoc,
					parent = doc.defaultView;

				// If no document and documentElement is available, return
				if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
					return document;
				}

				// Set our document
				document = doc;
				docElem = doc.documentElement;

				// Support tests
				documentIsHTML = !isXML( doc );

				// Support: IE>8
				// If iframe document is assigned to "document" variable and if iframe has been reloaded,
				// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
				// IE6-8 do not support the defaultView property so parent will be undefined
				if ( parent && parent !== parent.top ) {
					// IE11 does not have attachEvent, so all must suffer
					if ( parent.addEventListener ) {
						parent.addEventListener( "unload", function() {
							setDocument();
						}, false );
					} else if ( parent.attachEvent ) {
						parent.attachEvent( "onunload", function() {
							setDocument();
						});
					}
				}

				/* Attributes
				 ---------------------------------------------------------------------- */

				// Support: IE<8
				// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
				support.attributes = assert(function( div ) {
					div.className = "i";
					return !div.getAttribute("className");
				});

				/* getElement(s)By*
				 ---------------------------------------------------------------------- */

				// Check if getElementsByTagName("*") returns only elements
				support.getElementsByTagName = assert(function( div ) {
					div.appendChild( doc.createComment("") );
					return !div.getElementsByTagName("*").length;
				});

				// Check if getElementsByClassName can be trusted
				support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
					div.innerHTML = "<div class='a'></div><div class='a i'></div>";

					// Support: Safari<4
					// Catch class over-caching
					div.firstChild.className = "i";
					// Support: Opera<10
					// Catch gEBCN failure to find non-leading classes
					return div.getElementsByClassName("i").length === 2;
				});

				// Support: IE<10
				// Check if getElementById returns elements by name
				// The broken getElementById methods don't pick up programatically-set names,
				// so use a roundabout getElementsByName test
				support.getById = assert(function( div ) {
					docElem.appendChild( div ).id = expando;
					return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
				});

				// ID find and filter
				if ( support.getById ) {
					Expr.find["ID"] = function( id, context ) {
						if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
							var m = context.getElementById( id );
							// Check parentNode to catch when Blackberry 4.6 returns
							// nodes that are no longer in the document #6963
							return m && m.parentNode ? [ m ] : [];
						}
					};
					Expr.filter["ID"] = function( id ) {
						var attrId = id.replace( runescape, funescape );
						return function( elem ) {
							return elem.getAttribute("id") === attrId;
						};
					};
				} else {
					// Support: IE6/7
					// getElementById is not reliable as a find shortcut
					delete Expr.find["ID"];

					Expr.filter["ID"] =  function( id ) {
						var attrId = id.replace( runescape, funescape );
						return function( elem ) {
							var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
							return node && node.value === attrId;
						};
					};
				}

				// Tag
				Expr.find["TAG"] = support.getElementsByTagName ?
					function( tag, context ) {
						if ( typeof context.getElementsByTagName !== strundefined ) {
							return context.getElementsByTagName( tag );
						}
					} :
					function( tag, context ) {
						var elem,
							tmp = [],
							i = 0,
							results = context.getElementsByTagName( tag );

						// Filter out possible comments
						if ( tag === "*" ) {
							while ( (elem = results[i++]) ) {
								if ( elem.nodeType === 1 ) {
									tmp.push( elem );
								}
							}

							return tmp;
						}
						return results;
					};

				// Class
				Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
					if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
						return context.getElementsByClassName( className );
					}
				};

				/* QSA/matchesSelector
				 ---------------------------------------------------------------------- */

				// QSA and matchesSelector support

				// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
				rbuggyMatches = [];

				// qSa(:focus) reports false when true (Chrome 21)
				// We allow this because of a bug in IE8/9 that throws an error
				// whenever `document.activeElement` is accessed on an iframe
				// So, we allow :focus to pass through QSA all the time to avoid the IE error
				// See http://bugs.jquery.com/ticket/13378
				rbuggyQSA = [];

				if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
					// Build QSA regex
					// Regex strategy adopted from Diego Perini
					assert(function( div ) {
						// Select is set to empty string on purpose
						// This is to test IE's treatment of not explicitly
						// setting a boolean content attribute,
						// since its presence should be enough
						// http://bugs.jquery.com/ticket/12359
						div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";

						// Support: IE8, Opera 11-12.16
						// Nothing should be selected when empty strings follow ^= or $= or *=
						// The test attribute must be unknown in Opera but "safe" for WinRT
						// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
						if ( div.querySelectorAll("[msallowclip^='']").length ) {
							rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
						}

						// Support: IE8
						// Boolean attributes and "value" are not treated correctly
						if ( !div.querySelectorAll("[selected]").length ) {
							rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
						}

						// Webkit/Opera - :checked should return selected option elements
						// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
						// IE8 throws error here and will not see later tests
						if ( !div.querySelectorAll(":checked").length ) {
							rbuggyQSA.push(":checked");
						}
					});

					assert(function( div ) {
						// Support: Windows 8 Native Apps
						// The type and name attributes are restricted during .innerHTML assignment
						var input = doc.createElement("input");
						input.setAttribute( "type", "hidden" );
						div.appendChild( input ).setAttribute( "name", "D" );

						// Support: IE8
						// Enforce case-sensitivity of name attribute
						if ( div.querySelectorAll("[name=d]").length ) {
							rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
						}

						// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
						// IE8 throws error here and will not see later tests
						if ( !div.querySelectorAll(":enabled").length ) {
							rbuggyQSA.push( ":enabled", ":disabled" );
						}

						// Opera 10-11 does not throw on post-comma invalid pseudos
						div.querySelectorAll("*,:x");
						rbuggyQSA.push(",.*:");
					});
				}

				if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
					docElem.webkitMatchesSelector ||
					docElem.mozMatchesSelector ||
					docElem.oMatchesSelector ||
					docElem.msMatchesSelector) )) ) {

					assert(function( div ) {
						// Check to see if it's possible to do matchesSelector
						// on a disconnected node (IE 9)
						support.disconnectedMatch = matches.call( div, "div" );

						// This should fail with an exception
						// Gecko does not error, returns false instead
						matches.call( div, "[s!='']:x" );
						rbuggyMatches.push( "!=", pseudos );
					});
				}

				rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
				rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );

				/* Contains
				 ---------------------------------------------------------------------- */
				hasCompare = rnative.test( docElem.compareDocumentPosition );

				// Element contains another
				// Purposefully does not implement inclusive descendent
				// As in, an element does not contain itself
				contains = hasCompare || rnative.test( docElem.contains ) ?
					function( a, b ) {
						var adown = a.nodeType === 9 ? a.documentElement : a,
							bup = b && b.parentNode;
						return a === bup || !!( bup && bup.nodeType === 1 && (
								adown.contains ?
									adown.contains( bup ) :
								a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
							));
					} :
					function( a, b ) {
						if ( b ) {
							while ( (b = b.parentNode) ) {
								if ( b === a ) {
									return true;
								}
							}
						}
						return false;
					};

				/* Sorting
				 ---------------------------------------------------------------------- */

				// Document order sorting
				sortOrder = hasCompare ?
					function( a, b ) {

						// Flag for duplicate removal
						if ( a === b ) {
							hasDuplicate = true;
							return 0;
						}

						// Sort on method existence if only one input has compareDocumentPosition
						var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
						if ( compare ) {
							return compare;
						}

						// Calculate position if both inputs belong to the same document
						compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
							a.compareDocumentPosition( b ) :

							// Otherwise we know they are disconnected
							1;

						// Disconnected nodes
						if ( compare & 1 ||
							(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {

							// Choose the first element that is related to our preferred document
							if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
								return -1;
							}
							if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
								return 1;
							}

							// Maintain original order
							return sortInput ?
								( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
								0;
						}

						return compare & 4 ? -1 : 1;
					} :
					function( a, b ) {
						// Exit early if the nodes are identical
						if ( a === b ) {
							hasDuplicate = true;
							return 0;
						}

						var cur,
							i = 0,
							aup = a.parentNode,
							bup = b.parentNode,
							ap = [ a ],
							bp = [ b ];

						// Parentless nodes are either documents or disconnected
						if ( !aup || !bup ) {
							return a === doc ? -1 :
								b === doc ? 1 :
									aup ? -1 :
										bup ? 1 :
											sortInput ?
												( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
												0;

							// If the nodes are siblings, we can do a quick check
						} else if ( aup === bup ) {
							return siblingCheck( a, b );
						}

						// Otherwise we need full lists of their ancestors for comparison
						cur = a;
						while ( (cur = cur.parentNode) ) {
							ap.unshift( cur );
						}
						cur = b;
						while ( (cur = cur.parentNode) ) {
							bp.unshift( cur );
						}

						// Walk down the tree looking for a discrepancy
						while ( ap[i] === bp[i] ) {
							i++;
						}

						return i ?
							// Do a sibling check if the nodes have a common ancestor
							siblingCheck( ap[i], bp[i] ) :

							// Otherwise nodes in our document sort first
							ap[i] === preferredDoc ? -1 :
								bp[i] === preferredDoc ? 1 :
									0;
					};

				return doc;
			};

			Sizzle.matches = function( expr, elements ) {
				return Sizzle( expr, null, null, elements );
			};

			Sizzle.matchesSelector = function( elem, expr ) {
				// Set document vars if needed
				if ( ( elem.ownerDocument || elem ) !== document ) {
					setDocument( elem );
				}

				// Make sure that attribute selectors are quoted
				expr = expr.replace( rattributeQuotes, "='$1']" );

				if ( support.matchesSelector && documentIsHTML &&
					( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
					( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {

					try {
						var ret = matches.call( elem, expr );

						// IE 9's matchesSelector returns false on disconnected nodes
						if ( ret || support.disconnectedMatch ||
								// As well, disconnected nodes are said to be in a document
								// fragment in IE 9
							elem.document && elem.document.nodeType !== 11 ) {
							return ret;
						}
					} catch(e) {}
				}

				return Sizzle( expr, document, null, [ elem ] ).length > 0;
			};

			Sizzle.contains = function( context, elem ) {
				// Set document vars if needed
				if ( ( context.ownerDocument || context ) !== document ) {
					setDocument( context );
				}
				return contains( context, elem );
			};

			Sizzle.attr = function( elem, name ) {
				// Set document vars if needed
				if ( ( elem.ownerDocument || elem ) !== document ) {
					setDocument( elem );
				}

				var fn = Expr.attrHandle[ name.toLowerCase() ],
				// Don't get fooled by Object.prototype properties (jQuery #13807)
					val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
						fn( elem, name, !documentIsHTML ) :
						undefined;

				return val !== undefined ?
					val :
					support.attributes || !documentIsHTML ?
						elem.getAttribute( name ) :
						(val = elem.getAttributeNode(name)) && val.specified ?
							val.value :
							null;
			};

			Sizzle.error = function( msg ) {
				throw new Error( "Syntax error, unrecognized expression: " + msg );
			};

			/**
			 * Document sorting and removing duplicates
			 * @param {ArrayLike} results
			 */
			Sizzle.uniqueSort = function( results ) {
				var elem,
					duplicates = [],
					j = 0,
					i = 0;

				// Unless we *know* we can detect duplicates, assume their presence
				hasDuplicate = !support.detectDuplicates;
				sortInput = !support.sortStable && results.slice( 0 );
				results.sort( sortOrder );

				if ( hasDuplicate ) {
					while ( (elem = results[i++]) ) {
						if ( elem === results[ i ] ) {
							j = duplicates.push( i );
						}
					}
					while ( j-- ) {
						results.splice( duplicates[ j ], 1 );
					}
				}

				// Clear input after sorting to release objects
				// See https://github.com/jquery/sizzle/pull/225
				sortInput = null;

				return results;
			};

			/**
			 * Utility function for retrieving the text value of an array of DOM nodes
			 * @param {Array|Element} elem
			 */
			getText = Sizzle.getText = function( elem ) {
				var node,
					ret = "",
					i = 0,
					nodeType = elem.nodeType;

				if ( !nodeType ) {
					// If no nodeType, this is expected to be an array
					while ( (node = elem[i++]) ) {
						// Do not traverse comment nodes
						ret += getText( node );
					}
				} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
					// Use textContent for elements
					// innerText usage removed for consistency of new lines (jQuery #11153)
					if ( typeof elem.textContent === "string" ) {
						return elem.textContent;
					} else {
						// Traverse its children
						for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
							ret += getText( elem );
						}
					}
				} else if ( nodeType === 3 || nodeType === 4 ) {
					return elem.nodeValue;
				}
				// Do not include comment or processing instruction nodes

				return ret;
			};

			Expr = Sizzle.selectors = {

				// Can be adjusted by the user
				cacheLength: 50,

				createPseudo: markFunction,

				match: matchExpr,

				attrHandle: {},

				find: {},

				relative: {
					">": { dir: "parentNode", first: true },
					" ": { dir: "parentNode" },
					"+": { dir: "previousSibling", first: true },
					"~": { dir: "previousSibling" }
				},

				preFilter: {
					"ATTR": function( match ) {
						match[1] = match[1].replace( runescape, funescape );

						// Move the given value to match[3] whether quoted or unquoted
						match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );

						if ( match[2] === "~=" ) {
							match[3] = " " + match[3] + " ";
						}

						return match.slice( 0, 4 );
					},

					"CHILD": function( match ) {
						/* matches from matchExpr["CHILD"]
						 1 type (only|nth|...)
						 2 what (child|of-type)
						 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
						 4 xn-component of xn+y argument ([+-]?\d*n|)
						 5 sign of xn-component
						 6 x of xn-component
						 7 sign of y-component
						 8 y of y-component
						 */
						match[1] = match[1].toLowerCase();

						if ( match[1].slice( 0, 3 ) === "nth" ) {
							// nth-* requires argument
							if ( !match[3] ) {
								Sizzle.error( match[0] );
							}

							// numeric x and y parameters for Expr.filter.CHILD
							// remember that false/true cast respectively to 0/1
							match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
							match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );

							// other types prohibit arguments
						} else if ( match[3] ) {
							Sizzle.error( match[0] );
						}

						return match;
					},

					"PSEUDO": function( match ) {
						var excess,
							unquoted = !match[6] && match[2];

						if ( matchExpr["CHILD"].test( match[0] ) ) {
							return null;
						}

						// Accept quoted arguments as-is
						if ( match[3] ) {
							match[2] = match[4] || match[5] || "";

							// Strip excess characters from unquoted arguments
						} else if ( unquoted && rpseudo.test( unquoted ) &&
								// Get excess from tokenize (recursively)
							(excess = tokenize( unquoted, true )) &&
								// advance to the next closing parenthesis
							(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {

							// excess is a negative index
							match[0] = match[0].slice( 0, excess );
							match[2] = unquoted.slice( 0, excess );
						}

						// Return only captures needed by the pseudo filter method (type and argument)
						return match.slice( 0, 3 );
					}
				},

				filter: {

					"TAG": function( nodeNameSelector ) {
						var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
						return nodeNameSelector === "*" ?
							function() { return true; } :
							function( elem ) {
								return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
							};
					},

					"CLASS": function( className ) {
						var pattern = classCache[ className + " " ];

						return pattern ||
							(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
							classCache( className, function( elem ) {
								return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
							});
					},

					"ATTR": function( name, operator, check ) {
						return function( elem ) {
							var result = Sizzle.attr( elem, name );

							if ( result == null ) {
								return operator === "!=";
							}
							if ( !operator ) {
								return true;
							}

							result += "";

							return operator === "=" ? result === check :
								operator === "!=" ? result !== check :
									operator === "^=" ? check && result.indexOf( check ) === 0 :
										operator === "*=" ? check && result.indexOf( check ) > -1 :
											operator === "$=" ? check && result.slice( -check.length ) === check :
												operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
													operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
														false;
						};
					},

					"CHILD": function( type, what, argument, first, last ) {
						var simple = type.slice( 0, 3 ) !== "nth",
							forward = type.slice( -4 ) !== "last",
							ofType = what === "of-type";

						return first === 1 && last === 0 ?

							// Shortcut for :nth-*(n)
							function( elem ) {
								return !!elem.parentNode;
							} :

							function( elem, context, xml ) {
								var cache, outerCache, node, diff, nodeIndex, start,
									dir = simple !== forward ? "nextSibling" : "previousSibling",
									parent = elem.parentNode,
									name = ofType && elem.nodeName.toLowerCase(),
									useCache = !xml && !ofType;

								if ( parent ) {

									// :(first|last|only)-(child|of-type)
									if ( simple ) {
										while ( dir ) {
											node = elem;
											while ( (node = node[ dir ]) ) {
												if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
													return false;
												}
											}
											// Reverse direction for :only-* (if we haven't yet done so)
											start = dir = type === "only" && !start && "nextSibling";
										}
										return true;
									}

									start = [ forward ? parent.firstChild : parent.lastChild ];

									// non-xml :nth-child(...) stores cache data on `parent`
									if ( forward && useCache ) {
										// Seek `elem` from a previously-cached index
										outerCache = parent[ expando ] || (parent[ expando ] = {});
										cache = outerCache[ type ] || [];
										nodeIndex = cache[0] === dirruns && cache[1];
										diff = cache[0] === dirruns && cache[2];
										node = nodeIndex && parent.childNodes[ nodeIndex ];

										while ( (node = ++nodeIndex && node && node[ dir ] ||

											// Fallback to seeking `elem` from the start
										(diff = nodeIndex = 0) || start.pop()) ) {

											// When found, cache indexes on `parent` and break
											if ( node.nodeType === 1 && ++diff && node === elem ) {
												outerCache[ type ] = [ dirruns, nodeIndex, diff ];
												break;
											}
										}

										// Use previously-cached element index if available
									} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
										diff = cache[1];

										// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
									} else {
										// Use the same loop as above to seek `elem` from the start
										while ( (node = ++nodeIndex && node && node[ dir ] ||
										(diff = nodeIndex = 0) || start.pop()) ) {

											if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
												// Cache the index of each encountered element
												if ( useCache ) {
													(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
												}

												if ( node === elem ) {
													break;
												}
											}
										}
									}

									// Incorporate the offset, then check against cycle size
									diff -= last;
									return diff === first || ( diff % first === 0 && diff / first >= 0 );
								}
							};
					},

					"PSEUDO": function( pseudo, argument ) {
						// pseudo-class names are case-insensitive
						// http://www.w3.org/TR/selectors/#pseudo-classes
						// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
						// Remember that setFilters inherits from pseudos
						var args,
							fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
								Sizzle.error( "unsupported pseudo: " + pseudo );

						// The user may use createPseudo to indicate that
						// arguments are needed to create the filter function
						// just as Sizzle does
						if ( fn[ expando ] ) {
							return fn( argument );
						}

						// But maintain support for old signatures
						if ( fn.length > 1 ) {
							args = [ pseudo, pseudo, "", argument ];
							return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
								markFunction(function( seed, matches ) {
									var idx,
										matched = fn( seed, argument ),
										i = matched.length;
									while ( i-- ) {
										idx = indexOf.call( seed, matched[i] );
										seed[ idx ] = !( matches[ idx ] = matched[i] );
									}
								}) :
								function( elem ) {
									return fn( elem, 0, args );
								};
						}

						return fn;
					}
				},

				pseudos: {
					// Potentially complex pseudos
					"not": markFunction(function( selector ) {
						// Trim the selector passed to compile
						// to avoid treating leading and trailing
						// spaces as combinators
						var input = [],
							results = [],
							matcher = compile( selector.replace( rtrim, "$1" ) );

						return matcher[ expando ] ?
							markFunction(function( seed, matches, context, xml ) {
								var elem,
									unmatched = matcher( seed, null, xml, [] ),
									i = seed.length;

								// Match elements unmatched by `matcher`
								while ( i-- ) {
									if ( (elem = unmatched[i]) ) {
										seed[i] = !(matches[i] = elem);
									}
								}
							}) :
							function( elem, context, xml ) {
								input[0] = elem;
								matcher( input, null, xml, results );
								return !results.pop();
							};
					}),

					"has": markFunction(function( selector ) {
						return function( elem ) {
							return Sizzle( selector, elem ).length > 0;
						};
					}),

					"contains": markFunction(function( text ) {
						return function( elem ) {
							return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
						};
					}),

					// "Whether an element is represented by a :lang() selector
					// is based solely on the element's language value
					// being equal to the identifier C,
					// or beginning with the identifier C immediately followed by "-".
					// The matching of C against the element's language value is performed case-insensitively.
					// The identifier C does not have to be a valid language name."
					// http://www.w3.org/TR/selectors/#lang-pseudo
					"lang": markFunction( function( lang ) {
						// lang value must be a valid identifier
						if ( !ridentifier.test(lang || "") ) {
							Sizzle.error( "unsupported lang: " + lang );
						}
						lang = lang.replace( runescape, funescape ).toLowerCase();
						return function( elem ) {
							var elemLang;
							do {
								if ( (elemLang = documentIsHTML ?
										elem.lang :
									elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {

									elemLang = elemLang.toLowerCase();
									return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
								}
							} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
							return false;
						};
					}),

					// Miscellaneous
					"target": function( elem ) {
						var hash = window.location && window.location.hash;
						return hash && hash.slice( 1 ) === elem.id;
					},

					"root": function( elem ) {
						return elem === docElem;
					},

					"focus": function( elem ) {
						return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
					},

					// Boolean properties
					"enabled": function( elem ) {
						return elem.disabled === false;
					},

					"disabled": function( elem ) {
						return elem.disabled === true;
					},

					"checked": function( elem ) {
						// In CSS3, :checked should return both checked and selected elements
						// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
						var nodeName = elem.nodeName.toLowerCase();
						return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
					},

					"selected": function( elem ) {
						// Accessing this property makes selected-by-default
						// options in Safari work properly
						if ( elem.parentNode ) {
							elem.parentNode.selectedIndex;
						}

						return elem.selected === true;
					},

					// Contents
					"empty": function( elem ) {
						// http://www.w3.org/TR/selectors/#empty-pseudo
						// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
						//   but not by others (comment: 8; processing instruction: 7; etc.)
						// nodeType < 6 works because attributes (2) do not appear as children
						for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
							if ( elem.nodeType < 6 ) {
								return false;
							}
						}
						return true;
					},

					"parent": function( elem ) {
						return !Expr.pseudos["empty"]( elem );
					},

					// Element/input types
					"header": function( elem ) {
						return rheader.test( elem.nodeName );
					},

					"input": function( elem ) {
						return rinputs.test( elem.nodeName );
					},

					"button": function( elem ) {
						var name = elem.nodeName.toLowerCase();
						return name === "input" && elem.type === "button" || name === "button";
					},

					"text": function( elem ) {
						var attr;
						return elem.nodeName.toLowerCase() === "input" &&
							elem.type === "text" &&

								// Support: IE<8
								// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
							( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
					},

					// Position-in-collection
					"first": createPositionalPseudo(function() {
						return [ 0 ];
					}),

					"last": createPositionalPseudo(function( matchIndexes, length ) {
						return [ length - 1 ];
					}),

					"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
						return [ argument < 0 ? argument + length : argument ];
					}),

					"even": createPositionalPseudo(function( matchIndexes, length ) {
						var i = 0;
						for ( ; i < length; i += 2 ) {
							matchIndexes.push( i );
						}
						return matchIndexes;
					}),

					"odd": createPositionalPseudo(function( matchIndexes, length ) {
						var i = 1;
						for ( ; i < length; i += 2 ) {
							matchIndexes.push( i );
						}
						return matchIndexes;
					}),

					"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
						var i = argument < 0 ? argument + length : argument;
						for ( ; --i >= 0; ) {
							matchIndexes.push( i );
						}
						return matchIndexes;
					}),

					"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
						var i = argument < 0 ? argument + length : argument;
						for ( ; ++i < length; ) {
							matchIndexes.push( i );
						}
						return matchIndexes;
					})
				}
			};

			Expr.pseudos["nth"] = Expr.pseudos["eq"];

// Add button/input type pseudos
			for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
				Expr.pseudos[ i ] = createInputPseudo( i );
			}
			for ( i in { submit: true, reset: true } ) {
				Expr.pseudos[ i ] = createButtonPseudo( i );
			}

// Easy API for creating new setFilters
			function setFilters() {}
			setFilters.prototype = Expr.filters = Expr.pseudos;
			Expr.setFilters = new setFilters();

			tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
				var matched, match, tokens, type,
					soFar, groups, preFilters,
					cached = tokenCache[ selector + " " ];

				if ( cached ) {
					return parseOnly ? 0 : cached.slice( 0 );
				}

				soFar = selector;
				groups = [];
				preFilters = Expr.preFilter;

				while ( soFar ) {

					// Comma and first run
					if ( !matched || (match = rcomma.exec( soFar )) ) {
						if ( match ) {
							// Don't consume trailing commas as valid
							soFar = soFar.slice( match[0].length ) || soFar;
						}
						groups.push( (tokens = []) );
					}

					matched = false;

					// Combinators
					if ( (match = rcombinators.exec( soFar )) ) {
						matched = match.shift();
						tokens.push({
							value: matched,
							// Cast descendant combinators to space
							type: match[0].replace( rtrim, " " )
						});
						soFar = soFar.slice( matched.length );
					}

					// Filters
					for ( type in Expr.filter ) {
						if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
							(match = preFilters[ type ]( match ))) ) {
							matched = match.shift();
							tokens.push({
								value: matched,
								type: type,
								matches: match
							});
							soFar = soFar.slice( matched.length );
						}
					}

					if ( !matched ) {
						break;
					}
				}

				// Return the length of the invalid excess
				// if we're just parsing
				// Otherwise, throw an error or return tokens
				return parseOnly ?
					soFar.length :
					soFar ?
						Sizzle.error( selector ) :
						// Cache the tokens
						tokenCache( selector, groups ).slice( 0 );
			};

			function toSelector( tokens ) {
				var i = 0,
					len = tokens.length,
					selector = "";
				for ( ; i < len; i++ ) {
					selector += tokens[i].value;
				}
				return selector;
			}

			function addCombinator( matcher, combinator, base ) {
				var dir = combinator.dir,
					checkNonElements = base && dir === "parentNode",
					doneName = done++;

				return combinator.first ?
					// Check against closest ancestor/preceding element
					function( elem, context, xml ) {
						while ( (elem = elem[ dir ]) ) {
							if ( elem.nodeType === 1 || checkNonElements ) {
								return matcher( elem, context, xml );
							}
						}
					} :

					// Check against all ancestor/preceding elements
					function( elem, context, xml ) {
						var oldCache, outerCache,
							newCache = [ dirruns, doneName ];

						// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
						if ( xml ) {
							while ( (elem = elem[ dir ]) ) {
								if ( elem.nodeType === 1 || checkNonElements ) {
									if ( matcher( elem, context, xml ) ) {
										return true;
									}
								}
							}
						} else {
							while ( (elem = elem[ dir ]) ) {
								if ( elem.nodeType === 1 || checkNonElements ) {
									outerCache = elem[ expando ] || (elem[ expando ] = {});
									if ( (oldCache = outerCache[ dir ]) &&
										oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {

										// Assign to newCache so results back-propagate to previous elements
										return (newCache[ 2 ] = oldCache[ 2 ]);
									} else {
										// Reuse newcache so results back-propagate to previous elements
										outerCache[ dir ] = newCache;

										// A match means we're done; a fail means we have to keep checking
										if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
											return true;
										}
									}
								}
							}
						}
					};
			}

			function elementMatcher( matchers ) {
				return matchers.length > 1 ?
					function( elem, context, xml ) {
						var i = matchers.length;
						while ( i-- ) {
							if ( !matchers[i]( elem, context, xml ) ) {
								return false;
							}
						}
						return true;
					} :
					matchers[0];
			}

			function multipleContexts( selector, contexts, results ) {
				var i = 0,
					len = contexts.length;
				for ( ; i < len; i++ ) {
					Sizzle( selector, contexts[i], results );
				}
				return results;
			}

			function condense( unmatched, map, filter, context, xml ) {
				var elem,
					newUnmatched = [],
					i = 0,
					len = unmatched.length,
					mapped = map != null;

				for ( ; i < len; i++ ) {
					if ( (elem = unmatched[i]) ) {
						if ( !filter || filter( elem, context, xml ) ) {
							newUnmatched.push( elem );
							if ( mapped ) {
								map.push( i );
							}
						}
					}
				}

				return newUnmatched;
			}

			function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
				if ( postFilter && !postFilter[ expando ] ) {
					postFilter = setMatcher( postFilter );
				}
				if ( postFinder && !postFinder[ expando ] ) {
					postFinder = setMatcher( postFinder, postSelector );
				}
				return markFunction(function( seed, results, context, xml ) {
					var temp, i, elem,
						preMap = [],
						postMap = [],
						preexisting = results.length,

					// Get initial elements from seed or context
						elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),

					// Prefilter to get matcher input, preserving a map for seed-results synchronization
						matcherIn = preFilter && ( seed || !selector ) ?
							condense( elems, preMap, preFilter, context, xml ) :
							elems,

						matcherOut = matcher ?
							// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
							postFinder || ( seed ? preFilter : preexisting || postFilter ) ?

								// ...intermediate processing is necessary
								[] :

								// ...otherwise use results directly
								results :
							matcherIn;

					// Find primary matches
					if ( matcher ) {
						matcher( matcherIn, matcherOut, context, xml );
					}

					// Apply postFilter
					if ( postFilter ) {
						temp = condense( matcherOut, postMap );
						postFilter( temp, [], context, xml );

						// Un-match failing elements by moving them back to matcherIn
						i = temp.length;
						while ( i-- ) {
							if ( (elem = temp[i]) ) {
								matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
							}
						}
					}

					if ( seed ) {
						if ( postFinder || preFilter ) {
							if ( postFinder ) {
								// Get the final matcherOut by condensing this intermediate into postFinder contexts
								temp = [];
								i = matcherOut.length;
								while ( i-- ) {
									if ( (elem = matcherOut[i]) ) {
										// Restore matcherIn since elem is not yet a final match
										temp.push( (matcherIn[i] = elem) );
									}
								}
								postFinder( null, (matcherOut = []), temp, xml );
							}

							// Move matched elements from seed to results to keep them synchronized
							i = matcherOut.length;
							while ( i-- ) {
								if ( (elem = matcherOut[i]) &&
									(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {

									seed[temp] = !(results[temp] = elem);
								}
							}
						}

						// Add elements to results, through postFinder if defined
					} else {
						matcherOut = condense(
							matcherOut === results ?
								matcherOut.splice( preexisting, matcherOut.length ) :
								matcherOut
						);
						if ( postFinder ) {
							postFinder( null, results, matcherOut, xml );
						} else {
							push.apply( results, matcherOut );
						}
					}
				});
			}

			function matcherFromTokens( tokens ) {
				var checkContext, matcher, j,
					len = tokens.length,
					leadingRelative = Expr.relative[ tokens[0].type ],
					implicitRelative = leadingRelative || Expr.relative[" "],
					i = leadingRelative ? 1 : 0,

				// The foundational matcher ensures that elements are reachable from top-level context(s)
					matchContext = addCombinator( function( elem ) {
						return elem === checkContext;
					}, implicitRelative, true ),
					matchAnyContext = addCombinator( function( elem ) {
						return indexOf.call( checkContext, elem ) > -1;
					}, implicitRelative, true ),
					matchers = [ function( elem, context, xml ) {
						return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
								(checkContext = context).nodeType ?
									matchContext( elem, context, xml ) :
									matchAnyContext( elem, context, xml ) );
					} ];

				for ( ; i < len; i++ ) {
					if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
						matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
					} else {
						matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );

						// Return special upon seeing a positional matcher
						if ( matcher[ expando ] ) {
							// Find the next relative operator (if any) for proper handling
							j = ++i;
							for ( ; j < len; j++ ) {
								if ( Expr.relative[ tokens[j].type ] ) {
									break;
								}
							}
							return setMatcher(
								i > 1 && elementMatcher( matchers ),
								i > 1 && toSelector(
									// If the preceding token was a descendant combinator, insert an implicit any-element `*`
									tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
								).replace( rtrim, "$1" ),
								matcher,
								i < j && matcherFromTokens( tokens.slice( i, j ) ),
								j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
								j < len && toSelector( tokens )
							);
						}
						matchers.push( matcher );
					}
				}

				return elementMatcher( matchers );
			}

			function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
				var bySet = setMatchers.length > 0,
					byElement = elementMatchers.length > 0,
					superMatcher = function( seed, context, xml, results, outermost ) {
						var elem, j, matcher,
							matchedCount = 0,
							i = "0",
							unmatched = seed && [],
							setMatched = [],
							contextBackup = outermostContext,
						// We must always have either seed elements or outermost context
							elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
						// Use integer dirruns iff this is the outermost matcher
							dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
							len = elems.length;

						if ( outermost ) {
							outermostContext = context !== document && context;
						}

						// Add elements passing elementMatchers directly to results
						// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
						// Support: IE<9, Safari
						// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
						for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
							if ( byElement && elem ) {
								j = 0;
								while ( (matcher = elementMatchers[j++]) ) {
									if ( matcher( elem, context, xml ) ) {
										results.push( elem );
										break;
									}
								}
								if ( outermost ) {
									dirruns = dirrunsUnique;
								}
							}

							// Track unmatched elements for set filters
							if ( bySet ) {
								// They will have gone through all possible matchers
								if ( (elem = !matcher && elem) ) {
									matchedCount--;
								}

								// Lengthen the array for every element, matched or not
								if ( seed ) {
									unmatched.push( elem );
								}
							}
						}

						// Apply set filters to unmatched elements
						matchedCount += i;
						if ( bySet && i !== matchedCount ) {
							j = 0;
							while ( (matcher = setMatchers[j++]) ) {
								matcher( unmatched, setMatched, context, xml );
							}

							if ( seed ) {
								// Reintegrate element matches to eliminate the need for sorting
								if ( matchedCount > 0 ) {
									while ( i-- ) {
										if ( !(unmatched[i] || setMatched[i]) ) {
											setMatched[i] = pop.call( results );
										}
									}
								}

								// Discard index placeholder values to get only actual matches
								setMatched = condense( setMatched );
							}

							// Add matches to results
							push.apply( results, setMatched );

							// Seedless set matches succeeding multiple successful matchers stipulate sorting
							if ( outermost && !seed && setMatched.length > 0 &&
								( matchedCount + setMatchers.length ) > 1 ) {

								Sizzle.uniqueSort( results );
							}
						}

						// Override manipulation of globals by nested matchers
						if ( outermost ) {
							dirruns = dirrunsUnique;
							outermostContext = contextBackup;
						}

						return unmatched;
					};

				return bySet ?
					markFunction( superMatcher ) :
					superMatcher;
			}

			compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
				var i,
					setMatchers = [],
					elementMatchers = [],
					cached = compilerCache[ selector + " " ];

				if ( !cached ) {
					// Generate a function of recursive functions that can be used to check each element
					if ( !match ) {
						match = tokenize( selector );
					}
					i = match.length;
					while ( i-- ) {
						cached = matcherFromTokens( match[i] );
						if ( cached[ expando ] ) {
							setMatchers.push( cached );
						} else {
							elementMatchers.push( cached );
						}
					}

					// Cache the compiled function
					cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );

					// Save selector and tokenization
					cached.selector = selector;
				}
				return cached;
			};

			/**
			 * A low-level selection function that works with Sizzle's compiled
			 *  selector functions
			 * @param {String|Function} selector A selector or a pre-compiled
			 *  selector function built with Sizzle.compile
			 * @param {Element} context
			 * @param {Array} [results]
			 * @param {Array} [seed] A set of elements to match against
			 */
			select = Sizzle.select = function( selector, context, results, seed ) {
				var i, tokens, token, type, find,
					compiled = typeof selector === "function" && selector,
					match = !seed && tokenize( (selector = compiled.selector || selector) );

				results = results || [];

				// Try to minimize operations if there is no seed and only one group
				if ( match.length === 1 ) {

					// Take a shortcut and set the context if the root selector is an ID
					tokens = match[0] = match[0].slice( 0 );
					if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
						support.getById && context.nodeType === 9 && documentIsHTML &&
						Expr.relative[ tokens[1].type ] ) {

						context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
						if ( !context ) {
							return results;

							// Precompiled matchers will still verify ancestry, so step up a level
						} else if ( compiled ) {
							context = context.parentNode;
						}

						selector = selector.slice( tokens.shift().value.length );
					}

					// Fetch a seed set for right-to-left matching
					i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
					while ( i-- ) {
						token = tokens[i];

						// Abort if we hit a combinator
						if ( Expr.relative[ (type = token.type) ] ) {
							break;
						}
						if ( (find = Expr.find[ type ]) ) {
							// Search, expanding context for leading sibling combinators
							if ( (seed = find(
									token.matches[0].replace( runescape, funescape ),
									rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
								)) ) {

								// If seed is empty or no tokens remain, we can return early
								tokens.splice( i, 1 );
								selector = seed.length && toSelector( tokens );
								if ( !selector ) {
									push.apply( results, seed );
									return results;
								}

								break;
							}
						}
					}
				}

				// Compile and execute a filtering function if one is not provided
				// Provide `match` to avoid retokenization if we modified the selector above
				( compiled || compile( selector, match ) )(
					seed,
					context,
					!documentIsHTML,
					results,
					rsibling.test( selector ) && testContext( context.parentNode ) || context
				);
				return results;
			};

// One-time assignments

// Sort stability
			support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;

// Support: Chrome<14
// Always assume duplicates if they aren't passed to the comparison function
			support.detectDuplicates = !!hasDuplicate;

// Initialize against the default document
			setDocument();

// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
// Detached nodes confoundingly follow *each other*
			support.sortDetached = assert(function( div1 ) {
				// Should return 1, but returns 4 (following)
				return div1.compareDocumentPosition( document.createElement("div") ) & 1;
			});

// Support: IE<8
// Prevent attribute/property "interpolation"
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
			if ( !assert(function( div ) {
					div.innerHTML = "<a href='#'></a>";
					return div.firstChild.getAttribute("href") === "#" ;
				}) ) {
				addHandle( "type|href|height|width", function( elem, name, isXML ) {
					if ( !isXML ) {
						return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
					}
				});
			}

// Support: IE<9
// Use defaultValue in place of getAttribute("value")
			if ( !support.attributes || !assert(function( div ) {
					div.innerHTML = "<input/>";
					div.firstChild.setAttribute( "value", "" );
					return div.firstChild.getAttribute( "value" ) === "";
				}) ) {
				addHandle( "value", function( elem, name, isXML ) {
					if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
						return elem.defaultValue;
					}
				});
			}

// Support: IE<9
// Use getAttributeNode to fetch booleans when getAttribute lies
			if ( !assert(function( div ) {
					return div.getAttribute("disabled") == null;
				}) ) {
				addHandle( booleans, function( elem, name, isXML ) {
					var val;
					if ( !isXML ) {
						return elem[ name ] === true ? name.toLowerCase() :
							(val = elem.getAttributeNode( name )) && val.specified ?
								val.value :
								null;
					}
				});
			}

			return Sizzle;

		})( window );



	jQuery.find = Sizzle;
	jQuery.expr = Sizzle.selectors;
	jQuery.expr[":"] = jQuery.expr.pseudos;
	jQuery.unique = Sizzle.uniqueSort;
	jQuery.text = Sizzle.getText;
	jQuery.isXMLDoc = Sizzle.isXML;
	jQuery.contains = Sizzle.contains;



	var rneedsContext = jQuery.expr.match.needsContext;

	var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);



	var risSimple = /^.[^:#\[\.,]*$/;

// Implement the identical functionality for filter and not
	function winnow( elements, qualifier, not ) {
		if ( jQuery.isFunction( qualifier ) ) {
			return jQuery.grep( elements, function( elem, i ) {
				/* jshint -W018 */
				return !!qualifier.call( elem, i, elem ) !== not;
			});

		}

		if ( qualifier.nodeType ) {
			return jQuery.grep( elements, function( elem ) {
				return ( elem === qualifier ) !== not;
			});

		}

		if ( typeof qualifier === "string" ) {
			if ( risSimple.test( qualifier ) ) {
				return jQuery.filter( qualifier, elements, not );
			}

			qualifier = jQuery.filter( qualifier, elements );
		}

		return jQuery.grep( elements, function( elem ) {
			return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
		});
	}

	jQuery.filter = function( expr, elems, not ) {
		var elem = elems[ 0 ];

		if ( not ) {
			expr = ":not(" + expr + ")";
		}

		return elems.length === 1 && elem.nodeType === 1 ?
			jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
			jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
				return elem.nodeType === 1;
			}));
	};

	jQuery.fn.extend({
		find: function( selector ) {
			var i,
				ret = [],
				self = this,
				len = self.length;

			if ( typeof selector !== "string" ) {
				return this.pushStack( jQuery( selector ).filter(function() {
					for ( i = 0; i < len; i++ ) {
						if ( jQuery.contains( self[ i ], this ) ) {
							return true;
						}
					}
				}) );
			}

			for ( i = 0; i < len; i++ ) {
				jQuery.find( selector, self[ i ], ret );
			}

			// Needed because $( selector, context ) becomes $( context ).find( selector )
			ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
			ret.selector = this.selector ? this.selector + " " + selector : selector;
			return ret;
		},
		filter: function( selector ) {
			return this.pushStack( winnow(this, selector || [], false) );
		},
		not: function( selector ) {
			return this.pushStack( winnow(this, selector || [], true) );
		},
		is: function( selector ) {
			return !!winnow(
				this,

				// If this is a positional/relative selector, check membership in the returned set
				// so $("p:first").is("p:last") won't return true for a doc with two "p".
				typeof selector === "string" && rneedsContext.test( selector ) ?
					jQuery( selector ) :
				selector || [],
				false
			).length;
		}
	});


// Initialize a jQuery object


// A central reference to the root jQuery(document)
	var rootjQuery,

	// Use the correct document accordingly with window argument (sandbox)
		document = window.document,

	// A simple way to check for HTML strings
	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
	// Strict HTML recognition (#11290: must start with <)
		rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,

		init = jQuery.fn.init = function( selector, context ) {
			var match, elem;

			// HANDLE: $(""), $(null), $(undefined), $(false)
			if ( !selector ) {
				return this;
			}

			// Handle HTML strings
			if ( typeof selector === "string" ) {
				if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
					// Assume that strings that start and end with <> are HTML and skip the regex check
					match = [ null, selector, null ];

				} else {
					match = rquickExpr.exec( selector );
				}

				// Match html or make sure no context is specified for #id
				if ( match && (match[1] || !context) ) {

					// HANDLE: $(html) -> $(array)
					if ( match[1] ) {
						context = context instanceof jQuery ? context[0] : context;

						// scripts is true for back-compat
						// Intentionally let the error be thrown if parseHTML is not present
						jQuery.merge( this, jQuery.parseHTML(
							match[1],
							context && context.nodeType ? context.ownerDocument || context : document,
							true
						) );

						// HANDLE: $(html, props)
						if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
							for ( match in context ) {
								// Properties of context are called as methods if possible
								if ( jQuery.isFunction( this[ match ] ) ) {
									this[ match ]( context[ match ] );

									// ...and otherwise set as attributes
								} else {
									this.attr( match, context[ match ] );
								}
							}
						}

						return this;

						// HANDLE: $(#id)
					} else {
						elem = document.getElementById( match[2] );

						// Check parentNode to catch when Blackberry 4.6 returns
						// nodes that are no longer in the document #6963
						if ( elem && elem.parentNode ) {
							// Handle the case where IE and Opera return items
							// by name instead of ID
							if ( elem.id !== match[2] ) {
								return rootjQuery.find( selector );
							}

							// Otherwise, we inject the element directly into the jQuery object
							this.length = 1;
							this[0] = elem;
						}

						this.context = document;
						this.selector = selector;
						return this;
					}

					// HANDLE: $(expr, $(...))
				} else if ( !context || context.jquery ) {
					return ( context || rootjQuery ).find( selector );

					// HANDLE: $(expr, context)
					// (which is just equivalent to: $(context).find(expr)
				} else {
					return this.constructor( context ).find( selector );
				}

				// HANDLE: $(DOMElement)
			} else if ( selector.nodeType ) {
				this.context = this[0] = selector;
				this.length = 1;
				return this;

				// HANDLE: $(function)
				// Shortcut for document ready
			} else if ( jQuery.isFunction( selector ) ) {
				return typeof rootjQuery.ready !== "undefined" ?
					rootjQuery.ready( selector ) :
					// Execute immediately if ready is not present
					selector( jQuery );
			}

			if ( selector.selector !== undefined ) {
				this.selector = selector.selector;
				this.context = selector.context;
			}

			return jQuery.makeArray( selector, this );
		};

// Give the init function the jQuery prototype for later instantiation
	init.prototype = jQuery.fn;

// Initialize central reference
	rootjQuery = jQuery( document );


	var rparentsprev = /^(?:parents|prev(?:Until|All))/,
	// methods guaranteed to produce a unique set when starting from a unique set
		guaranteedUnique = {
			children: true,
			contents: true,
			next: true,
			prev: true
		};

	jQuery.extend({
		dir: function( elem, dir, until ) {
			var matched = [],
				cur = elem[ dir ];

			while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
				if ( cur.nodeType === 1 ) {
					matched.push( cur );
				}
				cur = cur[dir];
			}
			return matched;
		},

		sibling: function( n, elem ) {
			var r = [];

			for ( ; n; n = n.nextSibling ) {
				if ( n.nodeType === 1 && n !== elem ) {
					r.push( n );
				}
			}

			return r;
		}
	});

	jQuery.fn.extend({
		has: function( target ) {
			var i,
				targets = jQuery( target, this ),
				len = targets.length;

			return this.filter(function() {
				for ( i = 0; i < len; i++ ) {
					if ( jQuery.contains( this, targets[i] ) ) {
						return true;
					}
				}
			});
		},

		closest: function( selectors, context ) {
			var cur,
				i = 0,
				l = this.length,
				matched = [],
				pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
					jQuery( selectors, context || this.context ) :
					0;

			for ( ; i < l; i++ ) {
				for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
					// Always skip document fragments
					if ( cur.nodeType < 11 && (pos ?
						pos.index(cur) > -1 :

							// Don't pass non-elements to Sizzle
						cur.nodeType === 1 &&
						jQuery.find.matchesSelector(cur, selectors)) ) {

						matched.push( cur );
						break;
					}
				}
			}

			return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
		},

		// Determine the position of an element within
		// the matched set of elements
		index: function( elem ) {

			// No argument, return index in parent
			if ( !elem ) {
				return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
			}

			// index in selector
			if ( typeof elem === "string" ) {
				return jQuery.inArray( this[0], jQuery( elem ) );
			}

			// Locate the position of the desired element
			return jQuery.inArray(
				// If it receives a jQuery object, the first element is used
				elem.jquery ? elem[0] : elem, this );
		},

		add: function( selector, context ) {
			return this.pushStack(
				jQuery.unique(
					jQuery.merge( this.get(), jQuery( selector, context ) )
				)
			);
		},

		addBack: function( selector ) {
			return this.add( selector == null ?
					this.prevObject : this.prevObject.filter(selector)
			);
		}
	});

	function sibling( cur, dir ) {
		do {
			cur = cur[ dir ];
		} while ( cur && cur.nodeType !== 1 );

		return cur;
	}

	jQuery.each({
		parent: function( elem ) {
			var parent = elem.parentNode;
			return parent && parent.nodeType !== 11 ? parent : null;
		},
		parents: function( elem ) {
			return jQuery.dir( elem, "parentNode" );
		},
		parentsUntil: function( elem, i, until ) {
			return jQuery.dir( elem, "parentNode", until );
		},
		next: function( elem ) {
			return sibling( elem, "nextSibling" );
		},
		prev: function( elem ) {
			return sibling( elem, "previousSibling" );
		},
		nextAll: function( elem ) {
			return jQuery.dir( elem, "nextSibling" );
		},
		prevAll: function( elem ) {
			return jQuery.dir( elem, "previousSibling" );
		},
		nextUntil: function( elem, i, until ) {
			return jQuery.dir( elem, "nextSibling", until );
		},
		prevUntil: function( elem, i, until ) {
			return jQuery.dir( elem, "previousSibling", until );
		},
		siblings: function( elem ) {
			return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
		},
		children: function( elem ) {
			return jQuery.sibling( elem.firstChild );
		},
		contents: function( elem ) {
			return jQuery.nodeName( elem, "iframe" ) ?
			elem.contentDocument || elem.contentWindow.document :
				jQuery.merge( [], elem.childNodes );
		}
	}, function( name, fn ) {
		jQuery.fn[ name ] = function( until, selector ) {
			var ret = jQuery.map( this, fn, until );

			if ( name.slice( -5 ) !== "Until" ) {
				selector = until;
			}

			if ( selector && typeof selector === "string" ) {
				ret = jQuery.filter( selector, ret );
			}

			if ( this.length > 1 ) {
				// Remove duplicates
				if ( !guaranteedUnique[ name ] ) {
					ret = jQuery.unique( ret );
				}

				// Reverse order for parents* and prev-derivatives
				if ( rparentsprev.test( name ) ) {
					ret = ret.reverse();
				}
			}

			return this.pushStack( ret );
		};
	});
	var rnotwhite = (/\S+/g);



// String to Object options format cache
	var optionsCache = {};

// Convert String-formatted options into Object-formatted ones and store in cache
	function createOptions( options ) {
		var object = optionsCache[ options ] = {};
		jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
			object[ flag ] = true;
		});
		return object;
	}

	/*
	 * Create a callback list using the following parameters:
	 *
	 *	options: an optional list of space-separated options that will change how
	 *			the callback list behaves or a more traditional option object
	 *
	 * By default a callback list will act like an event callback list and can be
	 * "fired" multiple times.
	 *
	 * Possible options:
	 *
	 *	once:			will ensure the callback list can only be fired once (like a Deferred)
	 *
	 *	memory:			will keep track of previous values and will call any callback added
	 *					after the list has been fired right away with the latest "memorized"
	 *					values (like a Deferred)
	 *
	 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
	 *
	 *	stopOnFalse:	interrupt callings when a callback returns false
	 *
	 */
	jQuery.Callbacks = function( options ) {

		// Convert options from String-formatted to Object-formatted if needed
		// (we check in cache first)
		options = typeof options === "string" ?
			( optionsCache[ options ] || createOptions( options ) ) :
			jQuery.extend( {}, options );

		var // Flag to know if list is currently firing
			firing,
		// Last fire value (for non-forgettable lists)
			memory,
		// Flag to know if list was already fired
			fired,
		// End of the loop when firing
			firingLength,
		// Index of currently firing callback (modified by remove if needed)
			firingIndex,
		// First callback to fire (used internally by add and fireWith)
			firingStart,
		// Actual callback list
			list = [],
		// Stack of fire calls for repeatable lists
			stack = !options.once && [],
		// Fire callbacks
			fire = function( data ) {
				memory = options.memory && data;
				fired = true;
				firingIndex = firingStart || 0;
				firingStart = 0;
				firingLength = list.length;
				firing = true;
				for ( ; list && firingIndex < firingLength; firingIndex++ ) {
					if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
						memory = false; // To prevent further calls using add
						break;
					}
				}
				firing = false;
				if ( list ) {
					if ( stack ) {
						if ( stack.length ) {
							fire( stack.shift() );
						}
					} else if ( memory ) {
						list = [];
					} else {
						self.disable();
					}
				}
			},
		// Actual Callbacks object
			self = {
				// Add a callback or a collection of callbacks to the list
				add: function() {
					if ( list ) {
						// First, we save the current length
						var start = list.length;
						(function add( args ) {
							jQuery.each( args, function( _, arg ) {
								var type = jQuery.type( arg );
								if ( type === "function" ) {
									if ( !options.unique || !self.has( arg ) ) {
										list.push( arg );
									}
								} else if ( arg && arg.length && type !== "string" ) {
									// Inspect recursively
									add( arg );
								}
							});
						})( arguments );
						// Do we need to add the callbacks to the
						// current firing batch?
						if ( firing ) {
							firingLength = list.length;
							// With memory, if we're not firing then
							// we should call right away
						} else if ( memory ) {
							firingStart = start;
							fire( memory );
						}
					}
					return this;
				},
				// Remove a callback from the list
				remove: function() {
					if ( list ) {
						jQuery.each( arguments, function( _, arg ) {
							var index;
							while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
								list.splice( index, 1 );
								// Handle firing indexes
								if ( firing ) {
									if ( index <= firingLength ) {
										firingLength--;
									}
									if ( index <= firingIndex ) {
										firingIndex--;
									}
								}
							}
						});
					}
					return this;
				},
				// Check if a given callback is in the list.
				// If no argument is given, return whether or not list has callbacks attached.
				has: function( fn ) {
					return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
				},
				// Remove all callbacks from the list
				empty: function() {
					list = [];
					firingLength = 0;
					return this;
				},
				// Have the list do nothing anymore
				disable: function() {
					list = stack = memory = undefined;
					return this;
				},
				// Is it disabled?
				disabled: function() {
					return !list;
				},
				// Lock the list in its current state
				lock: function() {
					stack = undefined;
					if ( !memory ) {
						self.disable();
					}
					return this;
				},
				// Is it locked?
				locked: function() {
					return !stack;
				},
				// Call all callbacks with the given context and arguments
				fireWith: function( context, args ) {
					if ( list && ( !fired || stack ) ) {
						args = args || [];
						args = [ context, args.slice ? args.slice() : args ];
						if ( firing ) {
							stack.push( args );
						} else {
							fire( args );
						}
					}
					return this;
				},
				// Call all the callbacks with the given arguments
				fire: function() {
					self.fireWith( this, arguments );
					return this;
				},
				// To know if the callbacks have already been called at least once
				fired: function() {
					return !!fired;
				}
			};

		return self;
	};


	jQuery.extend({

		Deferred: function( func ) {
			var tuples = [
					// action, add listener, listener list, final state
					[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
					[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
					[ "notify", "progress", jQuery.Callbacks("memory") ]
				],
				state = "pending",
				promise = {
					state: function() {
						return state;
					},
					always: function() {
						deferred.done( arguments ).fail( arguments );
						return this;
					},
					then: function( /* fnDone, fnFail, fnProgress */ ) {
						var fns = arguments;
						return jQuery.Deferred(function( newDefer ) {
							jQuery.each( tuples, function( i, tuple ) {
								var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
								// deferred[ done | fail | progress ] for forwarding actions to newDefer
								deferred[ tuple[1] ](function() {
									var returned = fn && fn.apply( this, arguments );
									if ( returned && jQuery.isFunction( returned.promise ) ) {
										returned.promise()
											.done( newDefer.resolve )
											.fail( newDefer.reject )
											.progress( newDefer.notify );
									} else {
										newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
									}
								});
							});
							fns = null;
						}).promise();
					},
					// Get a promise for this deferred
					// If obj is provided, the promise aspect is added to the object
					promise: function( obj ) {
						return obj != null ? jQuery.extend( obj, promise ) : promise;
					}
				},
				deferred = {};

			// Keep pipe for back-compat
			promise.pipe = promise.then;

			// Add list-specific methods
			jQuery.each( tuples, function( i, tuple ) {
				var list = tuple[ 2 ],
					stateString = tuple[ 3 ];

				// promise[ done | fail | progress ] = list.add
				promise[ tuple[1] ] = list.add;

				// Handle state
				if ( stateString ) {
					list.add(function() {
						// state = [ resolved | rejected ]
						state = stateString;

						// [ reject_list | resolve_list ].disable; progress_list.lock
					}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
				}

				// deferred[ resolve | reject | notify ]
				deferred[ tuple[0] ] = function() {
					deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
					return this;
				};
				deferred[ tuple[0] + "With" ] = list.fireWith;
			});

			// Make the deferred a promise
			promise.promise( deferred );

			// Call given func if any
			if ( func ) {
				func.call( deferred, deferred );
			}

			// All done!
			return deferred;
		},

		// Deferred helper
		when: function( subordinate /* , ..., subordinateN */ ) {
			var i = 0,
				resolveValues = slice.call( arguments ),
				length = resolveValues.length,

			// the count of uncompleted subordinates
				remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,

			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
				deferred = remaining === 1 ? subordinate : jQuery.Deferred(),

			// Update function for both resolve and progress values
				updateFunc = function( i, contexts, values ) {
					return function( value ) {
						contexts[ i ] = this;
						values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
						if ( values === progressValues ) {
							deferred.notifyWith( contexts, values );

						} else if ( !(--remaining) ) {
							deferred.resolveWith( contexts, values );
						}
					};
				},

				progressValues, progressContexts, resolveContexts;

			// add listeners to Deferred subordinates; treat others as resolved
			if ( length > 1 ) {
				progressValues = new Array( length );
				progressContexts = new Array( length );
				resolveContexts = new Array( length );
				for ( ; i < length; i++ ) {
					if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
						resolveValues[ i ].promise()
							.done( updateFunc( i, resolveContexts, resolveValues ) )
							.fail( deferred.reject )
							.progress( updateFunc( i, progressContexts, progressValues ) );
					} else {
						--remaining;
					}
				}
			}

			// if we're not waiting on anything, resolve the master
			if ( !remaining ) {
				deferred.resolveWith( resolveContexts, resolveValues );
			}

			return deferred.promise();
		}
	});


// The deferred used on DOM ready
	var readyList;

	jQuery.fn.ready = function( fn ) {
		// Add the callback
		jQuery.ready.promise().done( fn );

		return this;
	};

	jQuery.extend({
		// Is the DOM ready to be used? Set to true once it occurs.
		isReady: false,

		// A counter to track how many items to wait for before
		// the ready event fires. See #6781
		readyWait: 1,

		// Hold (or release) the ready event
		holdReady: function( hold ) {
			if ( hold ) {
				jQuery.readyWait++;
			} else {
				jQuery.ready( true );
			}
		},

		// Handle when the DOM is ready
		ready: function( wait ) {

			// Abort if there are pending holds or we're already ready
			if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
				return;
			}

			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
			if ( !document.body ) {
				return setTimeout( jQuery.ready );
			}

			// Remember that the DOM is ready
			jQuery.isReady = true;

			// If a normal DOM Ready event fired, decrement, and wait if need be
			if ( wait !== true && --jQuery.readyWait > 0 ) {
				return;
			}

			// If there are functions bound, to execute
			readyList.resolveWith( document, [ jQuery ] );

			// Trigger any bound ready events
			if ( jQuery.fn.triggerHandler ) {
				jQuery( document ).triggerHandler( "ready" );
				jQuery( document ).off( "ready" );
			}
		}
	});

	/**
	 * Clean-up method for dom ready events
	 */
	function detach() {
		if ( document.addEventListener ) {
			document.removeEventListener( "DOMContentLoaded", completed, false );
			window.removeEventListener( "load", completed, false );

		} else {
			document.detachEvent( "onreadystatechange", completed );
			window.detachEvent( "onload", completed );
		}
	}

	/**
	 * The ready event handler and self cleanup method
	 */
	function completed() {
		// readyState === "complete" is good enough for us to call the dom ready in oldIE
		if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
			detach();
			jQuery.ready();
		}
	}

	jQuery.ready.promise = function( obj ) {
		if ( !readyList ) {

			readyList = jQuery.Deferred();

			// Catch cases where $(document).ready() is called after the browser event has already occurred.
			// we once tried to use readyState "interactive" here, but it caused issues like the one
			// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
			if ( document.readyState === "complete" ) {
				// Handle it asynchronously to allow scripts the opportunity to delay ready
				setTimeout( jQuery.ready );

				// Standards-based browsers support DOMContentLoaded
			} else if ( document.addEventListener ) {
				// Use the handy event callback
				document.addEventListener( "DOMContentLoaded", completed, false );

				// A fallback to window.onload, that will always work
				window.addEventListener( "load", completed, false );

				// If IE event model is used
			} else {
				// Ensure firing before onload, maybe late but safe also for iframes
				document.attachEvent( "onreadystatechange", completed );

				// A fallback to window.onload, that will always work
				window.attachEvent( "onload", completed );

				// If IE and not a frame
				// continually check to see if the document is ready
				var top = false;

				try {
					top = window.frameElement == null && document.documentElement;
				} catch(e) {}

				if ( top && top.doScroll ) {
					(function doScrollCheck() {
						if ( !jQuery.isReady ) {

							try {
								// Use the trick by Diego Perini
								// http://javascript.nwbox.com/IEContentLoaded/
								top.doScroll("left");
							} catch(e) {
								return setTimeout( doScrollCheck, 50 );
							}

							// detach all dom ready events
							detach();

							// and execute any waiting functions
							jQuery.ready();
						}
					})();
				}
			}
		}
		return readyList.promise( obj );
	};


	var strundefined = typeof undefined;



// Support: IE<9
// Iteration over object's inherited properties before its own
	var i;
	for ( i in jQuery( support ) ) {
		break;
	}
	support.ownLast = i !== "0";

// Note: most support tests are defined in their respective modules.
// false until the test is run
	support.inlineBlockNeedsLayout = false;

// Execute ASAP in case we need to set body.style.zoom
	jQuery(function() {
		// Minified: var a,b,c,d
		var val, div, body, container;

		body = document.getElementsByTagName( "body" )[ 0 ];
		if ( !body || !body.style ) {
			// Return for frameset docs that don't have a body
			return;
		}

		// Setup
		div = document.createElement( "div" );
		container = document.createElement( "div" );
		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
		body.appendChild( container ).appendChild( div );

		if ( typeof div.style.zoom !== strundefined ) {
			// Support: IE<8
			// Check if natively block-level elements act like inline-block
			// elements when setting their display to 'inline' and giving
			// them layout
			div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";

			support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
			if ( val ) {
				// Prevent IE 6 from affecting layout for positioned elements #11048
				// Prevent IE from shrinking the body in IE 7 mode #12869
				// Support: IE<8
				body.style.zoom = 1;
			}
		}

		body.removeChild( container );
	});




	(function() {
		var div = document.createElement( "div" );

		// Execute the test only if not already executed in another module.
		if (support.deleteExpando == null) {
			// Support: IE<9
			support.deleteExpando = true;
			try {
				delete div.test;
			} catch( e ) {
				support.deleteExpando = false;
			}
		}

		// Null elements to avoid leaks in IE.
		div = null;
	})();


	/**
	 * Determines whether an object can have data
	 */
	jQuery.acceptData = function( elem ) {
		var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
			nodeType = +elem.nodeType || 1;

		// Do not set data on non-element DOM nodes because it will not be cleared (#8335).
		return nodeType !== 1 && nodeType !== 9 ?
			false :

			// Nodes accept data unless otherwise specified; rejection can be conditional
		!noData || noData !== true && elem.getAttribute("classid") === noData;
	};


	var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
		rmultiDash = /([A-Z])/g;

	function dataAttr( elem, key, data ) {
		// If nothing was found internally, try to fetch any
		// data from the HTML5 data-* attribute
		if ( data === undefined && elem.nodeType === 1 ) {

			var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();

			data = elem.getAttribute( name );

			if ( typeof data === "string" ) {
				try {
					data = data === "true" ? true :
						data === "false" ? false :
							data === "null" ? null :
								// Only convert to a number if it doesn't change the string
								+data + "" === data ? +data :
									rbrace.test( data ) ? jQuery.parseJSON( data ) :
										data;
				} catch( e ) {}

				// Make sure we set the data so it isn't changed later
				jQuery.data( elem, key, data );

			} else {
				data = undefined;
			}
		}

		return data;
	}

// checks a cache object for emptiness
	function isEmptyDataObject( obj ) {
		var name;
		for ( name in obj ) {

			// if the public data object is empty, the private is still empty
			if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
				continue;
			}
			if ( name !== "toJSON" ) {
				return false;
			}
		}

		return true;
	}

	function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var ret, thisCache,
			internalKey = jQuery.expando,

		// We have to handle DOM nodes and JS objects differently because IE6-7
		// can't GC object references properly across the DOM-JS boundary
			isNode = elem.nodeType,

		// Only DOM nodes need the global jQuery cache; JS object data is
		// attached directly to the object so GC can occur automatically
			cache = isNode ? jQuery.cache : elem,

		// Only defining an ID for JS objects if its cache already exists allows
		// the code to shortcut on the same path as a DOM node with no cache
			id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;

		// Avoid doing any more work than we need to when trying to get data on an
		// object that has no data at all
		if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
			return;
		}

		if ( !id ) {
			// Only DOM nodes need a new unique ID for each element since their data
			// ends up in the global cache
			if ( isNode ) {
				id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
			} else {
				id = internalKey;
			}
		}

		if ( !cache[ id ] ) {
			// Avoid exposing jQuery metadata on plain JS objects when the object
			// is serialized using JSON.stringify
			cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
		}

		// An object can be passed to jQuery.data instead of a key/value pair; this gets
		// shallow copied over onto the existing cache
		if ( typeof name === "object" || typeof name === "function" ) {
			if ( pvt ) {
				cache[ id ] = jQuery.extend( cache[ id ], name );
			} else {
				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
			}
		}

		thisCache = cache[ id ];

		// jQuery data() is stored in a separate object inside the object's internal data
		// cache in order to avoid key collisions between internal data and user-defined
		// data.
		if ( !pvt ) {
			if ( !thisCache.data ) {
				thisCache.data = {};
			}

			thisCache = thisCache.data;
		}

		if ( data !== undefined ) {
			thisCache[ jQuery.camelCase( name ) ] = data;
		}

		// Check for both converted-to-camel and non-converted data property names
		// If a data property was specified
		if ( typeof name === "string" ) {

			// First Try to find as-is property data
			ret = thisCache[ name ];

			// Test for null|undefined property data
			if ( ret == null ) {

				// Try to find the camelCased property
				ret = thisCache[ jQuery.camelCase( name ) ];
			}
		} else {
			ret = thisCache;
		}

		return ret;
	}

	function internalRemoveData( elem, name, pvt ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var thisCache, i,
			isNode = elem.nodeType,

		// See jQuery.data for more information
			cache = isNode ? jQuery.cache : elem,
			id = isNode ? elem[ jQuery.expando ] : jQuery.expando;

		// If there is already no cache entry for this object, there is no
		// purpose in continuing
		if ( !cache[ id ] ) {
			return;
		}

		if ( name ) {

			thisCache = pvt ? cache[ id ] : cache[ id ].data;

			if ( thisCache ) {

				// Support array or space separated string names for data keys
				if ( !jQuery.isArray( name ) ) {

					// try the string as a key before any manipulation
					if ( name in thisCache ) {
						name = [ name ];
					} else {

						// split the camel cased version by spaces unless a key with the spaces exists
						name = jQuery.camelCase( name );
						if ( name in thisCache ) {
							name = [ name ];
						} else {
							name = name.split(" ");
						}
					}
				} else {
					// If "name" is an array of keys...
					// When data is initially created, via ("key", "val") signature,
					// keys will be converted to camelCase.
					// Since there is no way to tell _how_ a key was added, remove
					// both plain key and camelCase key. #12786
					// This will only penalize the array argument path.
					name = name.concat( jQuery.map( name, jQuery.camelCase ) );
				}

				i = name.length;
				while ( i-- ) {
					delete thisCache[ name[i] ];
				}

				// If there is no data left in the cache, we want to continue
				// and let the cache object itself get destroyed
				if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
					return;
				}
			}
		}

		// See jQuery.data for more information
		if ( !pvt ) {
			delete cache[ id ].data;

			// Don't destroy the parent cache unless the internal data object
			// had been the only thing left in it
			if ( !isEmptyDataObject( cache[ id ] ) ) {
				return;
			}
		}

		// Destroy the cache
		if ( isNode ) {
			jQuery.cleanData( [ elem ], true );

			// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
			/* jshint eqeqeq: false */
		} else if ( support.deleteExpando || cache != cache.window ) {
			/* jshint eqeqeq: true */
			delete cache[ id ];

			// When all else fails, null
		} else {
			cache[ id ] = null;
		}
	}

	jQuery.extend({
		cache: {},

		// The following elements (space-suffixed to avoid Object.prototype collisions)
		// throw uncatchable exceptions if you attempt to set expando properties
		noData: {
			"applet ": true,
			"embed ": true,
			// ...but Flash objects (which have this classid) *can* handle expandos
			"object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
		},

		hasData: function( elem ) {
			elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
			return !!elem && !isEmptyDataObject( elem );
		},

		data: function( elem, name, data ) {
			return internalData( elem, name, data );
		},

		removeData: function( elem, name ) {
			return internalRemoveData( elem, name );
		},

		// For internal use only.
		_data: function( elem, name, data ) {
			return internalData( elem, name, data, true );
		},

		_removeData: function( elem, name ) {
			return internalRemoveData( elem, name, true );
		}
	});

	jQuery.fn.extend({
		data: function( key, value ) {
			var i, name, data,
				elem = this[0],
				attrs = elem && elem.attributes;

			// Special expections of .data basically thwart jQuery.access,
			// so implement the relevant behavior ourselves

			// Gets all values
			if ( key === undefined ) {
				if ( this.length ) {
					data = jQuery.data( elem );

					if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
						i = attrs.length;
						while ( i-- ) {

							// Support: IE11+
							// The attrs elements can be null (#14894)
							if ( attrs[ i ] ) {
								name = attrs[ i ].name;
								if ( name.indexOf( "data-" ) === 0 ) {
									name = jQuery.camelCase( name.slice(5) );
									dataAttr( elem, name, data[ name ] );
								}
							}
						}
						jQuery._data( elem, "parsedAttrs", true );
					}
				}

				return data;
			}

			// Sets multiple values
			if ( typeof key === "object" ) {
				return this.each(function() {
					jQuery.data( this, key );
				});
			}

			return arguments.length > 1 ?

				// Sets one value
				this.each(function() {
					jQuery.data( this, key, value );
				}) :

				// Gets one value
				// Try to fetch any internally stored data first
				elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
		},

		removeData: function( key ) {
			return this.each(function() {
				jQuery.removeData( this, key );
			});
		}
	});


	jQuery.extend({
		queue: function( elem, type, data ) {
			var queue;

			if ( elem ) {
				type = ( type || "fx" ) + "queue";
				queue = jQuery._data( elem, type );

				// Speed up dequeue by getting out quickly if this is just a lookup
				if ( data ) {
					if ( !queue || jQuery.isArray(data) ) {
						queue = jQuery._data( elem, type, jQuery.makeArray(data) );
					} else {
						queue.push( data );
					}
				}
				return queue || [];
			}
		},

		dequeue: function( elem, type ) {
			type = type || "fx";

			var queue = jQuery.queue( elem, type ),
				startLength = queue.length,
				fn = queue.shift(),
				hooks = jQuery._queueHooks( elem, type ),
				next = function() {
					jQuery.dequeue( elem, type );
				};

			// If the fx queue is dequeued, always remove the progress sentinel
			if ( fn === "inprogress" ) {
				fn = queue.shift();
				startLength--;
			}

			if ( fn ) {

				// Add a progress sentinel to prevent the fx queue from being
				// automatically dequeued
				if ( type === "fx" ) {
					queue.unshift( "inprogress" );
				}

				// clear up the last queue stop function
				delete hooks.stop;
				fn.call( elem, next, hooks );
			}

			if ( !startLength && hooks ) {
				hooks.empty.fire();
			}
		},

		// not intended for public consumption - generates a queueHooks object, or returns the current one
		_queueHooks: function( elem, type ) {
			var key = type + "queueHooks";
			return jQuery._data( elem, key ) || jQuery._data( elem, key, {
					empty: jQuery.Callbacks("once memory").add(function() {
						jQuery._removeData( elem, type + "queue" );
						jQuery._removeData( elem, key );
					})
				});
		}
	});

	jQuery.fn.extend({
		queue: function( type, data ) {
			var setter = 2;

			if ( typeof type !== "string" ) {
				data = type;
				type = "fx";
				setter--;
			}

			if ( arguments.length < setter ) {
				return jQuery.queue( this[0], type );
			}

			return data === undefined ?
				this :
				this.each(function() {
					var queue = jQuery.queue( this, type, data );

					// ensure a hooks for this queue
					jQuery._queueHooks( this, type );

					if ( type === "fx" && queue[0] !== "inprogress" ) {
						jQuery.dequeue( this, type );
					}
				});
		},
		dequeue: function( type ) {
			return this.each(function() {
				jQuery.dequeue( this, type );
			});
		},
		clearQueue: function( type ) {
			return this.queue( type || "fx", [] );
		},
		// Get a promise resolved when queues of a certain type
		// are emptied (fx is the type by default)
		promise: function( type, obj ) {
			var tmp,
				count = 1,
				defer = jQuery.Deferred(),
				elements = this,
				i = this.length,
				resolve = function() {
					if ( !( --count ) ) {
						defer.resolveWith( elements, [ elements ] );
					}
				};

			if ( typeof type !== "string" ) {
				obj = type;
				type = undefined;
			}
			type = type || "fx";

			while ( i-- ) {
				tmp = jQuery._data( elements[ i ], type + "queueHooks" );
				if ( tmp && tmp.empty ) {
					count++;
					tmp.empty.add( resolve );
				}
			}
			resolve();
			return defer.promise( obj );
		}
	});
	var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;

	var cssExpand = [ "Top", "Right", "Bottom", "Left" ];

	var isHidden = function( elem, el ) {
		// isHidden might be called from jQuery#filter function;
		// in that case, element will be second argument
		elem = el || elem;
		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
	};



// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
	var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
		var i = 0,
			length = elems.length,
			bulk = key == null;

		// Sets many values
		if ( jQuery.type( key ) === "object" ) {
			chainable = true;
			for ( i in key ) {
				jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
			}

			// Sets one value
		} else if ( value !== undefined ) {
			chainable = true;

			if ( !jQuery.isFunction( value ) ) {
				raw = true;
			}

			if ( bulk ) {
				// Bulk operations run against the entire set
				if ( raw ) {
					fn.call( elems, value );
					fn = null;

					// ...except when executing function values
				} else {
					bulk = fn;
					fn = function( elem, key, value ) {
						return bulk.call( jQuery( elem ), value );
					};
				}
			}

			if ( fn ) {
				for ( ; i < length; i++ ) {
					fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
				}
			}
		}

		return chainable ?
			elems :

			// Gets
			bulk ?
				fn.call( elems ) :
				length ? fn( elems[0], key ) : emptyGet;
	};
	var rcheckableType = (/^(?:checkbox|radio)$/i);



	(function() {
		// Minified: var a,b,c
		var input = document.createElement( "input" ),
			div = document.createElement( "div" ),
			fragment = document.createDocumentFragment();

		// Setup
		div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";

		// IE strips leading whitespace when .innerHTML is used
		support.leadingWhitespace = div.firstChild.nodeType === 3;

		// Make sure that tbody elements aren't automatically inserted
		// IE will insert them into empty tables
		support.tbody = !div.getElementsByTagName( "tbody" ).length;

		// Make sure that link elements get serialized correctly by innerHTML
		// This requires a wrapper element in IE
		support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;

		// Makes sure cloning an html5 element does not cause problems
		// Where outerHTML is undefined, this still works
		support.html5Clone =
			document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";

		// Check if a disconnected checkbox will retain its checked
		// value of true after appended to the DOM (IE6/7)
		input.type = "checkbox";
		input.checked = true;
		fragment.appendChild( input );
		support.appendChecked = input.checked;

		// Make sure textarea (and checkbox) defaultValue is properly cloned
		// Support: IE6-IE11+
		div.innerHTML = "<textarea>x</textarea>";
		support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;

		// #11217 - WebKit loses check when the name is after the checked attribute
		fragment.appendChild( div );
		div.innerHTML = "<input type='radio' checked='checked' name='t'/>";

		// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
		// old WebKit doesn't clone checked state correctly in fragments
		support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;

		// Support: IE<9
		// Opera does not clone events (and typeof div.attachEvent === undefined).
		// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
		support.noCloneEvent = true;
		if ( div.attachEvent ) {
			div.attachEvent( "onclick", function() {
				support.noCloneEvent = false;
			});

			div.cloneNode( true ).click();
		}

		// Execute the test only if not already executed in another module.
		if (support.deleteExpando == null) {
			// Support: IE<9
			support.deleteExpando = true;
			try {
				delete div.test;
			} catch( e ) {
				support.deleteExpando = false;
			}
		}
	})();


	(function() {
		var i, eventName,
			div = document.createElement( "div" );

		// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
		for ( i in { submit: true, change: true, focusin: true }) {
			eventName = "on" + i;

			if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
				// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
				div.setAttribute( eventName, "t" );
				support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
			}
		}

		// Null elements to avoid leaks in IE.
		div = null;
	})();


	var rformElems = /^(?:input|select|textarea)$/i,
		rkeyEvent = /^key/,
		rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
		rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
		rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;

	function returnTrue() {
		return true;
	}

	function returnFalse() {
		return false;
	}

	function safeActiveElement() {
		try {
			return document.activeElement;
		} catch ( err ) { }
	}

	/*
	 * Helper functions for managing events -- not part of the public interface.
	 * Props to Dean Edwards' addEvent library for many of the ideas.
	 */
	jQuery.event = {

		global: {},

		add: function( elem, types, handler, data, selector ) {
			var tmp, events, t, handleObjIn,
				special, eventHandle, handleObj,
				handlers, type, namespaces, origType,
				elemData = jQuery._data( elem );

			// Don't attach events to noData or text/comment nodes (but allow plain objects)
			if ( !elemData ) {
				return;
			}

			// Caller can pass in an object of custom data in lieu of the handler
			if ( handler.handler ) {
				handleObjIn = handler;
				handler = handleObjIn.handler;
				selector = handleObjIn.selector;
			}

			// Make sure that the handler has a unique ID, used to find/remove it later
			if ( !handler.guid ) {
				handler.guid = jQuery.guid++;
			}

			// Init the element's event structure and main handler, if this is the first
			if ( !(events = elemData.events) ) {
				events = elemData.events = {};
			}
			if ( !(eventHandle = elemData.handle) ) {
				eventHandle = elemData.handle = function( e ) {
					// Discard the second event of a jQuery.event.trigger() and
					// when an event is called after a page has unloaded
					return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
						jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
						undefined;
				};
				// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
				eventHandle.elem = elem;
			}

			// Handle multiple events separated by a space
			types = ( types || "" ).match( rnotwhite ) || [ "" ];
			t = types.length;
			while ( t-- ) {
				tmp = rtypenamespace.exec( types[t] ) || [];
				type = origType = tmp[1];
				namespaces = ( tmp[2] || "" ).split( "." ).sort();

				// There *must* be a type, no attaching namespace-only handlers
				if ( !type ) {
					continue;
				}

				// If event changes its type, use the special event handlers for the changed type
				special = jQuery.event.special[ type ] || {};

				// If selector defined, determine special event api type, otherwise given type
				type = ( selector ? special.delegateType : special.bindType ) || type;

				// Update special based on newly reset type
				special = jQuery.event.special[ type ] || {};

				// handleObj is passed to all event handlers
				handleObj = jQuery.extend({
					type: type,
					origType: origType,
					data: data,
					handler: handler,
					guid: handler.guid,
					selector: selector,
					needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
					namespace: namespaces.join(".")
				}, handleObjIn );

				// Init the event handler queue if we're the first
				if ( !(handlers = events[ type ]) ) {
					handlers = events[ type ] = [];
					handlers.delegateCount = 0;

					// Only use addEventListener/attachEvent if the special events handler returns false
					if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
						// Bind the global event handler to the element
						if ( elem.addEventListener ) {
							elem.addEventListener( type, eventHandle, false );

						} else if ( elem.attachEvent ) {
							elem.attachEvent( "on" + type, eventHandle );
						}
					}
				}

				if ( special.add ) {
					special.add.call( elem, handleObj );

					if ( !handleObj.handler.guid ) {
						handleObj.handler.guid = handler.guid;
					}
				}

				// Add to the element's handler list, delegates in front
				if ( selector ) {
					handlers.splice( handlers.delegateCount++, 0, handleObj );
				} else {
					handlers.push( handleObj );
				}

				// Keep track of which events have ever been used, for event optimization
				jQuery.event.global[ type ] = true;
			}

			// Nullify elem to prevent memory leaks in IE
			elem = null;
		},

		// Detach an event or set of events from an element
		remove: function( elem, types, handler, selector, mappedTypes ) {
			var j, handleObj, tmp,
				origCount, t, events,
				special, handlers, type,
				namespaces, origType,
				elemData = jQuery.hasData( elem ) && jQuery._data( elem );

			if ( !elemData || !(events = elemData.events) ) {
				return;
			}

			// Once for each type.namespace in types; type may be omitted
			types = ( types || "" ).match( rnotwhite ) || [ "" ];
			t = types.length;
			while ( t-- ) {
				tmp = rtypenamespace.exec( types[t] ) || [];
				type = origType = tmp[1];
				namespaces = ( tmp[2] || "" ).split( "." ).sort();

				// Unbind all events (on this namespace, if provided) for the element
				if ( !type ) {
					for ( type in events ) {
						jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
					}
					continue;
				}

				special = jQuery.event.special[ type ] || {};
				type = ( selector ? special.delegateType : special.bindType ) || type;
				handlers = events[ type ] || [];
				tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );

				// Remove matching events
				origCount = j = handlers.length;
				while ( j-- ) {
					handleObj = handlers[ j ];

					if ( ( mappedTypes || origType === handleObj.origType ) &&
						( !handler || handler.guid === handleObj.guid ) &&
						( !tmp || tmp.test( handleObj.namespace ) ) &&
						( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
						handlers.splice( j, 1 );

						if ( handleObj.selector ) {
							handlers.delegateCount--;
						}
						if ( special.remove ) {
							special.remove.call( elem, handleObj );
						}
					}
				}

				// Remove generic event handler if we removed something and no more handlers exist
				// (avoids potential for endless recursion during removal of special event handlers)
				if ( origCount && !handlers.length ) {
					if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
						jQuery.removeEvent( elem, type, elemData.handle );
					}

					delete events[ type ];
				}
			}

			// Remove the expando if it's no longer used
			if ( jQuery.isEmptyObject( events ) ) {
				delete elemData.handle;

				// removeData also checks for emptiness and clears the expando if empty
				// so use it instead of delete
				jQuery._removeData( elem, "events" );
			}
		},

		trigger: function( event, data, elem, onlyHandlers ) {
			var handle, ontype, cur,
				bubbleType, special, tmp, i,
				eventPath = [ elem || document ],
				type = hasOwn.call( event, "type" ) ? event.type : event,
				namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];

			cur = tmp = elem = elem || document;

			// Don't do events on text and comment nodes
			if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
				return;
			}

			// focus/blur morphs to focusin/out; ensure we're not firing them right now
			if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
				return;
			}

			if ( type.indexOf(".") >= 0 ) {
				// Namespaced trigger; create a regexp to match event type in handle()
				namespaces = type.split(".");
				type = namespaces.shift();
				namespaces.sort();
			}
			ontype = type.indexOf(":") < 0 && "on" + type;

			// Caller can pass in a jQuery.Event object, Object, or just an event type string
			event = event[ jQuery.expando ] ?
				event :
				new jQuery.Event( type, typeof event === "object" && event );

			// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
			event.isTrigger = onlyHandlers ? 2 : 3;
			event.namespace = namespaces.join(".");
			event.namespace_re = event.namespace ?
				new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
				null;

			// Clean up the event in case it is being reused
			event.result = undefined;
			if ( !event.target ) {
				event.target = elem;
			}

			// Clone any incoming data and prepend the event, creating the handler arg list
			data = data == null ?
				[ event ] :
				jQuery.makeArray( data, [ event ] );

			// Allow special events to draw outside the lines
			special = jQuery.event.special[ type ] || {};
			if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
				return;
			}

			// Determine event propagation path in advance, per W3C events spec (#9951)
			// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
			if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

				bubbleType = special.delegateType || type;
				if ( !rfocusMorph.test( bubbleType + type ) ) {
					cur = cur.parentNode;
				}
				for ( ; cur; cur = cur.parentNode ) {
					eventPath.push( cur );
					tmp = cur;
				}

				// Only add window if we got to document (e.g., not plain obj or detached DOM)
				if ( tmp === (elem.ownerDocument || document) ) {
					eventPath.push( tmp.defaultView || tmp.parentWindow || window );
				}
			}

			// Fire handlers on the event path
			i = 0;
			while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {

				event.type = i > 1 ?
					bubbleType :
				special.bindType || type;

				// jQuery handler
				handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
				if ( handle ) {
					handle.apply( cur, data );
				}

				// Native handler
				handle = ontype && cur[ ontype ];
				if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
					event.result = handle.apply( cur, data );
					if ( event.result === false ) {
						event.preventDefault();
					}
				}
			}
			event.type = type;

			// If nobody prevented the default action, do it now
			if ( !onlyHandlers && !event.isDefaultPrevented() ) {

				if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
					jQuery.acceptData( elem ) ) {

					// Call a native DOM method on the target with the same name name as the event.
					// Can't use an .isFunction() check here because IE6/7 fails that test.
					// Don't do default actions on window, that's where global variables be (#6170)
					if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {

						// Don't re-trigger an onFOO event when we call its FOO() method
						tmp = elem[ ontype ];

						if ( tmp ) {
							elem[ ontype ] = null;
						}

						// Prevent re-triggering of the same event, since we already bubbled it above
						jQuery.event.triggered = type;
						try {
							elem[ type ]();
						} catch ( e ) {
							// IE<9 dies on focus/blur to hidden element (#1486,#12518)
							// only reproducible on winXP IE8 native, not IE9 in IE8 mode
						}
						jQuery.event.triggered = undefined;

						if ( tmp ) {
							elem[ ontype ] = tmp;
						}
					}
				}
			}

			return event.result;
		},

		dispatch: function( event ) {

			// Make a writable jQuery.Event from the native event object
			event = jQuery.event.fix( event );

			var i, ret, handleObj, matched, j,
				handlerQueue = [],
				args = slice.call( arguments ),
				handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
				special = jQuery.event.special[ event.type ] || {};

			// Use the fix-ed jQuery.Event rather than the (read-only) native event
			args[0] = event;
			event.delegateTarget = this;

			// Call the preDispatch hook for the mapped type, and let it bail if desired
			if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
				return;
			}

			// Determine handlers
			handlerQueue = jQuery.event.handlers.call( this, event, handlers );

			// Run delegates first; they may want to stop propagation beneath us
			i = 0;
			while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
				event.currentTarget = matched.elem;

				j = 0;
				while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {

					// Triggered event must either 1) have no namespace, or
					// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
					if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {

						event.handleObj = handleObj;
						event.data = handleObj.data;

						ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
							.apply( matched.elem, args );

						if ( ret !== undefined ) {
							if ( (event.result = ret) === false ) {
								event.preventDefault();
								event.stopPropagation();
							}
						}
					}
				}
			}

			// Call the postDispatch hook for the mapped type
			if ( special.postDispatch ) {
				special.postDispatch.call( this, event );
			}

			return event.result;
		},

		handlers: function( event, handlers ) {
			var sel, handleObj, matches, i,
				handlerQueue = [],
				delegateCount = handlers.delegateCount,
				cur = event.target;

			// Find delegate handlers
			// Black-hole SVG <use> instance trees (#13180)
			// Avoid non-left-click bubbling in Firefox (#3861)
			if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {

				/* jshint eqeqeq: false */
				for ( ; cur != this; cur = cur.parentNode || this ) {
					/* jshint eqeqeq: true */

					// Don't check non-elements (#13208)
					// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
					if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
						matches = [];
						for ( i = 0; i < delegateCount; i++ ) {
							handleObj = handlers[ i ];

							// Don't conflict with Object.prototype properties (#13203)
							sel = handleObj.selector + " ";

							if ( matches[ sel ] === undefined ) {
								matches[ sel ] = handleObj.needsContext ?
								jQuery( sel, this ).index( cur ) >= 0 :
									jQuery.find( sel, this, null, [ cur ] ).length;
							}
							if ( matches[ sel ] ) {
								matches.push( handleObj );
							}
						}
						if ( matches.length ) {
							handlerQueue.push({ elem: cur, handlers: matches });
						}
					}
				}
			}

			// Add the remaining (directly-bound) handlers
			if ( delegateCount < handlers.length ) {
				handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
			}

			return handlerQueue;
		},

		fix: function( event ) {
			if ( event[ jQuery.expando ] ) {
				return event;
			}

			// Create a writable copy of the event object and normalize some properties
			var i, prop, copy,
				type = event.type,
				originalEvent = event,
				fixHook = this.fixHooks[ type ];

			if ( !fixHook ) {
				this.fixHooks[ type ] = fixHook =
					rmouseEvent.test( type ) ? this.mouseHooks :
						rkeyEvent.test( type ) ? this.keyHooks :
						{};
			}
			copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

			event = new jQuery.Event( originalEvent );

			i = copy.length;
			while ( i-- ) {
				prop = copy[ i ];
				event[ prop ] = originalEvent[ prop ];
			}

			// Support: IE<9
			// Fix target property (#1925)
			if ( !event.target ) {
				event.target = originalEvent.srcElement || document;
			}

			// Support: Chrome 23+, Safari?
			// Target should not be a text node (#504, #13143)
			if ( event.target.nodeType === 3 ) {
				event.target = event.target.parentNode;
			}

			// Support: IE<9
			// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
			event.metaKey = !!event.metaKey;

			return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
		},

		// Includes some event props shared by KeyEvent and MouseEvent
		props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),

		fixHooks: {},

		keyHooks: {
			props: "char charCode key keyCode".split(" "),
			filter: function( event, original ) {

				// Add which for key events
				if ( event.which == null ) {
					event.which = original.charCode != null ? original.charCode : original.keyCode;
				}

				return event;
			}
		},

		mouseHooks: {
			props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
			filter: function( event, original ) {
				var body, eventDoc, doc,
					button = original.button,
					fromElement = original.fromElement;

				// Calculate pageX/Y if missing and clientX/Y available
				if ( event.pageX == null && original.clientX != null ) {
					eventDoc = event.target.ownerDocument || document;
					doc = eventDoc.documentElement;
					body = eventDoc.body;

					event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
					event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
				}

				// Add relatedTarget, if necessary
				if ( !event.relatedTarget && fromElement ) {
					event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
				}

				// Add which for click: 1 === left; 2 === middle; 3 === right
				// Note: button is not normalized, so don't use it
				if ( !event.which && button !== undefined ) {
					event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
				}

				return event;
			}
		},

		special: {
			load: {
				// Prevent triggered image.load events from bubbling to window.load
				noBubble: true
			},
			focus: {
				// Fire native event if possible so blur/focus sequence is correct
				trigger: function() {
					if ( this !== safeActiveElement() && this.focus ) {
						try {
							this.focus();
							return false;
						} catch ( e ) {
							// Support: IE<9
							// If we error on focus to hidden element (#1486, #12518),
							// let .trigger() run the handlers
						}
					}
				},
				delegateType: "focusin"
			},
			blur: {
				trigger: function() {
					if ( this === safeActiveElement() && this.blur ) {
						this.blur();
						return false;
					}
				},
				delegateType: "focusout"
			},
			click: {
				// For checkbox, fire native event so checked state will be right
				trigger: function() {
					if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
						this.click();
						return false;
					}
				},

				// For cross-browser consistency, don't fire native .click() on links
				_default: function( event ) {
					return jQuery.nodeName( event.target, "a" );
				}
			},

			beforeunload: {
				postDispatch: function( event ) {

					// Support: Firefox 20+
					// Firefox doesn't alert if the returnValue field is not set.
					if ( event.result !== undefined && event.originalEvent ) {
						event.originalEvent.returnValue = event.result;
					}
				}
			}
		},

		simulate: function( type, elem, event, bubble ) {
			// Piggyback on a donor event to simulate a different one.
			// Fake originalEvent to avoid donor's stopPropagation, but if the
			// simulated event prevents default then we do the same on the donor.
			var e = jQuery.extend(
				new jQuery.Event(),
				event,
				{
					type: type,
					isSimulated: true,
					originalEvent: {}
				}
			);
			if ( bubble ) {
				jQuery.event.trigger( e, null, elem );
			} else {
				jQuery.event.dispatch.call( elem, e );
			}
			if ( e.isDefaultPrevented() ) {
				event.preventDefault();
			}
		}
	};

	jQuery.removeEvent = document.removeEventListener ?
		function( elem, type, handle ) {
			if ( elem.removeEventListener ) {
				elem.removeEventListener( type, handle, false );
			}
		} :
		function( elem, type, handle ) {
			var name = "on" + type;

			if ( elem.detachEvent ) {

				// #8545, #7054, preventing memory leaks for custom events in IE6-8
				// detachEvent needed property on element, by name of that event, to properly expose it to GC
				if ( typeof elem[ name ] === strundefined ) {
					elem[ name ] = null;
				}

				elem.detachEvent( name, handle );
			}
		};

	jQuery.Event = function( src, props ) {
		// Allow instantiation without the 'new' keyword
		if ( !(this instanceof jQuery.Event) ) {
			return new jQuery.Event( src, props );
		}

		// Event object
		if ( src && src.type ) {
			this.originalEvent = src;
			this.type = src.type;

			// Events bubbling up the document may have been marked as prevented
			// by a handler lower down the tree; reflect the correct value.
			this.isDefaultPrevented = src.defaultPrevented ||
			src.defaultPrevented === undefined &&
				// Support: IE < 9, Android < 4.0
			src.returnValue === false ?
				returnTrue :
				returnFalse;

			// Event type
		} else {
			this.type = src;
		}

		// Put explicitly provided properties onto the event object
		if ( props ) {
			jQuery.extend( this, props );
		}

		// Create a timestamp if incoming event doesn't have one
		this.timeStamp = src && src.timeStamp || jQuery.now();

		// Mark it as fixed
		this[ jQuery.expando ] = true;
	};

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
	jQuery.Event.prototype = {
		isDefaultPrevented: returnFalse,
		isPropagationStopped: returnFalse,
		isImmediatePropagationStopped: returnFalse,

		preventDefault: function() {
			var e = this.originalEvent;

			this.isDefaultPrevented = returnTrue;
			if ( !e ) {
				return;
			}

			// If preventDefault exists, run it on the original event
			if ( e.preventDefault ) {
				e.preventDefault();

				// Support: IE
				// Otherwise set the returnValue property of the original event to false
			} else {
				e.returnValue = false;
			}
		},
		stopPropagation: function() {
			var e = this.originalEvent;

			this.isPropagationStopped = returnTrue;
			if ( !e ) {
				return;
			}
			// If stopPropagation exists, run it on the original event
			if ( e.stopPropagation ) {
				e.stopPropagation();
			}

			// Support: IE
			// Set the cancelBubble property of the original event to true
			e.cancelBubble = true;
		},
		stopImmediatePropagation: function() {
			var e = this.originalEvent;

			this.isImmediatePropagationStopped = returnTrue;

			if ( e && e.stopImmediatePropagation ) {
				e.stopImmediatePropagation();
			}

			this.stopPropagation();
		}
	};

// Create mouseenter/leave events using mouseover/out and event-time checks
	jQuery.each({
		mouseenter: "mouseover",
		mouseleave: "mouseout",
		pointerenter: "pointerover",
		pointerleave: "pointerout"
	}, function( orig, fix ) {
		jQuery.event.special[ orig ] = {
			delegateType: fix,
			bindType: fix,

			handle: function( event ) {
				var ret,
					target = this,
					related = event.relatedTarget,
					handleObj = event.handleObj;

				// For mousenter/leave call the handler if related is outside the target.
				// NB: No relatedTarget if the mouse left/entered the browser window
				if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
					event.type = handleObj.origType;
					ret = handleObj.handler.apply( this, arguments );
					event.type = fix;
				}
				return ret;
			}
		};
	});

// IE submit delegation
	if ( !support.submitBubbles ) {

		jQuery.event.special.submit = {
			setup: function() {
				// Only need this for delegated form submit events
				if ( jQuery.nodeName( this, "form" ) ) {
					return false;
				}

				// Lazy-add a submit handler when a descendant form may potentially be submitted
				jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
					// Node name check avoids a VML-related crash in IE (#9807)
					var elem = e.target,
						form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
					if ( form && !jQuery._data( form, "submitBubbles" ) ) {
						jQuery.event.add( form, "submit._submit", function( event ) {
							event._submit_bubble = true;
						});
						jQuery._data( form, "submitBubbles", true );
					}
				});
				// return undefined since we don't need an event listener
			},

			postDispatch: function( event ) {
				// If form was submitted by the user, bubble the event up the tree
				if ( event._submit_bubble ) {
					delete event._submit_bubble;
					if ( this.parentNode && !event.isTrigger ) {
						jQuery.event.simulate( "submit", this.parentNode, event, true );
					}
				}
			},

			teardown: function() {
				// Only need this for delegated form submit events
				if ( jQuery.nodeName( this, "form" ) ) {
					return false;
				}

				// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
				jQuery.event.remove( this, "._submit" );
			}
		};
	}

// IE change delegation and checkbox/radio fix
	if ( !support.changeBubbles ) {

		jQuery.event.special.change = {

			setup: function() {

				if ( rformElems.test( this.nodeName ) ) {
					// IE doesn't fire change on a check/radio until blur; trigger it on click
					// after a propertychange. Eat the blur-change in special.change.handle.
					// This still fires onchange a second time for check/radio after blur.
					if ( this.type === "checkbox" || this.type === "radio" ) {
						jQuery.event.add( this, "propertychange._change", function( event ) {
							if ( event.originalEvent.propertyName === "checked" ) {
								this._just_changed = true;
							}
						});
						jQuery.event.add( this, "click._change", function( event ) {
							if ( this._just_changed && !event.isTrigger ) {
								this._just_changed = false;
							}
							// Allow triggered, simulated change events (#11500)
							jQuery.event.simulate( "change", this, event, true );
						});
					}
					return false;
				}
				// Delegated event; lazy-add a change handler on descendant inputs
				jQuery.event.add( this, "beforeactivate._change", function( e ) {
					var elem = e.target;

					if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
						jQuery.event.add( elem, "change._change", function( event ) {
							if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
								jQuery.event.simulate( "change", this.parentNode, event, true );
							}
						});
						jQuery._data( elem, "changeBubbles", true );
					}
				});
			},

			handle: function( event ) {
				var elem = event.target;

				// Swallow native change events from checkbox/radio, we already triggered them above
				if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
					return event.handleObj.handler.apply( this, arguments );
				}
			},

			teardown: function() {
				jQuery.event.remove( this, "._change" );

				return !rformElems.test( this.nodeName );
			}
		};
	}

// Create "bubbling" focus and blur events
	if ( !support.focusinBubbles ) {
		jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {

			// Attach a single capturing handler on the document while someone wants focusin/focusout
			var handler = function( event ) {
				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
			};

			jQuery.event.special[ fix ] = {
				setup: function() {
					var doc = this.ownerDocument || this,
						attaches = jQuery._data( doc, fix );

					if ( !attaches ) {
						doc.addEventListener( orig, handler, true );
					}
					jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
				},
				teardown: function() {
					var doc = this.ownerDocument || this,
						attaches = jQuery._data( doc, fix ) - 1;

					if ( !attaches ) {
						doc.removeEventListener( orig, handler, true );
						jQuery._removeData( doc, fix );
					} else {
						jQuery._data( doc, fix, attaches );
					}
				}
			};
		});
	}

	jQuery.fn.extend({

		on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
			var type, origFn;

			// Types can be a map of types/handlers
			if ( typeof types === "object" ) {
				// ( types-Object, selector, data )
				if ( typeof selector !== "string" ) {
					// ( types-Object, data )
					data = data || selector;
					selector = undefined;
				}
				for ( type in types ) {
					this.on( type, selector, data, types[ type ], one );
				}
				return this;
			}

			if ( data == null && fn == null ) {
				// ( types, fn )
				fn = selector;
				data = selector = undefined;
			} else if ( fn == null ) {
				if ( typeof selector === "string" ) {
					// ( types, selector, fn )
					fn = data;
					data = undefined;
				} else {
					// ( types, data, fn )
					fn = data;
					data = selector;
					selector = undefined;
				}
			}
			if ( fn === false ) {
				fn = returnFalse;
			} else if ( !fn ) {
				return this;
			}

			if ( one === 1 ) {
				origFn = fn;
				fn = function( event ) {
					// Can use an empty set, since event contains the info
					jQuery().off( event );
					return origFn.apply( this, arguments );
				};
				// Use same guid so caller can remove using origFn
				fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
			}
			return this.each( function() {
				jQuery.event.add( this, types, fn, data, selector );
			});
		},
		one: function( types, selector, data, fn ) {
			return this.on( types, selector, data, fn, 1 );
		},
		off: function( types, selector, fn ) {
			var handleObj, type;
			if ( types && types.preventDefault && types.handleObj ) {
				// ( event )  dispatched jQuery.Event
				handleObj = types.handleObj;
				jQuery( types.delegateTarget ).off(
					handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
					handleObj.selector,
					handleObj.handler
				);
				return this;
			}
			if ( typeof types === "object" ) {
				// ( types-object [, selector] )
				for ( type in types ) {
					this.off( type, selector, types[ type ] );
				}
				return this;
			}
			if ( selector === false || typeof selector === "function" ) {
				// ( types [, fn] )
				fn = selector;
				selector = undefined;
			}
			if ( fn === false ) {
				fn = returnFalse;
			}
			return this.each(function() {
				jQuery.event.remove( this, types, fn, selector );
			});
		},

		trigger: function( type, data ) {
			return this.each(function() {
				jQuery.event.trigger( type, data, this );
			});
		},
		triggerHandler: function( type, data ) {
			var elem = this[0];
			if ( elem ) {
				return jQuery.event.trigger( type, data, elem, true );
			}
		}
	});


	function createSafeFragment( document ) {
		var list = nodeNames.split( "|" ),
			safeFrag = document.createDocumentFragment();

		if ( safeFrag.createElement ) {
			while ( list.length ) {
				safeFrag.createElement(
					list.pop()
				);
			}
		}
		return safeFrag;
	}

	var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
			"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
		rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
		rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
		rleadingWhitespace = /^\s+/,
		rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
		rtagName = /<([\w:]+)/,
		rtbody = /<tbody/i,
		rhtml = /<|&#?\w+;/,
		rnoInnerhtml = /<(?:script|style|link)/i,
	// checked="checked" or checked
		rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
		rscriptType = /^$|\/(?:java|ecma)script/i,
		rscriptTypeMasked = /^true\/(.*)/,
		rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,

	// We have to close these tags to support XHTML (#13200)
		wrapMap = {
			option: [ 1, "<select multiple='multiple'>", "</select>" ],
			legend: [ 1, "<fieldset>", "</fieldset>" ],
			area: [ 1, "<map>", "</map>" ],
			param: [ 1, "<object>", "</object>" ],
			thead: [ 1, "<table>", "</table>" ],
			tr: [ 2, "<table><tbody>", "</tbody></table>" ],
			col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
			td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],

			// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
			// unless wrapped in a div with non-breaking characters in front of it.
			_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
		},
		safeFragment = createSafeFragment( document ),
		fragmentDiv = safeFragment.appendChild( document.createElement("div") );

	wrapMap.optgroup = wrapMap.option;
	wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
	wrapMap.th = wrapMap.td;

	function getAll( context, tag ) {
		var elems, elem,
			i = 0,
			found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
				typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
					undefined;

		if ( !found ) {
			for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
				if ( !tag || jQuery.nodeName( elem, tag ) ) {
					found.push( elem );
				} else {
					jQuery.merge( found, getAll( elem, tag ) );
				}
			}
		}

		return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
			jQuery.merge( [ context ], found ) :
			found;
	}

// Used in buildFragment, fixes the defaultChecked property
	function fixDefaultChecked( elem ) {
		if ( rcheckableType.test( elem.type ) ) {
			elem.defaultChecked = elem.checked;
		}
	}

// Support: IE<8
// Manipulating tables requires a tbody
	function manipulationTarget( elem, content ) {
		return jQuery.nodeName( elem, "table" ) &&
		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?

		elem.getElementsByTagName("tbody")[0] ||
		elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
			elem;
	}

// Replace/restore the type attribute of script elements for safe DOM manipulation
	function disableScript( elem ) {
		elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
		return elem;
	}
	function restoreScript( elem ) {
		var match = rscriptTypeMasked.exec( elem.type );
		if ( match ) {
			elem.type = match[1];
		} else {
			elem.removeAttribute("type");
		}
		return elem;
	}

// Mark scripts as having already been evaluated
	function setGlobalEval( elems, refElements ) {
		var elem,
			i = 0;
		for ( ; (elem = elems[i]) != null; i++ ) {
			jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
		}
	}

	function cloneCopyEvent( src, dest ) {

		if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
			return;
		}

		var type, i, l,
			oldData = jQuery._data( src ),
			curData = jQuery._data( dest, oldData ),
			events = oldData.events;

		if ( events ) {
			delete curData.handle;
			curData.events = {};

			for ( type in events ) {
				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
					jQuery.event.add( dest, type, events[ type ][ i ] );
				}
			}
		}

		// make the cloned public data object a copy from the original
		if ( curData.data ) {
			curData.data = jQuery.extend( {}, curData.data );
		}
	}

	function fixCloneNodeIssues( src, dest ) {
		var nodeName, e, data;

		// We do not need to do anything for non-Elements
		if ( dest.nodeType !== 1 ) {
			return;
		}

		nodeName = dest.nodeName.toLowerCase();

		// IE6-8 copies events bound via attachEvent when using cloneNode.
		if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
			data = jQuery._data( dest );

			for ( e in data.events ) {
				jQuery.removeEvent( dest, e, data.handle );
			}

			// Event data gets referenced instead of copied if the expando gets copied too
			dest.removeAttribute( jQuery.expando );
		}

		// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
		if ( nodeName === "script" && dest.text !== src.text ) {
			disableScript( dest ).text = src.text;
			restoreScript( dest );

			// IE6-10 improperly clones children of object elements using classid.
			// IE10 throws NoModificationAllowedError if parent is null, #12132.
		} else if ( nodeName === "object" ) {
			if ( dest.parentNode ) {
				dest.outerHTML = src.outerHTML;
			}

			// This path appears unavoidable for IE9. When cloning an object
			// element in IE9, the outerHTML strategy above is not sufficient.
			// If the src has innerHTML and the destination does not,
			// copy the src.innerHTML into the dest.innerHTML. #10324
			if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
				dest.innerHTML = src.innerHTML;
			}

		} else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
			// IE6-8 fails to persist the checked state of a cloned checkbox
			// or radio button. Worse, IE6-7 fail to give the cloned element
			// a checked appearance if the defaultChecked value isn't also set

			dest.defaultChecked = dest.checked = src.checked;

			// IE6-7 get confused and end up setting the value of a cloned
			// checkbox/radio button to an empty string instead of "on"
			if ( dest.value !== src.value ) {
				dest.value = src.value;
			}

			// IE6-8 fails to return the selected option to the default selected
			// state when cloning options
		} else if ( nodeName === "option" ) {
			dest.defaultSelected = dest.selected = src.defaultSelected;

			// IE6-8 fails to set the defaultValue to the correct value when
			// cloning other types of input fields
		} else if ( nodeName === "input" || nodeName === "textarea" ) {
			dest.defaultValue = src.defaultValue;
		}
	}

	jQuery.extend({
		clone: function( elem, dataAndEvents, deepDataAndEvents ) {
			var destElements, node, clone, i, srcElements,
				inPage = jQuery.contains( elem.ownerDocument, elem );

			if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
				clone = elem.cloneNode( true );

				// IE<=8 does not properly clone detached, unknown element nodes
			} else {
				fragmentDiv.innerHTML = elem.outerHTML;
				fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
			}

			if ( (!support.noCloneEvent || !support.noCloneChecked) &&
				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {

				// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
				destElements = getAll( clone );
				srcElements = getAll( elem );

				// Fix all IE cloning issues
				for ( i = 0; (node = srcElements[i]) != null; ++i ) {
					// Ensure that the destination node is not null; Fixes #9587
					if ( destElements[i] ) {
						fixCloneNodeIssues( node, destElements[i] );
					}
				}
			}

			// Copy the events from the original to the clone
			if ( dataAndEvents ) {
				if ( deepDataAndEvents ) {
					srcElements = srcElements || getAll( elem );
					destElements = destElements || getAll( clone );

					for ( i = 0; (node = srcElements[i]) != null; i++ ) {
						cloneCopyEvent( node, destElements[i] );
					}
				} else {
					cloneCopyEvent( elem, clone );
				}
			}

			// Preserve script evaluation history
			destElements = getAll( clone, "script" );
			if ( destElements.length > 0 ) {
				setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
			}

			destElements = srcElements = node = null;

			// Return the cloned set
			return clone;
		},

		buildFragment: function( elems, context, scripts, selection ) {
			var j, elem, contains,
				tmp, tag, tbody, wrap,
				l = elems.length,

			// Ensure a safe fragment
				safe = createSafeFragment( context ),

				nodes = [],
				i = 0;

			for ( ; i < l; i++ ) {
				elem = elems[ i ];

				if ( elem || elem === 0 ) {

					// Add nodes directly
					if ( jQuery.type( elem ) === "object" ) {
						jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );

						// Convert non-html into a text node
					} else if ( !rhtml.test( elem ) ) {
						nodes.push( context.createTextNode( elem ) );

						// Convert html into DOM nodes
					} else {
						tmp = tmp || safe.appendChild( context.createElement("div") );

						// Deserialize a standard representation
						tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
						wrap = wrapMap[ tag ] || wrapMap._default;

						tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];

						// Descend through wrappers to the right content
						j = wrap[0];
						while ( j-- ) {
							tmp = tmp.lastChild;
						}

						// Manually add leading whitespace removed by IE
						if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
							nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
						}

						// Remove IE's autoinserted <tbody> from table fragments
						if ( !support.tbody ) {

							// String was a <table>, *may* have spurious <tbody>
							elem = tag === "table" && !rtbody.test( elem ) ?
								tmp.firstChild :

								// String was a bare <thead> or <tfoot>
								wrap[1] === "<table>" && !rtbody.test( elem ) ?
									tmp :
									0;

							j = elem && elem.childNodes.length;
							while ( j-- ) {
								if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
									elem.removeChild( tbody );
								}
							}
						}

						jQuery.merge( nodes, tmp.childNodes );

						// Fix #12392 for WebKit and IE > 9
						tmp.textContent = "";

						// Fix #12392 for oldIE
						while ( tmp.firstChild ) {
							tmp.removeChild( tmp.firstChild );
						}

						// Remember the top-level container for proper cleanup
						tmp = safe.lastChild;
					}
				}
			}

			// Fix #11356: Clear elements from fragment
			if ( tmp ) {
				safe.removeChild( tmp );
			}

			// Reset defaultChecked for any radios and checkboxes
			// about to be appended to the DOM in IE 6/7 (#8060)
			if ( !support.appendChecked ) {
				jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
			}

			i = 0;
			while ( (elem = nodes[ i++ ]) ) {

				// #4087 - If origin and destination elements are the same, and this is
				// that element, do not do anything
				if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
					continue;
				}

				contains = jQuery.contains( elem.ownerDocument, elem );

				// Append to fragment
				tmp = getAll( safe.appendChild( elem ), "script" );

				// Preserve script evaluation history
				if ( contains ) {
					setGlobalEval( tmp );
				}

				// Capture executables
				if ( scripts ) {
					j = 0;
					while ( (elem = tmp[ j++ ]) ) {
						if ( rscriptType.test( elem.type || "" ) ) {
							scripts.push( elem );
						}
					}
				}
			}

			tmp = null;

			return safe;
		},

		cleanData: function( elems, /* internal */ acceptData ) {
			var elem, type, id, data,
				i = 0,
				internalKey = jQuery.expando,
				cache = jQuery.cache,
				deleteExpando = support.deleteExpando,
				special = jQuery.event.special;

			for ( ; (elem = elems[i]) != null; i++ ) {
				if ( acceptData || jQuery.acceptData( elem ) ) {

					id = elem[ internalKey ];
					data = id && cache[ id ];

					if ( data ) {
						if ( data.events ) {
							for ( type in data.events ) {
								if ( special[ type ] ) {
									jQuery.event.remove( elem, type );

									// This is a shortcut to avoid jQuery.event.remove's overhead
								} else {
									jQuery.removeEvent( elem, type, data.handle );
								}
							}
						}

						// Remove cache only if it was not already removed by jQuery.event.remove
						if ( cache[ id ] ) {

							delete cache[ id ];

							// IE does not allow us to delete expando properties from nodes,
							// nor does it have a removeAttribute function on Document nodes;
							// we must handle all of these cases
							if ( deleteExpando ) {
								delete elem[ internalKey ];

							} else if ( typeof elem.removeAttribute !== strundefined ) {
								elem.removeAttribute( internalKey );

							} else {
								elem[ internalKey ] = null;
							}

							deletedIds.push( id );
						}
					}
				}
			}
		}
	});

	jQuery.fn.extend({
		text: function( value ) {
			return access( this, function( value ) {
				return value === undefined ?
					jQuery.text( this ) :
					this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
			}, null, value, arguments.length );
		},

		append: function() {
			return this.domManip( arguments, function( elem ) {
				if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
					var target = manipulationTarget( this, elem );
					target.appendChild( elem );
				}
			});
		},

		prepend: function() {
			return this.domManip( arguments, function( elem ) {
				if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
					var target = manipulationTarget( this, elem );
					target.insertBefore( elem, target.firstChild );
				}
			});
		},

		before: function() {
			return this.domManip( arguments, function( elem ) {
				if ( this.parentNode ) {
					this.parentNode.insertBefore( elem, this );
				}
			});
		},

		after: function() {
			return this.domManip( arguments, function( elem ) {
				if ( this.parentNode ) {
					this.parentNode.insertBefore( elem, this.nextSibling );
				}
			});
		},

		remove: function( selector, keepData /* Internal Use Only */ ) {
			var elem,
				elems = selector ? jQuery.filter( selector, this ) : this,
				i = 0;

			for ( ; (elem = elems[i]) != null; i++ ) {

				if ( !keepData && elem.nodeType === 1 ) {
					jQuery.cleanData( getAll( elem ) );
				}

				if ( elem.parentNode ) {
					if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
						setGlobalEval( getAll( elem, "script" ) );
					}
					elem.parentNode.removeChild( elem );
				}
			}

			return this;
		},

		empty: function() {
			var elem,
				i = 0;

			for ( ; (elem = this[i]) != null; i++ ) {
				// Remove element nodes and prevent memory leaks
				if ( elem.nodeType === 1 ) {
					jQuery.cleanData( getAll( elem, false ) );
				}

				// Remove any remaining nodes
				while ( elem.firstChild ) {
					elem.removeChild( elem.firstChild );
				}

				// If this is a select, ensure that it displays empty (#12336)
				// Support: IE<9
				if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
					elem.options.length = 0;
				}
			}

			return this;
		},

		clone: function( dataAndEvents, deepDataAndEvents ) {
			dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
			deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

			return this.map(function() {
				return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
			});
		},

		html: function( value ) {
			return access( this, function( value ) {
				var elem = this[ 0 ] || {},
					i = 0,
					l = this.length;

				if ( value === undefined ) {
					return elem.nodeType === 1 ?
						elem.innerHTML.replace( rinlinejQuery, "" ) :
						undefined;
				}

				// See if we can take a shortcut and just use innerHTML
				if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
					( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
					( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
					!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {

					value = value.replace( rxhtmlTag, "<$1></$2>" );

					try {
						for (; i < l; i++ ) {
							// Remove element nodes and prevent memory leaks
							elem = this[i] || {};
							if ( elem.nodeType === 1 ) {
								jQuery.cleanData( getAll( elem, false ) );
								elem.innerHTML = value;
							}
						}

						elem = 0;

						// If using innerHTML throws an exception, use the fallback method
					} catch(e) {}
				}

				if ( elem ) {
					this.empty().append( value );
				}
			}, null, value, arguments.length );
		},

		replaceWith: function() {
			var arg = arguments[ 0 ];

			// Make the changes, replacing each context element with the new content
			this.domManip( arguments, function( elem ) {
				arg = this.parentNode;

				jQuery.cleanData( getAll( this ) );

				if ( arg ) {
					arg.replaceChild( elem, this );
				}
			});

			// Force removal if there was no new content (e.g., from empty arguments)
			return arg && (arg.length || arg.nodeType) ? this : this.remove();
		},

		detach: function( selector ) {
			return this.remove( selector, true );
		},

		domManip: function( args, callback ) {

			// Flatten any nested arrays
			args = concat.apply( [], args );

			var first, node, hasScripts,
				scripts, doc, fragment,
				i = 0,
				l = this.length,
				set = this,
				iNoClone = l - 1,
				value = args[0],
				isFunction = jQuery.isFunction( value );

			// We can't cloneNode fragments that contain checked, in WebKit
			if ( isFunction ||
				( l > 1 && typeof value === "string" &&
				!support.checkClone && rchecked.test( value ) ) ) {
				return this.each(function( index ) {
					var self = set.eq( index );
					if ( isFunction ) {
						args[0] = value.call( this, index, self.html() );
					}
					self.domManip( args, callback );
				});
			}

			if ( l ) {
				fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
				first = fragment.firstChild;

				if ( fragment.childNodes.length === 1 ) {
					fragment = first;
				}

				if ( first ) {
					scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
					hasScripts = scripts.length;

					// Use the original fragment for the last item instead of the first because it can end up
					// being emptied incorrectly in certain situations (#8070).
					for ( ; i < l; i++ ) {
						node = fragment;

						if ( i !== iNoClone ) {
							node = jQuery.clone( node, true, true );

							// Keep references to cloned scripts for later restoration
							if ( hasScripts ) {
								jQuery.merge( scripts, getAll( node, "script" ) );
							}
						}

						callback.call( this[i], node, i );
					}

					if ( hasScripts ) {
						doc = scripts[ scripts.length - 1 ].ownerDocument;

						// Reenable scripts
						jQuery.map( scripts, restoreScript );

						// Evaluate executable scripts on first document insertion
						for ( i = 0; i < hasScripts; i++ ) {
							node = scripts[ i ];
							if ( rscriptType.test( node.type || "" ) &&
								!jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {

								if ( node.src ) {
									// Optional AJAX dependency, but won't run scripts if not present
									if ( jQuery._evalUrl ) {
										jQuery._evalUrl( node.src );
									}
								} else {
									jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
								}
							}
						}
					}

					// Fix #11809: Avoid leaking memory
					fragment = first = null;
				}
			}

			return this;
		}
	});

	jQuery.each({
		appendTo: "append",
		prependTo: "prepend",
		insertBefore: "before",
		insertAfter: "after",
		replaceAll: "replaceWith"
	}, function( name, original ) {
		jQuery.fn[ name ] = function( selector ) {
			var elems,
				i = 0,
				ret = [],
				insert = jQuery( selector ),
				last = insert.length - 1;

			for ( ; i <= last; i++ ) {
				elems = i === last ? this : this.clone(true);
				jQuery( insert[i] )[ original ]( elems );

				// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
				push.apply( ret, elems.get() );
			}

			return this.pushStack( ret );
		};
	});


	var iframe,
		elemdisplay = {};

	/**
	 * Retrieve the actual display of a element
	 * @param {String} name nodeName of the element
	 * @param {Object} doc Document object
	 */
// Called only from within defaultDisplay
	function actualDisplay( name, doc ) {
		var style,
			elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),

		// getDefaultComputedStyle might be reliably used only on attached element
			display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?

				// Use of this method is a temporary fix (more like optmization) until something better comes along,
				// since it was removed from specification and supported only in FF
				style.display : jQuery.css( elem[ 0 ], "display" );

		// We don't have any data stored on the element,
		// so use "detach" method as fast way to get rid of the element
		elem.detach();

		return display;
	}

	/**
	 * Try to determine the default display value of an element
	 * @param {String} nodeName
	 */
	function defaultDisplay( nodeName ) {
		var doc = document,
			display = elemdisplay[ nodeName ];

		if ( !display ) {
			display = actualDisplay( nodeName, doc );

			// If the simple way fails, read from inside an iframe
			if ( display === "none" || !display ) {

				// Use the already-created iframe if possible
				iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );

				// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
				doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;

				// Support: IE
				doc.write();
				doc.close();

				display = actualDisplay( nodeName, doc );
				iframe.detach();
			}

			// Store the correct default display
			elemdisplay[ nodeName ] = display;
		}

		return display;
	}


	(function() {
		var shrinkWrapBlocksVal;

		support.shrinkWrapBlocks = function() {
			if ( shrinkWrapBlocksVal != null ) {
				return shrinkWrapBlocksVal;
			}

			// Will be changed later if needed.
			shrinkWrapBlocksVal = false;

			// Minified: var b,c,d
			var div, body, container;

			body = document.getElementsByTagName( "body" )[ 0 ];
			if ( !body || !body.style ) {
				// Test fired too early or in an unsupported environment, exit.
				return;
			}

			// Setup
			div = document.createElement( "div" );
			container = document.createElement( "div" );
			container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
			body.appendChild( container ).appendChild( div );

			// Support: IE6
			// Check if elements with layout shrink-wrap their children
			if ( typeof div.style.zoom !== strundefined ) {
				// Reset CSS: box-sizing; display; margin; border
				div.style.cssText =
					// Support: Firefox<29, Android 2.3
					// Vendor-prefix box-sizing
					"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
					"box-sizing:content-box;display:block;margin:0;border:0;" +
					"padding:1px;width:1px;zoom:1";
				div.appendChild( document.createElement( "div" ) ).style.width = "5px";
				shrinkWrapBlocksVal = div.offsetWidth !== 3;
			}

			body.removeChild( container );

			return shrinkWrapBlocksVal;
		};

	})();
	var rmargin = (/^margin/);

	var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );



	var getStyles, curCSS,
		rposition = /^(top|right|bottom|left)$/;

	if ( window.getComputedStyle ) {
		getStyles = function( elem ) {
			return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
		};

		curCSS = function( elem, name, computed ) {
			var width, minWidth, maxWidth, ret,
				style = elem.style;

			computed = computed || getStyles( elem );

			// getPropertyValue is only needed for .css('filter') in IE9, see #12537
			ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;

			if ( computed ) {

				if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
					ret = jQuery.style( elem, name );
				}

				// A tribute to the "awesome hack by Dean Edwards"
				// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
				// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
				// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
				if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {

					// Remember the original values
					width = style.width;
					minWidth = style.minWidth;
					maxWidth = style.maxWidth;

					// Put in the new values to get a computed value out
					style.minWidth = style.maxWidth = style.width = ret;
					ret = computed.width;

					// Revert the changed values
					style.width = width;
					style.minWidth = minWidth;
					style.maxWidth = maxWidth;
				}
			}

			// Support: IE
			// IE returns zIndex value as an integer.
			return ret === undefined ?
				ret :
			ret + "";
		};
	} else if ( document.documentElement.currentStyle ) {
		getStyles = function( elem ) {
			return elem.currentStyle;
		};

		curCSS = function( elem, name, computed ) {
			var left, rs, rsLeft, ret,
				style = elem.style;

			computed = computed || getStyles( elem );
			ret = computed ? computed[ name ] : undefined;

			// Avoid setting ret to empty string here
			// so we don't default to auto
			if ( ret == null && style && style[ name ] ) {
				ret = style[ name ];
			}

			// From the awesome hack by Dean Edwards
			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

			// If we're not dealing with a regular pixel number
			// but a number that has a weird ending, we need to convert it to pixels
			// but not position css attributes, as those are proportional to the parent element instead
			// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
			if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {

				// Remember the original values
				left = style.left;
				rs = elem.runtimeStyle;
				rsLeft = rs && rs.left;

				// Put in the new values to get a computed value out
				if ( rsLeft ) {
					rs.left = elem.currentStyle.left;
				}
				style.left = name === "fontSize" ? "1em" : ret;
				ret = style.pixelLeft + "px";

				// Revert the changed values
				style.left = left;
				if ( rsLeft ) {
					rs.left = rsLeft;
				}
			}

			// Support: IE
			// IE returns zIndex value as an integer.
			return ret === undefined ?
				ret :
			ret + "" || "auto";
		};
	}




	function addGetHookIf( conditionFn, hookFn ) {
		// Define the hook, we'll check on the first run if it's really needed.
		return {
			get: function() {
				var condition = conditionFn();

				if ( condition == null ) {
					// The test was not ready at this point; screw the hook this time
					// but check again when needed next time.
					return;
				}

				if ( condition ) {
					// Hook not needed (or it's not possible to use it due to missing dependency),
					// remove it.
					// Since there are no other hooks for marginRight, remove the whole object.
					delete this.get;
					return;
				}

				// Hook needed; redefine it so that the support test is not executed again.

				return (this.get = hookFn).apply( this, arguments );
			}
		};
	}


	(function() {
		// Minified: var b,c,d,e,f,g, h,i
		var div, style, a, pixelPositionVal, boxSizingReliableVal,
			reliableHiddenOffsetsVal, reliableMarginRightVal;

		// Setup
		div = document.createElement( "div" );
		div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
		a = div.getElementsByTagName( "a" )[ 0 ];
		style = a && a.style;

		// Finish early in limited (non-browser) environments
		if ( !style ) {
			return;
		}

		style.cssText = "float:left;opacity:.5";

		// Support: IE<9
		// Make sure that element opacity exists (as opposed to filter)
		support.opacity = style.opacity === "0.5";

		// Verify style float existence
		// (IE uses styleFloat instead of cssFloat)
		support.cssFloat = !!style.cssFloat;

		div.style.backgroundClip = "content-box";
		div.cloneNode( true ).style.backgroundClip = "";
		support.clearCloneStyle = div.style.backgroundClip === "content-box";

		// Support: Firefox<29, Android 2.3
		// Vendor-prefix box-sizing
		support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
		style.WebkitBoxSizing === "";

		jQuery.extend(support, {
			reliableHiddenOffsets: function() {
				if ( reliableHiddenOffsetsVal == null ) {
					computeStyleTests();
				}
				return reliableHiddenOffsetsVal;
			},

			boxSizingReliable: function() {
				if ( boxSizingReliableVal == null ) {
					computeStyleTests();
				}
				return boxSizingReliableVal;
			},

			pixelPosition: function() {
				if ( pixelPositionVal == null ) {
					computeStyleTests();
				}
				return pixelPositionVal;
			},

			// Support: Android 2.3
			reliableMarginRight: function() {
				if ( reliableMarginRightVal == null ) {
					computeStyleTests();
				}
				return reliableMarginRightVal;
			}
		});

		function computeStyleTests() {
			// Minified: var b,c,d,j
			var div, body, container, contents;

			body = document.getElementsByTagName( "body" )[ 0 ];
			if ( !body || !body.style ) {
				// Test fired too early or in an unsupported environment, exit.
				return;
			}

			// Setup
			div = document.createElement( "div" );
			container = document.createElement( "div" );
			container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
			body.appendChild( container ).appendChild( div );

			div.style.cssText =
				// Support: Firefox<29, Android 2.3
				// Vendor-prefix box-sizing
				"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
				"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
				"border:1px;padding:1px;width:4px;position:absolute";

			// Support: IE<9
			// Assume reasonable values in the absence of getComputedStyle
			pixelPositionVal = boxSizingReliableVal = false;
			reliableMarginRightVal = true;

			// Check for getComputedStyle so that this code is not run in IE<9.
			if ( window.getComputedStyle ) {
				pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
				boxSizingReliableVal =
					( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";

				// Support: Android 2.3
				// Div with explicit width and no margin-right incorrectly
				// gets computed margin-right based on width of container (#3333)
				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
				contents = div.appendChild( document.createElement( "div" ) );

				// Reset CSS: box-sizing; display; margin; border; padding
				contents.style.cssText = div.style.cssText =
					// Support: Firefox<29, Android 2.3
					// Vendor-prefix box-sizing
					"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
					"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
				contents.style.marginRight = contents.style.width = "0";
				div.style.width = "1px";

				reliableMarginRightVal =
					!parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
			}

			// Support: IE8
			// Check if table cells still have offsetWidth/Height when they are set
			// to display:none and there are still other visible table cells in a
			// table row; if so, offsetWidth/Height are not reliable for use when
			// determining if an element has been hidden directly using
			// display:none (it is still safe to use offsets if a parent element is
			// hidden; don safety goggles and see bug #4512 for more information).
			div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
			contents = div.getElementsByTagName( "td" );
			contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
			reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
			if ( reliableHiddenOffsetsVal ) {
				contents[ 0 ].style.display = "";
				contents[ 1 ].style.display = "none";
				reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
			}

			body.removeChild( container );
		}

	})();


// A method for quickly swapping in/out CSS properties to get correct calculations.
	jQuery.swap = function( elem, options, callback, args ) {
		var ret, name,
			old = {};

		// Remember the old values, and insert the new ones
		for ( name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		ret = callback.apply( elem, args || [] );

		// Revert the old values
		for ( name in options ) {
			elem.style[ name ] = old[ name ];
		}

		return ret;
	};


	var
		ralpha = /alpha\([^)]*\)/i,
		ropacity = /opacity\s*=\s*([^)]*)/,

	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
		rdisplayswap = /^(none|table(?!-c[ea]).+)/,
		rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
		rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),

		cssShow = { position: "absolute", visibility: "hidden", display: "block" },
		cssNormalTransform = {
			letterSpacing: "0",
			fontWeight: "400"
		},

		cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];


// return a css property mapped to a potentially vendor prefixed property
	function vendorPropName( style, name ) {

		// shortcut for names that are not vendor prefixed
		if ( name in style ) {
			return name;
		}

		// check for vendor prefixed names
		var capName = name.charAt(0).toUpperCase() + name.slice(1),
			origName = name,
			i = cssPrefixes.length;

		while ( i-- ) {
			name = cssPrefixes[ i ] + capName;
			if ( name in style ) {
				return name;
			}
		}

		return origName;
	}

	function showHide( elements, show ) {
		var display, elem, hidden,
			values = [],
			index = 0,
			length = elements.length;

		for ( ; index < length; index++ ) {
			elem = elements[ index ];
			if ( !elem.style ) {
				continue;
			}

			values[ index ] = jQuery._data( elem, "olddisplay" );
			display = elem.style.display;
			if ( show ) {
				// Reset the inline display of this element to learn if it is
				// being hidden by cascaded rules or not
				if ( !values[ index ] && display === "none" ) {
					elem.style.display = "";
				}

				// Set elements which have been overridden with display: none
				// in a stylesheet to whatever the default browser style is
				// for such an element
				if ( elem.style.display === "" && isHidden( elem ) ) {
					values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
				}
			} else {
				hidden = isHidden( elem );

				if ( display && display !== "none" || !hidden ) {
					jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
				}
			}
		}

		// Set the display of most of the elements in a second loop
		// to avoid the constant reflow
		for ( index = 0; index < length; index++ ) {
			elem = elements[ index ];
			if ( !elem.style ) {
				continue;
			}
			if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
				elem.style.display = show ? values[ index ] || "" : "none";
			}
		}

		return elements;
	}

	function setPositiveNumber( elem, value, subtract ) {
		var matches = rnumsplit.exec( value );
		return matches ?
			// Guard against undefined "subtract", e.g., when used as in cssHooks
		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
			value;
	}

	function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
		var i = extra === ( isBorderBox ? "border" : "content" ) ?
				// If we already have the right measurement, avoid augmentation
				4 :
				// Otherwise initialize for horizontal or vertical properties
				name === "width" ? 1 : 0,

			val = 0;

		for ( ; i < 4; i += 2 ) {
			// both box models exclude margin, so add it if we want it
			if ( extra === "margin" ) {
				val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
			}

			if ( isBorderBox ) {
				// border-box includes padding, so remove it if we want content
				if ( extra === "content" ) {
					val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
				}

				// at this point, extra isn't border nor margin, so remove border
				if ( extra !== "margin" ) {
					val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
				}
			} else {
				// at this point, extra isn't content, so add padding
				val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );

				// at this point, extra isn't content nor padding, so add border
				if ( extra !== "padding" ) {
					val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
				}
			}
		}

		return val;
	}

	function getWidthOrHeight( elem, name, extra ) {

		// Start with offset property, which is equivalent to the border-box value
		var valueIsBorderBox = true,
			val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
			styles = getStyles( elem ),
			isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";

		// some non-html elements return undefined for offsetWidth, so check for null/undefined
		// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
		// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
		if ( val <= 0 || val == null ) {
			// Fall back to computed then uncomputed css if necessary
			val = curCSS( elem, name, styles );
			if ( val < 0 || val == null ) {
				val = elem.style[ name ];
			}

			// Computed unit is not pixels. Stop here and return.
			if ( rnumnonpx.test(val) ) {
				return val;
			}

			// we need the check for style in case a browser which returns unreliable values
			// for getComputedStyle silently falls back to the reliable elem.style
			valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );

			// Normalize "", auto, and prepare for extra
			val = parseFloat( val ) || 0;
		}

		// use the active box-sizing model to add/subtract irrelevant styles
		return ( val +
			augmentWidthOrHeight(
				elem,
				name,
				extra || ( isBorderBox ? "border" : "content" ),
				valueIsBorderBox,
				styles
			)
			) + "px";
	}

	jQuery.extend({
		// Add in style property hooks for overriding the default
		// behavior of getting and setting a style property
		cssHooks: {
			opacity: {
				get: function( elem, computed ) {
					if ( computed ) {
						// We should always get a number back from opacity
						var ret = curCSS( elem, "opacity" );
						return ret === "" ? "1" : ret;
					}
				}
			}
		},

		// Don't automatically add "px" to these possibly-unitless properties
		cssNumber: {
			"columnCount": true,
			"fillOpacity": true,
			"flexGrow": true,
			"flexShrink": true,
			"fontWeight": true,
			"lineHeight": true,
			"opacity": true,
			"order": true,
			"orphans": true,
			"widows": true,
			"zIndex": true,
			"zoom": true
		},

		// Add in properties whose names you wish to fix before
		// setting or getting the value
		cssProps: {
			// normalize float css property
			"float": support.cssFloat ? "cssFloat" : "styleFloat"
		},

		// Get and set the style property on a DOM Node
		style: function( elem, name, value, extra ) {
			// Don't set styles on text and comment nodes
			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
				return;
			}

			// Make sure that we're working with the right name
			var ret, type, hooks,
				origName = jQuery.camelCase( name ),
				style = elem.style;

			name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );

			// gets hook for the prefixed version
			// followed by the unprefixed version
			hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

			// Check if we're setting a value
			if ( value !== undefined ) {
				type = typeof value;

				// convert relative number strings (+= or -=) to relative numbers. #7345
				if ( type === "string" && (ret = rrelNum.exec( value )) ) {
					value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
					// Fixes bug #9237
					type = "number";
				}

				// Make sure that null and NaN values aren't set. See: #7116
				if ( value == null || value !== value ) {
					return;
				}

				// If a number was passed in, add 'px' to the (except for certain CSS properties)
				if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
					value += "px";
				}

				// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
				// but it would mean to define eight (for every problematic property) identical functions
				if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
					style[ name ] = "inherit";
				}

				// If a hook was provided, use that value, otherwise just set the specified value
				if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {

					// Support: IE
					// Swallow errors from 'invalid' CSS values (#5509)
					try {
						style[ name ] = value;
					} catch(e) {}
				}

			} else {
				// If a hook was provided get the non-computed value from there
				if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
					return ret;
				}

				// Otherwise just get the value from the style object
				return style[ name ];
			}
		},

		css: function( elem, name, extra, styles ) {
			var num, val, hooks,
				origName = jQuery.camelCase( name );

			// Make sure that we're working with the right name
			name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );

			// gets hook for the prefixed version
			// followed by the unprefixed version
			hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];

			// If a hook was provided get the computed value from there
			if ( hooks && "get" in hooks ) {
				val = hooks.get( elem, true, extra );
			}

			// Otherwise, if a way to get the computed value exists, use that
			if ( val === undefined ) {
				val = curCSS( elem, name, styles );
			}

			//convert "normal" to computed value
			if ( val === "normal" && name in cssNormalTransform ) {
				val = cssNormalTransform[ name ];
			}

			// Return, converting to number if forced or a qualifier was provided and val looks numeric
			if ( extra === "" || extra ) {
				num = parseFloat( val );
				return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
			}
			return val;
		}
	});

	jQuery.each([ "height", "width" ], function( i, name ) {
		jQuery.cssHooks[ name ] = {
			get: function( elem, computed, extra ) {
				if ( computed ) {
					// certain elements can have dimension info if we invisibly show them
					// however, it must have a current display style that would benefit from this
					return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
						jQuery.swap( elem, cssShow, function() {
							return getWidthOrHeight( elem, name, extra );
						}) :
						getWidthOrHeight( elem, name, extra );
				}
			},

			set: function( elem, value, extra ) {
				var styles = extra && getStyles( elem );
				return setPositiveNumber( elem, value, extra ?
						augmentWidthOrHeight(
							elem,
							name,
							extra,
							support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
							styles
						) : 0
				);
			}
		};
	});

	if ( !support.opacity ) {
		jQuery.cssHooks.opacity = {
			get: function( elem, computed ) {
				// IE uses filters for opacity
				return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
					computed ? "1" : "";
			},

			set: function( elem, value ) {
				var style = elem.style,
					currentStyle = elem.currentStyle,
					opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
					filter = currentStyle && currentStyle.filter || style.filter || "";

				// IE has trouble with opacity if it does not have layout
				// Force it by setting the zoom level
				style.zoom = 1;

				// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
				// if value === "", then remove inline opacity #12685
				if ( ( value >= 1 || value === "" ) &&
					jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
					style.removeAttribute ) {

					// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
					// if "filter:" is present at all, clearType is disabled, we want to avoid this
					// style.removeAttribute is IE Only, but so apparently is this code path...
					style.removeAttribute( "filter" );

					// if there is no filter style applied in a css rule or unset inline opacity, we are done
					if ( value === "" || currentStyle && !currentStyle.filter ) {
						return;
					}
				}

				// otherwise, set new filter values
				style.filter = ralpha.test( filter ) ?
					filter.replace( ralpha, opacity ) :
				filter + " " + opacity;
			}
		};
	}

	jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
		function( elem, computed ) {
			if ( computed ) {
				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
				// Work around by temporarily setting element display to inline-block
				return jQuery.swap( elem, { "display": "inline-block" },
					curCSS, [ elem, "marginRight" ] );
			}
		}
	);

// These hooks are used by animate to expand properties
	jQuery.each({
		margin: "",
		padding: "",
		border: "Width"
	}, function( prefix, suffix ) {
		jQuery.cssHooks[ prefix + suffix ] = {
			expand: function( value ) {
				var i = 0,
					expanded = {},

				// assumes a single number if not a string
					parts = typeof value === "string" ? value.split(" ") : [ value ];

				for ( ; i < 4; i++ ) {
					expanded[ prefix + cssExpand[ i ] + suffix ] =
						parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
				}

				return expanded;
			}
		};

		if ( !rmargin.test( prefix ) ) {
			jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
		}
	});

	jQuery.fn.extend({
		css: function( name, value ) {
			return access( this, function( elem, name, value ) {
				var styles, len,
					map = {},
					i = 0;

				if ( jQuery.isArray( name ) ) {
					styles = getStyles( elem );
					len = name.length;

					for ( ; i < len; i++ ) {
						map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
					}

					return map;
				}

				return value !== undefined ?
					jQuery.style( elem, name, value ) :
					jQuery.css( elem, name );
			}, name, value, arguments.length > 1 );
		},
		show: function() {
			return showHide( this, true );
		},
		hide: function() {
			return showHide( this );
		},
		toggle: function( state ) {
			if ( typeof state === "boolean" ) {
				return state ? this.show() : this.hide();
			}

			return this.each(function() {
				if ( isHidden( this ) ) {
					jQuery( this ).show();
				} else {
					jQuery( this ).hide();
				}
			});
		}
	});


	function Tween( elem, options, prop, end, easing ) {
		return new Tween.prototype.init( elem, options, prop, end, easing );
	}
	jQuery.Tween = Tween;

	Tween.prototype = {
		constructor: Tween,
		init: function( elem, options, prop, end, easing, unit ) {
			this.elem = elem;
			this.prop = prop;
			this.easing = easing || "swing";
			this.options = options;
			this.start = this.now = this.cur();
			this.end = end;
			this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
		},
		cur: function() {
			var hooks = Tween.propHooks[ this.prop ];

			return hooks && hooks.get ?
				hooks.get( this ) :
				Tween.propHooks._default.get( this );
		},
		run: function( percent ) {
			var eased,
				hooks = Tween.propHooks[ this.prop ];

			if ( this.options.duration ) {
				this.pos = eased = jQuery.easing[ this.easing ](
					percent, this.options.duration * percent, 0, 1, this.options.duration
				);
			} else {
				this.pos = eased = percent;
			}
			this.now = ( this.end - this.start ) * eased + this.start;

			if ( this.options.step ) {
				this.options.step.call( this.elem, this.now, this );
			}

			if ( hooks && hooks.set ) {
				hooks.set( this );
			} else {
				Tween.propHooks._default.set( this );
			}
			return this;
		}
	};

	Tween.prototype.init.prototype = Tween.prototype;

	Tween.propHooks = {
		_default: {
			get: function( tween ) {
				var result;

				if ( tween.elem[ tween.prop ] != null &&
					(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
					return tween.elem[ tween.prop ];
				}

				// passing an empty string as a 3rd parameter to .css will automatically
				// attempt a parseFloat and fallback to a string if the parse fails
				// so, simple values such as "10px" are parsed to Float.
				// complex values such as "rotate(1rad)" are returned as is.
				result = jQuery.css( tween.elem, tween.prop, "" );
				// Empty strings, null, undefined and "auto" are converted to 0.
				return !result || result === "auto" ? 0 : result;
			},
			set: function( tween ) {
				// use step hook for back compat - use cssHook if its there - use .style if its
				// available and use plain properties where available
				if ( jQuery.fx.step[ tween.prop ] ) {
					jQuery.fx.step[ tween.prop ]( tween );
				} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
					jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
				} else {
					tween.elem[ tween.prop ] = tween.now;
				}
			}
		}
	};

// Support: IE <=9
// Panic based approach to setting things on disconnected nodes

	Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
		set: function( tween ) {
			if ( tween.elem.nodeType && tween.elem.parentNode ) {
				tween.elem[ tween.prop ] = tween.now;
			}
		}
	};

	jQuery.easing = {
		linear: function( p ) {
			return p;
		},
		swing: function( p ) {
			return 0.5 - Math.cos( p * Math.PI ) / 2;
		}
	};

	jQuery.fx = Tween.prototype.init;

// Back Compat <1.8 extension point
	jQuery.fx.step = {};




	var
		fxNow, timerId,
		rfxtypes = /^(?:toggle|show|hide)$/,
		rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
		rrun = /queueHooks$/,
		animationPrefilters = [ defaultPrefilter ],
		tweeners = {
			"*": [ function( prop, value ) {
				var tween = this.createTween( prop, value ),
					target = tween.cur(),
					parts = rfxnum.exec( value ),
					unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),

				// Starting value computation is required for potential unit mismatches
					start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
						rfxnum.exec( jQuery.css( tween.elem, prop ) ),
					scale = 1,
					maxIterations = 20;

				if ( start && start[ 3 ] !== unit ) {
					// Trust units reported by jQuery.css
					unit = unit || start[ 3 ];

					// Make sure we update the tween properties later on
					parts = parts || [];

					// Iteratively approximate from a nonzero starting point
					start = +target || 1;

					do {
						// If previous iteration zeroed out, double until we get *something*
						// Use a string for doubling factor so we don't accidentally see scale as unchanged below
						scale = scale || ".5";

						// Adjust and apply
						start = start / scale;
						jQuery.style( tween.elem, prop, start + unit );

						// Update scale, tolerating zero or NaN from tween.cur()
						// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
					} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
				}

				// Update tween properties
				if ( parts ) {
					start = tween.start = +start || +target || 0;
					tween.unit = unit;
					// If a +=/-= token was provided, we're doing a relative animation
					tween.end = parts[ 1 ] ?
					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
						+parts[ 2 ];
				}

				return tween;
			} ]
		};

// Animations created synchronously will run synchronously
	function createFxNow() {
		setTimeout(function() {
			fxNow = undefined;
		});
		return ( fxNow = jQuery.now() );
	}

// Generate parameters to create a standard animation
	function genFx( type, includeWidth ) {
		var which,
			attrs = { height: type },
			i = 0;

		// if we include width, step value is 1 to do all cssExpand values,
		// if we don't include width, step value is 2 to skip over Left and Right
		includeWidth = includeWidth ? 1 : 0;
		for ( ; i < 4 ; i += 2 - includeWidth ) {
			which = cssExpand[ i ];
			attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
		}

		if ( includeWidth ) {
			attrs.opacity = attrs.width = type;
		}

		return attrs;
	}

	function createTween( value, prop, animation ) {
		var tween,
			collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
			index = 0,
			length = collection.length;
		for ( ; index < length; index++ ) {
			if ( (tween = collection[ index ].call( animation, prop, value )) ) {

				// we're done with this property
				return tween;
			}
		}
	}

	function defaultPrefilter( elem, props, opts ) {
		/* jshint validthis: true */
		var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
			anim = this,
			orig = {},
			style = elem.style,
			hidden = elem.nodeType && isHidden( elem ),
			dataShow = jQuery._data( elem, "fxshow" );

		// handle queue: false promises
		if ( !opts.queue ) {
			hooks = jQuery._queueHooks( elem, "fx" );
			if ( hooks.unqueued == null ) {
				hooks.unqueued = 0;
				oldfire = hooks.empty.fire;
				hooks.empty.fire = function() {
					if ( !hooks.unqueued ) {
						oldfire();
					}
				};
			}
			hooks.unqueued++;

			anim.always(function() {
				// doing this makes sure that the complete handler will be called
				// before this completes
				anim.always(function() {
					hooks.unqueued--;
					if ( !jQuery.queue( elem, "fx" ).length ) {
						hooks.empty.fire();
					}
				});
			});
		}

		// height/width overflow pass
		if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
			// Make sure that nothing sneaks out
			// Record all 3 overflow attributes because IE does not
			// change the overflow attribute when overflowX and
			// overflowY are set to the same value
			opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];

			// Set display property to inline-block for height/width
			// animations on inline elements that are having width/height animated
			display = jQuery.css( elem, "display" );

			// Test default display if display is currently "none"
			checkDisplay = display === "none" ?
			jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;

			if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {

				// inline-level elements accept inline-block;
				// block-level elements need to be inline with layout
				if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
					style.display = "inline-block";
				} else {
					style.zoom = 1;
				}
			}
		}

		if ( opts.overflow ) {
			style.overflow = "hidden";
			if ( !support.shrinkWrapBlocks() ) {
				anim.always(function() {
					style.overflow = opts.overflow[ 0 ];
					style.overflowX = opts.overflow[ 1 ];
					style.overflowY = opts.overflow[ 2 ];
				});
			}
		}

		// show/hide pass
		for ( prop in props ) {
			value = props[ prop ];
			if ( rfxtypes.exec( value ) ) {
				delete props[ prop ];
				toggle = toggle || value === "toggle";
				if ( value === ( hidden ? "hide" : "show" ) ) {

					// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
					if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
						hidden = true;
					} else {
						continue;
					}
				}
				orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );

				// Any non-fx value stops us from restoring the original display value
			} else {
				display = undefined;
			}
		}

		if ( !jQuery.isEmptyObject( orig ) ) {
			if ( dataShow ) {
				if ( "hidden" in dataShow ) {
					hidden = dataShow.hidden;
				}
			} else {
				dataShow = jQuery._data( elem, "fxshow", {} );
			}

			// store state if its toggle - enables .stop().toggle() to "reverse"
			if ( toggle ) {
				dataShow.hidden = !hidden;
			}
			if ( hidden ) {
				jQuery( elem ).show();
			} else {
				anim.done(function() {
					jQuery( elem ).hide();
				});
			}
			anim.done(function() {
				var prop;
				jQuery._removeData( elem, "fxshow" );
				for ( prop in orig ) {
					jQuery.style( elem, prop, orig[ prop ] );
				}
			});
			for ( prop in orig ) {
				tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );

				if ( !( prop in dataShow ) ) {
					dataShow[ prop ] = tween.start;
					if ( hidden ) {
						tween.end = tween.start;
						tween.start = prop === "width" || prop === "height" ? 1 : 0;
					}
				}
			}

			// If this is a noop like .hide().hide(), restore an overwritten display value
		} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
			style.display = display;
		}
	}

	function propFilter( props, specialEasing ) {
		var index, name, easing, value, hooks;

		// camelCase, specialEasing and expand cssHook pass
		for ( index in props ) {
			name = jQuery.camelCase( index );
			easing = specialEasing[ name ];
			value = props[ index ];
			if ( jQuery.isArray( value ) ) {
				easing = value[ 1 ];
				value = props[ index ] = value[ 0 ];
			}

			if ( index !== name ) {
				props[ name ] = value;
				delete props[ index ];
			}

			hooks = jQuery.cssHooks[ name ];
			if ( hooks && "expand" in hooks ) {
				value = hooks.expand( value );
				delete props[ name ];

				// not quite $.extend, this wont overwrite keys already present.
				// also - reusing 'index' from above because we have the correct "name"
				for ( index in value ) {
					if ( !( index in props ) ) {
						props[ index ] = value[ index ];
						specialEasing[ index ] = easing;
					}
				}
			} else {
				specialEasing[ name ] = easing;
			}
		}
	}

	function Animation( elem, properties, options ) {
		var result,
			stopped,
			index = 0,
			length = animationPrefilters.length,
			deferred = jQuery.Deferred().always( function() {
				// don't match elem in the :animated selector
				delete tick.elem;
			}),
			tick = function() {
				if ( stopped ) {
					return false;
				}
				var currentTime = fxNow || createFxNow(),
					remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
					temp = remaining / animation.duration || 0,
					percent = 1 - temp,
					index = 0,
					length = animation.tweens.length;

				for ( ; index < length ; index++ ) {
					animation.tweens[ index ].run( percent );
				}

				deferred.notifyWith( elem, [ animation, percent, remaining ]);

				if ( percent < 1 && length ) {
					return remaining;
				} else {
					deferred.resolveWith( elem, [ animation ] );
					return false;
				}
			},
			animation = deferred.promise({
				elem: elem,
				props: jQuery.extend( {}, properties ),
				opts: jQuery.extend( true, { specialEasing: {} }, options ),
				originalProperties: properties,
				originalOptions: options,
				startTime: fxNow || createFxNow(),
				duration: options.duration,
				tweens: [],
				createTween: function( prop, end ) {
					var tween = jQuery.Tween( elem, animation.opts, prop, end,
						animation.opts.specialEasing[ prop ] || animation.opts.easing );
					animation.tweens.push( tween );
					return tween;
				},
				stop: function( gotoEnd ) {
					var index = 0,
					// if we are going to the end, we want to run all the tweens
					// otherwise we skip this part
						length = gotoEnd ? animation.tweens.length : 0;
					if ( stopped ) {
						return this;
					}
					stopped = true;
					for ( ; index < length ; index++ ) {
						animation.tweens[ index ].run( 1 );
					}

					// resolve when we played the last frame
					// otherwise, reject
					if ( gotoEnd ) {
						deferred.resolveWith( elem, [ animation, gotoEnd ] );
					} else {
						deferred.rejectWith( elem, [ animation, gotoEnd ] );
					}
					return this;
				}
			}),
			props = animation.props;

		propFilter( props, animation.opts.specialEasing );

		for ( ; index < length ; index++ ) {
			result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
			if ( result ) {
				return result;
			}
		}

		jQuery.map( props, createTween, animation );

		if ( jQuery.isFunction( animation.opts.start ) ) {
			animation.opts.start.call( elem, animation );
		}

		jQuery.fx.timer(
			jQuery.extend( tick, {
				elem: elem,
				anim: animation,
				queue: animation.opts.queue
			})
		);

		// attach callbacks from options
		return animation.progress( animation.opts.progress )
			.done( animation.opts.done, animation.opts.complete )
			.fail( animation.opts.fail )
			.always( animation.opts.always );
	}

	jQuery.Animation = jQuery.extend( Animation, {
		tweener: function( props, callback ) {
			if ( jQuery.isFunction( props ) ) {
				callback = props;
				props = [ "*" ];
			} else {
				props = props.split(" ");
			}

			var prop,
				index = 0,
				length = props.length;

			for ( ; index < length ; index++ ) {
				prop = props[ index ];
				tweeners[ prop ] = tweeners[ prop ] || [];
				tweeners[ prop ].unshift( callback );
			}
		},

		prefilter: function( callback, prepend ) {
			if ( prepend ) {
				animationPrefilters.unshift( callback );
			} else {
				animationPrefilters.push( callback );
			}
		}
	});

	jQuery.speed = function( speed, easing, fn ) {
		var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
			complete: fn || !fn && easing ||
			jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;

		// normalize opt.queue - true/undefined/null -> "fx"
		if ( opt.queue == null || opt.queue === true ) {
			opt.queue = "fx";
		}

		// Queueing
		opt.old = opt.complete;

		opt.complete = function() {
			if ( jQuery.isFunction( opt.old ) ) {
				opt.old.call( this );
			}

			if ( opt.queue ) {
				jQuery.dequeue( this, opt.queue );
			}
		};

		return opt;
	};

	jQuery.fn.extend({
		fadeTo: function( speed, to, easing, callback ) {

			// show any hidden elements after setting opacity to 0
			return this.filter( isHidden ).css( "opacity", 0 ).show()

				// animate to the value specified
				.end().animate({ opacity: to }, speed, easing, callback );
		},
		animate: function( prop, speed, easing, callback ) {
			var empty = jQuery.isEmptyObject( prop ),
				optall = jQuery.speed( speed, easing, callback ),
				doAnimation = function() {
					// Operate on a copy of prop so per-property easing won't be lost
					var anim = Animation( this, jQuery.extend( {}, prop ), optall );

					// Empty animations, or finishing resolves immediately
					if ( empty || jQuery._data( this, "finish" ) ) {
						anim.stop( true );
					}
				};
			doAnimation.finish = doAnimation;

			return empty || optall.queue === false ?
				this.each( doAnimation ) :
				this.queue( optall.queue, doAnimation );
		},
		stop: function( type, clearQueue, gotoEnd ) {
			var stopQueue = function( hooks ) {
				var stop = hooks.stop;
				delete hooks.stop;
				stop( gotoEnd );
			};

			if ( typeof type !== "string" ) {
				gotoEnd = clearQueue;
				clearQueue = type;
				type = undefined;
			}
			if ( clearQueue && type !== false ) {
				this.queue( type || "fx", [] );
			}

			return this.each(function() {
				var dequeue = true,
					index = type != null && type + "queueHooks",
					timers = jQuery.timers,
					data = jQuery._data( this );

				if ( index ) {
					if ( data[ index ] && data[ index ].stop ) {
						stopQueue( data[ index ] );
					}
				} else {
					for ( index in data ) {
						if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
							stopQueue( data[ index ] );
						}
					}
				}

				for ( index = timers.length; index--; ) {
					if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
						timers[ index ].anim.stop( gotoEnd );
						dequeue = false;
						timers.splice( index, 1 );
					}
				}

				// start the next in the queue if the last step wasn't forced
				// timers currently will call their complete callbacks, which will dequeue
				// but only if they were gotoEnd
				if ( dequeue || !gotoEnd ) {
					jQuery.dequeue( this, type );
				}
			});
		},
		finish: function( type ) {
			if ( type !== false ) {
				type = type || "fx";
			}
			return this.each(function() {
				var index,
					data = jQuery._data( this ),
					queue = data[ type + "queue" ],
					hooks = data[ type + "queueHooks" ],
					timers = jQuery.timers,
					length = queue ? queue.length : 0;

				// enable finishing flag on private data
				data.finish = true;

				// empty the queue first
				jQuery.queue( this, type, [] );

				if ( hooks && hooks.stop ) {
					hooks.stop.call( this, true );
				}

				// look for any active animations, and finish them
				for ( index = timers.length; index--; ) {
					if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
						timers[ index ].anim.stop( true );
						timers.splice( index, 1 );
					}
				}

				// look for any animations in the old queue and finish them
				for ( index = 0; index < length; index++ ) {
					if ( queue[ index ] && queue[ index ].finish ) {
						queue[ index ].finish.call( this );
					}
				}

				// turn off finishing flag
				delete data.finish;
			});
		}
	});

	jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
		var cssFn = jQuery.fn[ name ];
		jQuery.fn[ name ] = function( speed, easing, callback ) {
			return speed == null || typeof speed === "boolean" ?
				cssFn.apply( this, arguments ) :
				this.animate( genFx( name, true ), speed, easing, callback );
		};
	});

// Generate shortcuts for custom animations
	jQuery.each({
		slideDown: genFx("show"),
		slideUp: genFx("hide"),
		slideToggle: genFx("toggle"),
		fadeIn: { opacity: "show" },
		fadeOut: { opacity: "hide" },
		fadeToggle: { opacity: "toggle" }
	}, function( name, props ) {
		jQuery.fn[ name ] = function( speed, easing, callback ) {
			return this.animate( props, speed, easing, callback );
		};
	});

	jQuery.timers = [];
	jQuery.fx.tick = function() {
		var timer,
			timers = jQuery.timers,
			i = 0;

		fxNow = jQuery.now();

		for ( ; i < timers.length; i++ ) {
			timer = timers[ i ];
			// Checks the timer has not already been removed
			if ( !timer() && timers[ i ] === timer ) {
				timers.splice( i--, 1 );
			}
		}

		if ( !timers.length ) {
			jQuery.fx.stop();
		}
		fxNow = undefined;
	};

	jQuery.fx.timer = function( timer ) {
		jQuery.timers.push( timer );
		if ( timer() ) {
			jQuery.fx.start();
		} else {
			jQuery.timers.pop();
		}
	};

	jQuery.fx.interval = 13;

	jQuery.fx.start = function() {
		if ( !timerId ) {
			timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
		}
	};

	jQuery.fx.stop = function() {
		clearInterval( timerId );
		timerId = null;
	};

	jQuery.fx.speeds = {
		slow: 600,
		fast: 200,
		// Default speed
		_default: 400
	};


// Based off of the plugin by Clint Helfers, with permission.
// http://blindsignals.com/index.php/2009/07/jquery-delay/
	jQuery.fn.delay = function( time, type ) {
		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
		type = type || "fx";

		return this.queue( type, function( next, hooks ) {
			var timeout = setTimeout( next, time );
			hooks.stop = function() {
				clearTimeout( timeout );
			};
		});
	};


	(function() {
		// Minified: var a,b,c,d,e
		var input, div, select, a, opt;

		// Setup
		div = document.createElement( "div" );
		div.setAttribute( "className", "t" );
		div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
		a = div.getElementsByTagName("a")[ 0 ];

		// First batch of tests.
		select = document.createElement("select");
		opt = select.appendChild( document.createElement("option") );
		input = div.getElementsByTagName("input")[ 0 ];

		a.style.cssText = "top:1px";

		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
		support.getSetAttribute = div.className !== "t";

		// Get the style information from getAttribute
		// (IE uses .cssText instead)
		support.style = /top/.test( a.getAttribute("style") );

		// Make sure that URLs aren't manipulated
		// (IE normalizes it by default)
		support.hrefNormalized = a.getAttribute("href") === "/a";

		// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
		support.checkOn = !!input.value;

		// Make sure that a selected-by-default option has a working selected property.
		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
		support.optSelected = opt.selected;

		// Tests for enctype support on a form (#6743)
		support.enctype = !!document.createElement("form").enctype;

		// Make sure that the options inside disabled selects aren't marked as disabled
		// (WebKit marks them as disabled)
		select.disabled = true;
		support.optDisabled = !opt.disabled;

		// Support: IE8 only
		// Check if we can trust getAttribute("value")
		input = document.createElement( "input" );
		input.setAttribute( "value", "" );
		support.input = input.getAttribute( "value" ) === "";

		// Check if an input maintains its value after becoming a radio
		input.value = "t";
		input.setAttribute( "type", "radio" );
		support.radioValue = input.value === "t";
	})();


	var rreturn = /\r/g;

	jQuery.fn.extend({
		val: function( value ) {
			var hooks, ret, isFunction,
				elem = this[0];

			if ( !arguments.length ) {
				if ( elem ) {
					hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];

					if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
						return ret;
					}

					ret = elem.value;

					return typeof ret === "string" ?
						// handle most common string cases
						ret.replace(rreturn, "") :
						// handle cases where value is null/undef or number
						ret == null ? "" : ret;
				}

				return;
			}

			isFunction = jQuery.isFunction( value );

			return this.each(function( i ) {
				var val;

				if ( this.nodeType !== 1 ) {
					return;
				}

				if ( isFunction ) {
					val = value.call( this, i, jQuery( this ).val() );
				} else {
					val = value;
				}

				// Treat null/undefined as ""; convert numbers to string
				if ( val == null ) {
					val = "";
				} else if ( typeof val === "number" ) {
					val += "";
				} else if ( jQuery.isArray( val ) ) {
					val = jQuery.map( val, function( value ) {
						return value == null ? "" : value + "";
					});
				}

				hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];

				// If set returns undefined, fall back to normal setting
				if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
					this.value = val;
				}
			});
		}
	});

	jQuery.extend({
		valHooks: {
			option: {
				get: function( elem ) {
					var val = jQuery.find.attr( elem, "value" );
					return val != null ?
						val :
						// Support: IE10-11+
						// option.text throws exceptions (#14686, #14858)
						jQuery.trim( jQuery.text( elem ) );
				}
			},
			select: {
				get: function( elem ) {
					var value, option,
						options = elem.options,
						index = elem.selectedIndex,
						one = elem.type === "select-one" || index < 0,
						values = one ? null : [],
						max = one ? index + 1 : options.length,
						i = index < 0 ?
							max :
							one ? index : 0;

					// Loop through all the selected options
					for ( ; i < max; i++ ) {
						option = options[ i ];

						// oldIE doesn't update selected after form reset (#2551)
						if ( ( option.selected || i === index ) &&
								// Don't return options that are disabled or in a disabled optgroup
							( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {

							// Get the specific value for the option
							value = jQuery( option ).val();

							// We don't need an array for one selects
							if ( one ) {
								return value;
							}

							// Multi-Selects return an array
							values.push( value );
						}
					}

					return values;
				},

				set: function( elem, value ) {
					var optionSet, option,
						options = elem.options,
						values = jQuery.makeArray( value ),
						i = options.length;

					while ( i-- ) {
						option = options[ i ];

						if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {

							// Support: IE6
							// When new option element is added to select box we need to
							// force reflow of newly added node in order to workaround delay
							// of initialization properties
							try {
								option.selected = optionSet = true;

							} catch ( _ ) {

								// Will be executed only in IE6
								option.scrollHeight;
							}

						} else {
							option.selected = false;
						}
					}

					// Force browsers to behave consistently when non-matching value is set
					if ( !optionSet ) {
						elem.selectedIndex = -1;
					}

					return options;
				}
			}
		}
	});

// Radios and checkboxes getter/setter
	jQuery.each([ "radio", "checkbox" ], function() {
		jQuery.valHooks[ this ] = {
			set: function( elem, value ) {
				if ( jQuery.isArray( value ) ) {
					return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
				}
			}
		};
		if ( !support.checkOn ) {
			jQuery.valHooks[ this ].get = function( elem ) {
				// Support: Webkit
				// "" is returned instead of "on" if a value isn't specified
				return elem.getAttribute("value") === null ? "on" : elem.value;
			};
		}
	});




	var nodeHook, boolHook,
		attrHandle = jQuery.expr.attrHandle,
		ruseDefault = /^(?:checked|selected)$/i,
		getSetAttribute = support.getSetAttribute,
		getSetInput = support.input;

	jQuery.fn.extend({
		attr: function( name, value ) {
			return access( this, jQuery.attr, name, value, arguments.length > 1 );
		},

		removeAttr: function( name ) {
			return this.each(function() {
				jQuery.removeAttr( this, name );
			});
		}
	});

	jQuery.extend({
		attr: function( elem, name, value ) {
			var hooks, ret,
				nType = elem.nodeType;

			// don't get/set attributes on text, comment and attribute nodes
			if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
				return;
			}

			// Fallback to prop when attributes are not supported
			if ( typeof elem.getAttribute === strundefined ) {
				return jQuery.prop( elem, name, value );
			}

			// All attributes are lowercase
			// Grab necessary hook if one is defined
			if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
				name = name.toLowerCase();
				hooks = jQuery.attrHooks[ name ] ||
				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
			}

			if ( value !== undefined ) {

				if ( value === null ) {
					jQuery.removeAttr( elem, name );

				} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
					return ret;

				} else {
					elem.setAttribute( name, value + "" );
					return value;
				}

			} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
				return ret;

			} else {
				ret = jQuery.find.attr( elem, name );

				// Non-existent attributes return null, we normalize to undefined
				return ret == null ?
					undefined :
					ret;
			}
		},

		removeAttr: function( elem, value ) {
			var name, propName,
				i = 0,
				attrNames = value && value.match( rnotwhite );

			if ( attrNames && elem.nodeType === 1 ) {
				while ( (name = attrNames[i++]) ) {
					propName = jQuery.propFix[ name ] || name;

					// Boolean attributes get special treatment (#10870)
					if ( jQuery.expr.match.bool.test( name ) ) {
						// Set corresponding property to false
						if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
							elem[ propName ] = false;
							// Support: IE<9
							// Also clear defaultChecked/defaultSelected (if appropriate)
						} else {
							elem[ jQuery.camelCase( "default-" + name ) ] =
								elem[ propName ] = false;
						}

						// See #9699 for explanation of this approach (setting first, then removal)
					} else {
						jQuery.attr( elem, name, "" );
					}

					elem.removeAttribute( getSetAttribute ? name : propName );
				}
			}
		},

		attrHooks: {
			type: {
				set: function( elem, value ) {
					if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
						// Setting the type on a radio button after the value resets the value in IE6-9
						// Reset value to default in case type is set after value during creation
						var val = elem.value;
						elem.setAttribute( "type", value );
						if ( val ) {
							elem.value = val;
						}
						return value;
					}
				}
			}
		}
	});

// Hook for boolean attributes
	boolHook = {
		set: function( elem, value, name ) {
			if ( value === false ) {
				// Remove boolean attributes when set to false
				jQuery.removeAttr( elem, name );
			} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
				// IE<8 needs the *property* name
				elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );

				// Use defaultChecked and defaultSelected for oldIE
			} else {
				elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
			}

			return name;
		}
	};

// Retrieve booleans specially
	jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {

		var getter = attrHandle[ name ] || jQuery.find.attr;

		attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
			function( elem, name, isXML ) {
				var ret, handle;
				if ( !isXML ) {
					// Avoid an infinite loop by temporarily removing this function from the getter
					handle = attrHandle[ name ];
					attrHandle[ name ] = ret;
					ret = getter( elem, name, isXML ) != null ?
						name.toLowerCase() :
						null;
					attrHandle[ name ] = handle;
				}
				return ret;
			} :
			function( elem, name, isXML ) {
				if ( !isXML ) {
					return elem[ jQuery.camelCase( "default-" + name ) ] ?
						name.toLowerCase() :
						null;
				}
			};
	});

// fix oldIE attroperties
	if ( !getSetInput || !getSetAttribute ) {
		jQuery.attrHooks.value = {
			set: function( elem, value, name ) {
				if ( jQuery.nodeName( elem, "input" ) ) {
					// Does not return so that setAttribute is also used
					elem.defaultValue = value;
				} else {
					// Use nodeHook if defined (#1954); otherwise setAttribute is fine
					return nodeHook && nodeHook.set( elem, value, name );
				}
			}
		};
	}

// IE6/7 do not support getting/setting some attributes with get/setAttribute
	if ( !getSetAttribute ) {

		// Use this for any attribute in IE6/7
		// This fixes almost every IE6/7 issue
		nodeHook = {
			set: function( elem, value, name ) {
				// Set the existing or create a new attribute node
				var ret = elem.getAttributeNode( name );
				if ( !ret ) {
					elem.setAttributeNode(
						(ret = elem.ownerDocument.createAttribute( name ))
					);
				}

				ret.value = value += "";

				// Break association with cloned elements by also using setAttribute (#9646)
				if ( name === "value" || value === elem.getAttribute( name ) ) {
					return value;
				}
			}
		};

		// Some attributes are constructed with empty-string values when not defined
		attrHandle.id = attrHandle.name = attrHandle.coords =
			function( elem, name, isXML ) {
				var ret;
				if ( !isXML ) {
					return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
						ret.value :
						null;
				}
			};

		// Fixing value retrieval on a button requires this module
		jQuery.valHooks.button = {
			get: function( elem, name ) {
				var ret = elem.getAttributeNode( name );
				if ( ret && ret.specified ) {
					return ret.value;
				}
			},
			set: nodeHook.set
		};

		// Set contenteditable to false on removals(#10429)
		// Setting to empty string throws an error as an invalid value
		jQuery.attrHooks.contenteditable = {
			set: function( elem, value, name ) {
				nodeHook.set( elem, value === "" ? false : value, name );
			}
		};

		// Set width and height to auto instead of 0 on empty string( Bug #8150 )
		// This is for removals
		jQuery.each([ "width", "height" ], function( i, name ) {
			jQuery.attrHooks[ name ] = {
				set: function( elem, value ) {
					if ( value === "" ) {
						elem.setAttribute( name, "auto" );
						return value;
					}
				}
			};
		});
	}

	if ( !support.style ) {
		jQuery.attrHooks.style = {
			get: function( elem ) {
				// Return undefined in the case of empty string
				// Note: IE uppercases css property names, but if we were to .toLowerCase()
				// .cssText, that would destroy case senstitivity in URL's, like in "background"
				return elem.style.cssText || undefined;
			},
			set: function( elem, value ) {
				return ( elem.style.cssText = value + "" );
			}
		};
	}




	var rfocusable = /^(?:input|select|textarea|button|object)$/i,
		rclickable = /^(?:a|area)$/i;

	jQuery.fn.extend({
		prop: function( name, value ) {
			return access( this, jQuery.prop, name, value, arguments.length > 1 );
		},

		removeProp: function( name ) {
			name = jQuery.propFix[ name ] || name;
			return this.each(function() {
				// try/catch handles cases where IE balks (such as removing a property on window)
				try {
					this[ name ] = undefined;
					delete this[ name ];
				} catch( e ) {}
			});
		}
	});

	jQuery.extend({
		propFix: {
			"for": "htmlFor",
			"class": "className"
		},

		prop: function( elem, name, value ) {
			var ret, hooks, notxml,
				nType = elem.nodeType;

			// don't get/set properties on text, comment and attribute nodes
			if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
				return;
			}

			notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

			if ( notxml ) {
				// Fix name and attach hooks
				name = jQuery.propFix[ name ] || name;
				hooks = jQuery.propHooks[ name ];
			}

			if ( value !== undefined ) {
				return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
					ret :
					( elem[ name ] = value );

			} else {
				return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
					ret :
					elem[ name ];
			}
		},

		propHooks: {
			tabIndex: {
				get: function( elem ) {
					// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
					// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
					// Use proper attribute retrieval(#12072)
					var tabindex = jQuery.find.attr( elem, "tabindex" );

					return tabindex ?
						parseInt( tabindex, 10 ) :
						rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
							0 :
							-1;
				}
			}
		}
	});

// Some attributes require a special call on IE
// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
	if ( !support.hrefNormalized ) {
		// href/src property should get the full normalized URL (#10299/#12915)
		jQuery.each([ "href", "src" ], function( i, name ) {
			jQuery.propHooks[ name ] = {
				get: function( elem ) {
					return elem.getAttribute( name, 4 );
				}
			};
		});
	}

// Support: Safari, IE9+
// mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
	if ( !support.optSelected ) {
		jQuery.propHooks.selected = {
			get: function( elem ) {
				var parent = elem.parentNode;

				if ( parent ) {
					parent.selectedIndex;

					// Make sure that it also works with optgroups, see #5701
					if ( parent.parentNode ) {
						parent.parentNode.selectedIndex;
					}
				}
				return null;
			}
		};
	}

	jQuery.each([
		"tabIndex",
		"readOnly",
		"maxLength",
		"cellSpacing",
		"cellPadding",
		"rowSpan",
		"colSpan",
		"useMap",
		"frameBorder",
		"contentEditable"
	], function() {
		jQuery.propFix[ this.toLowerCase() ] = this;
	});

// IE6/7 call enctype encoding
	if ( !support.enctype ) {
		jQuery.propFix.enctype = "encoding";
	}




	var rclass = /[\t\r\n\f]/g;

	jQuery.fn.extend({
		addClass: function( value ) {
			var classes, elem, cur, clazz, j, finalValue,
				i = 0,
				len = this.length,
				proceed = typeof value === "string" && value;

			if ( jQuery.isFunction( value ) ) {
				return this.each(function( j ) {
					jQuery( this ).addClass( value.call( this, j, this.className ) );
				});
			}

			if ( proceed ) {
				// The disjunction here is for better compressibility (see removeClass)
				classes = ( value || "" ).match( rnotwhite ) || [];

				for ( ; i < len; i++ ) {
					elem = this[ i ];
					cur = elem.nodeType === 1 && ( elem.className ?
						( " " + elem.className + " " ).replace( rclass, " " ) :
						" "
					);

					if ( cur ) {
						j = 0;
						while ( (clazz = classes[j++]) ) {
							if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
								cur += clazz + " ";
							}
						}

						// only assign if different to avoid unneeded rendering.
						finalValue = jQuery.trim( cur );
						if ( elem.className !== finalValue ) {
							elem.className = finalValue;
						}
					}
				}
			}

			return this;
		},

		removeClass: function( value ) {
			var classes, elem, cur, clazz, j, finalValue,
				i = 0,
				len = this.length,
				proceed = arguments.length === 0 || typeof value === "string" && value;

			if ( jQuery.isFunction( value ) ) {
				return this.each(function( j ) {
					jQuery( this ).removeClass( value.call( this, j, this.className ) );
				});
			}
			if ( proceed ) {
				classes = ( value || "" ).match( rnotwhite ) || [];

				for ( ; i < len; i++ ) {
					elem = this[ i ];
					// This expression is here for better compressibility (see addClass)
					cur = elem.nodeType === 1 && ( elem.className ?
						( " " + elem.className + " " ).replace( rclass, " " ) :
						""
					);

					if ( cur ) {
						j = 0;
						while ( (clazz = classes[j++]) ) {
							// Remove *all* instances
							while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
								cur = cur.replace( " " + clazz + " ", " " );
							}
						}

						// only assign if different to avoid unneeded rendering.
						finalValue = value ? jQuery.trim( cur ) : "";
						if ( elem.className !== finalValue ) {
							elem.className = finalValue;
						}
					}
				}
			}

			return this;
		},

		toggleClass: function( value, stateVal ) {
			var type = typeof value;

			if ( typeof stateVal === "boolean" && type === "string" ) {
				return stateVal ? this.addClass( value ) : this.removeClass( value );
			}

			if ( jQuery.isFunction( value ) ) {
				return this.each(function( i ) {
					jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
				});
			}

			return this.each(function() {
				if ( type === "string" ) {
					// toggle individual class names
					var className,
						i = 0,
						self = jQuery( this ),
						classNames = value.match( rnotwhite ) || [];

					while ( (className = classNames[ i++ ]) ) {
						// check each className given, space separated list
						if ( self.hasClass( className ) ) {
							self.removeClass( className );
						} else {
							self.addClass( className );
						}
					}

					// Toggle whole class name
				} else if ( type === strundefined || type === "boolean" ) {
					if ( this.className ) {
						// store className if set
						jQuery._data( this, "__className__", this.className );
					}

					// If the element has a class name or if we're passed "false",
					// then remove the whole classname (if there was one, the above saved it).
					// Otherwise bring back whatever was previously saved (if anything),
					// falling back to the empty string if nothing was stored.
					this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
				}
			});
		},

		hasClass: function( selector ) {
			var className = " " + selector + " ",
				i = 0,
				l = this.length;
			for ( ; i < l; i++ ) {
				if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
					return true;
				}
			}

			return false;
		}
	});




// Return jQuery for attributes-only inclusion


	jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {

		// Handle event binding
		jQuery.fn[ name ] = function( data, fn ) {
			return arguments.length > 0 ?
				this.on( name, null, data, fn ) :
				this.trigger( name );
		};
	});

	jQuery.fn.extend({
		hover: function( fnOver, fnOut ) {
			return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
		},

		bind: function( types, data, fn ) {
			return this.on( types, null, data, fn );
		},
		unbind: function( types, fn ) {
			return this.off( types, null, fn );
		},

		delegate: function( selector, types, data, fn ) {
			return this.on( types, selector, data, fn );
		},
		undelegate: function( selector, types, fn ) {
			// ( namespace ) or ( selector, types [, fn] )
			return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
		}
	});


	var nonce = jQuery.now();

	var rquery = (/\?/);



	var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;

	jQuery.parseJSON = function( data ) {
		// Attempt to parse using the native JSON parser first
		if ( window.JSON && window.JSON.parse ) {
			// Support: Android 2.3
			// Workaround failure to string-cast null input
			return window.JSON.parse( data + "" );
		}

		var requireNonComma,
			depth = null,
			str = jQuery.trim( data + "" );

		// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
		// after removing valid tokens
		return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {

			// Force termination if we see a misplaced comma
			if ( requireNonComma && comma ) {
				depth = 0;
			}

			// Perform no more replacements after returning to outermost depth
			if ( depth === 0 ) {
				return token;
			}

			// Commas must not follow "[", "{", or ","
			requireNonComma = open || comma;

			// Determine new depth
			// array/object open ("[" or "{"): depth += true - false (increment)
			// array/object close ("]" or "}"): depth += false - true (decrement)
			// other cases ("," or primitive): depth += true - true (numeric cast)
			depth += !close - !open;

			// Remove this token
			return "";
		}) ) ?
			( Function( "return " + str ) )() :
			jQuery.error( "Invalid JSON: " + data );
	};


// Cross-browser xml parsing
	jQuery.parseXML = function( data ) {
		var xml, tmp;
		if ( !data || typeof data !== "string" ) {
			return null;
		}
		try {
			if ( window.DOMParser ) { // Standard
				tmp = new DOMParser();
				xml = tmp.parseFromString( data, "text/xml" );
			} else { // IE
				xml = new ActiveXObject( "Microsoft.XMLDOM" );
				xml.async = "false";
				xml.loadXML( data );
			}
		} catch( e ) {
			xml = undefined;
		}
		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
			jQuery.error( "Invalid XML: " + data );
		}
		return xml;
	};


	var
	// Document location
		ajaxLocParts,
		ajaxLocation,

		rhash = /#.*$/,
		rts = /([?&])_=[^&]*/,
		rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
	// #7653, #8125, #8152: local protocol detection
		rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
		rnoContent = /^(?:GET|HEAD)$/,
		rprotocol = /^\/\//,
		rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,

	/* Prefilters
	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
	 * 2) These are called:
	 *    - BEFORE asking for a transport
	 *    - AFTER param serialization (s.data is a string if s.processData is true)
	 * 3) key is the dataType
	 * 4) the catchall symbol "*" can be used
	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
	 */
		prefilters = {},

	/* Transports bindings
	 * 1) key is the dataType
	 * 2) the catchall symbol "*" can be used
	 * 3) selection will start with transport dataType and THEN go to "*" if needed
	 */
		transports = {},

	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
		allTypes = "*/".concat("*");

// #8138, IE may throw an exception when accessing
// a field from window.location if document.domain has been set
	try {
		ajaxLocation = location.href;
	} catch( e ) {
		// Use the href attribute of an A element
		// since IE will modify it given document.location
		ajaxLocation = document.createElement( "a" );
		ajaxLocation.href = "";
		ajaxLocation = ajaxLocation.href;
	}

// Segment location into parts
	ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
	function addToPrefiltersOrTransports( structure ) {

		// dataTypeExpression is optional and defaults to "*"
		return function( dataTypeExpression, func ) {

			if ( typeof dataTypeExpression !== "string" ) {
				func = dataTypeExpression;
				dataTypeExpression = "*";
			}

			var dataType,
				i = 0,
				dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];

			if ( jQuery.isFunction( func ) ) {
				// For each dataType in the dataTypeExpression
				while ( (dataType = dataTypes[i++]) ) {
					// Prepend if requested
					if ( dataType.charAt( 0 ) === "+" ) {
						dataType = dataType.slice( 1 ) || "*";
						(structure[ dataType ] = structure[ dataType ] || []).unshift( func );

						// Otherwise append
					} else {
						(structure[ dataType ] = structure[ dataType ] || []).push( func );
					}
				}
			}
		};
	}

// Base inspection function for prefilters and transports
	function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {

		var inspected = {},
			seekingTransport = ( structure === transports );

		function inspect( dataType ) {
			var selected;
			inspected[ dataType ] = true;
			jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
				var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
				if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
					options.dataTypes.unshift( dataTypeOrTransport );
					inspect( dataTypeOrTransport );
					return false;
				} else if ( seekingTransport ) {
					return !( selected = dataTypeOrTransport );
				}
			});
			return selected;
		}

		return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
	}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes #9887
	function ajaxExtend( target, src ) {
		var deep, key,
			flatOptions = jQuery.ajaxSettings.flatOptions || {};

		for ( key in src ) {
			if ( src[ key ] !== undefined ) {
				( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
			}
		}
		if ( deep ) {
			jQuery.extend( true, target, deep );
		}

		return target;
	}

	/* Handles responses to an ajax request:
	 * - finds the right dataType (mediates between content-type and expected dataType)
	 * - returns the corresponding response
	 */
	function ajaxHandleResponses( s, jqXHR, responses ) {
		var firstDataType, ct, finalDataType, type,
			contents = s.contents,
			dataTypes = s.dataTypes;

		// Remove auto dataType and get content-type in the process
		while ( dataTypes[ 0 ] === "*" ) {
			dataTypes.shift();
			if ( ct === undefined ) {
				ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
			}
		}

		// Check if we're dealing with a known content-type
		if ( ct ) {
			for ( type in contents ) {
				if ( contents[ type ] && contents[ type ].test( ct ) ) {
					dataTypes.unshift( type );
					break;
				}
			}
		}

		// Check to see if we have a response for the expected dataType
		if ( dataTypes[ 0 ] in responses ) {
			finalDataType = dataTypes[ 0 ];
		} else {
			// Try convertible dataTypes
			for ( type in responses ) {
				if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
					finalDataType = type;
					break;
				}
				if ( !firstDataType ) {
					firstDataType = type;
				}
			}
			// Or just use first one
			finalDataType = finalDataType || firstDataType;
		}

		// If we found a dataType
		// We add the dataType to the list if needed
		// and return the corresponding response
		if ( finalDataType ) {
			if ( finalDataType !== dataTypes[ 0 ] ) {
				dataTypes.unshift( finalDataType );
			}
			return responses[ finalDataType ];
		}
	}

	/* Chain conversions given the request and the original response
	 * Also sets the responseXXX fields on the jqXHR instance
	 */
	function ajaxConvert( s, response, jqXHR, isSuccess ) {
		var conv2, current, conv, tmp, prev,
			converters = {},
		// Work with a copy of dataTypes in case we need to modify it for conversion
			dataTypes = s.dataTypes.slice();

		// Create converters map with lowercased keys
		if ( dataTypes[ 1 ] ) {
			for ( conv in s.converters ) {
				converters[ conv.toLowerCase() ] = s.converters[ conv ];
			}
		}

		current = dataTypes.shift();

		// Convert to each sequential dataType
		while ( current ) {

			if ( s.responseFields[ current ] ) {
				jqXHR[ s.responseFields[ current ] ] = response;
			}

			// Apply the dataFilter if provided
			if ( !prev && isSuccess && s.dataFilter ) {
				response = s.dataFilter( response, s.dataType );
			}

			prev = current;
			current = dataTypes.shift();

			if ( current ) {

				// There's only work to do if current dataType is non-auto
				if ( current === "*" ) {

					current = prev;

					// Convert response if prev dataType is non-auto and differs from current
				} else if ( prev !== "*" && prev !== current ) {

					// Seek a direct converter
					conv = converters[ prev + " " + current ] || converters[ "* " + current ];

					// If none found, seek a pair
					if ( !conv ) {
						for ( conv2 in converters ) {

							// If conv2 outputs current
							tmp = conv2.split( " " );
							if ( tmp[ 1 ] === current ) {

								// If prev can be converted to accepted input
								conv = converters[ prev + " " + tmp[ 0 ] ] ||
								converters[ "* " + tmp[ 0 ] ];
								if ( conv ) {
									// Condense equivalence converters
									if ( conv === true ) {
										conv = converters[ conv2 ];

										// Otherwise, insert the intermediate dataType
									} else if ( converters[ conv2 ] !== true ) {
										current = tmp[ 0 ];
										dataTypes.unshift( tmp[ 1 ] );
									}
									break;
								}
							}
						}
					}

					// Apply converter (if not an equivalence)
					if ( conv !== true ) {

						// Unless errors are allowed to bubble, catch and return them
						if ( conv && s[ "throws" ] ) {
							response = conv( response );
						} else {
							try {
								response = conv( response );
							} catch ( e ) {
								return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
							}
						}
					}
				}
			}
		}

		return { state: "success", data: response };
	}

	jQuery.extend({

		// Counter for holding the number of active queries
		active: 0,

		// Last-Modified header cache for next request
		lastModified: {},
		etag: {},

		ajaxSettings: {
			url: ajaxLocation,
			type: "GET",
			isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
			global: true,
			processData: true,
			async: true,
			contentType: "application/x-www-form-urlencoded; charset=UTF-8",
			/*
			 timeout: 0,
			 data: null,
			 dataType: null,
			 username: null,
			 password: null,
			 cache: null,
			 throws: false,
			 traditional: false,
			 headers: {},
			 */

			accepts: {
				"*": allTypes,
				text: "text/plain",
				html: "text/html",
				xml: "application/xml, text/xml",
				json: "application/json, text/javascript"
			},

			contents: {
				xml: /xml/,
				html: /html/,
				json: /json/
			},

			responseFields: {
				xml: "responseXML",
				text: "responseText",
				json: "responseJSON"
			},

			// Data converters
			// Keys separate source (or catchall "*") and destination types with a single space
			converters: {

				// Convert anything to text
				"* text": String,

				// Text to html (true = no transformation)
				"text html": true,

				// Evaluate text as a json expression
				"text json": jQuery.parseJSON,

				// Parse text as xml
				"text xml": jQuery.parseXML
			},

			// For options that shouldn't be deep extended:
			// you can add your own custom options here if
			// and when you create one that shouldn't be
			// deep extended (see ajaxExtend)
			flatOptions: {
				url: true,
				context: true
			}
		},

		// Creates a full fledged settings object into target
		// with both ajaxSettings and settings fields.
		// If target is omitted, writes into ajaxSettings.
		ajaxSetup: function( target, settings ) {
			return settings ?

				// Building a settings object
				ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :

				// Extending ajaxSettings
				ajaxExtend( jQuery.ajaxSettings, target );
		},

		ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
		ajaxTransport: addToPrefiltersOrTransports( transports ),

		// Main method
		ajax: function( url, options ) {

			// If url is an object, simulate pre-1.5 signature
			if ( typeof url === "object" ) {
				options = url;
				url = undefined;
			}

			// Force options to be an object
			options = options || {};

			var // Cross-domain detection vars
				parts,
			// Loop variable
				i,
			// URL without anti-cache param
				cacheURL,
			// Response headers as string
				responseHeadersString,
			// timeout handle
				timeoutTimer,

			// To know if global events are to be dispatched
				fireGlobals,

				transport,
			// Response headers
				responseHeaders,
			// Create the final options object
				s = jQuery.ajaxSetup( {}, options ),
			// Callbacks context
				callbackContext = s.context || s,
			// Context for global events is callbackContext if it is a DOM node or jQuery collection
				globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
					jQuery( callbackContext ) :
					jQuery.event,
			// Deferreds
				deferred = jQuery.Deferred(),
				completeDeferred = jQuery.Callbacks("once memory"),
			// Status-dependent callbacks
				statusCode = s.statusCode || {},
			// Headers (they are sent all at once)
				requestHeaders = {},
				requestHeadersNames = {},
			// The jqXHR state
				state = 0,
			// Default abort message
				strAbort = "canceled",
			// Fake xhr
				jqXHR = {
					readyState: 0,

					// Builds headers hashtable if needed
					getResponseHeader: function( key ) {
						var match;
						if ( state === 2 ) {
							if ( !responseHeaders ) {
								responseHeaders = {};
								while ( (match = rheaders.exec( responseHeadersString )) ) {
									responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
								}
							}
							match = responseHeaders[ key.toLowerCase() ];
						}
						return match == null ? null : match;
					},

					// Raw string
					getAllResponseHeaders: function() {
						return state === 2 ? responseHeadersString : null;
					},

					// Caches the header
					setRequestHeader: function( name, value ) {
						var lname = name.toLowerCase();
						if ( !state ) {
							name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
							requestHeaders[ name ] = value;
						}
						return this;
					},

					// Overrides response content-type header
					overrideMimeType: function( type ) {
						if ( !state ) {
							s.mimeType = type;
						}
						return this;
					},

					// Status-dependent callbacks
					statusCode: function( map ) {
						var code;
						if ( map ) {
							if ( state < 2 ) {
								for ( code in map ) {
									// Lazy-add the new callback in a way that preserves old ones
									statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
								}
							} else {
								// Execute the appropriate callbacks
								jqXHR.always( map[ jqXHR.status ] );
							}
						}
						return this;
					},

					// Cancel the request
					abort: function( statusText ) {
						var finalText = statusText || strAbort;
						if ( transport ) {
							transport.abort( finalText );
						}
						done( 0, finalText );
						return this;
					}
				};

			// Attach deferreds
			deferred.promise( jqXHR ).complete = completeDeferred.add;
			jqXHR.success = jqXHR.done;
			jqXHR.error = jqXHR.fail;

			// Remove hash character (#7531: and string promotion)
			// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
			// Handle falsy url in the settings object (#10093: consistency with old signature)
			// We also use the url parameter if available
			s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );

			// Alias method option to type as per ticket #12004
			s.type = options.method || options.type || s.method || s.type;

			// Extract dataTypes list
			s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];

			// A cross-domain request is in order when we have a protocol:host:port mismatch
			if ( s.crossDomain == null ) {
				parts = rurl.exec( s.url.toLowerCase() );
				s.crossDomain = !!( parts &&
				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
				( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
				( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
				);
			}

			// Convert data if not already a string
			if ( s.data && s.processData && typeof s.data !== "string" ) {
				s.data = jQuery.param( s.data, s.traditional );
			}

			// Apply prefilters
			inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

			// If request was aborted inside a prefilter, stop there
			if ( state === 2 ) {
				return jqXHR;
			}

			// We can fire global events as of now if asked to
			fireGlobals = s.global;

			// Watch for a new set of requests
			if ( fireGlobals && jQuery.active++ === 0 ) {
				jQuery.event.trigger("ajaxStart");
			}

			// Uppercase the type
			s.type = s.type.toUpperCase();

			// Determine if request has content
			s.hasContent = !rnoContent.test( s.type );

			// Save the URL in case we're toying with the If-Modified-Since
			// and/or If-None-Match header later on
			cacheURL = s.url;

			// More options handling for requests with no content
			if ( !s.hasContent ) {

				// If data is available, append data to url
				if ( s.data ) {
					cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
					// #9682: remove data so that it's not used in an eventual retry
					delete s.data;
				}

				// Add anti-cache in url if needed
				if ( s.cache === false ) {
					s.url = rts.test( cacheURL ) ?

						// If there is already a '_' parameter, set its value
						cacheURL.replace( rts, "$1_=" + nonce++ ) :

						// Otherwise add one to the end
					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
				}
			}

			// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
			if ( s.ifModified ) {
				if ( jQuery.lastModified[ cacheURL ] ) {
					jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
				}
				if ( jQuery.etag[ cacheURL ] ) {
					jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
				}
			}

			// Set the correct header, if data is being sent
			if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
				jqXHR.setRequestHeader( "Content-Type", s.contentType );
			}

			// Set the Accepts header for the server, depending on the dataType
			jqXHR.setRequestHeader(
				"Accept",
				s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
					s.accepts[ "*" ]
			);

			// Check for headers option
			for ( i in s.headers ) {
				jqXHR.setRequestHeader( i, s.headers[ i ] );
			}

			// Allow custom headers/mimetypes and early abort
			if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
				// Abort if not done already and return
				return jqXHR.abort();
			}

			// aborting is no longer a cancellation
			strAbort = "abort";

			// Install callbacks on deferreds
			for ( i in { success: 1, error: 1, complete: 1 } ) {
				jqXHR[ i ]( s[ i ] );
			}

			// Get transport
			transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

			// If no transport, we auto-abort
			if ( !transport ) {
				done( -1, "No Transport" );
			} else {
				jqXHR.readyState = 1;

				// Send global event
				if ( fireGlobals ) {
					globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
				}
				// Timeout
				if ( s.async && s.timeout > 0 ) {
					timeoutTimer = setTimeout(function() {
						jqXHR.abort("timeout");
					}, s.timeout );
				}

				try {
					state = 1;
					transport.send( requestHeaders, done );
				} catch ( e ) {
					// Propagate exception as error if not done
					if ( state < 2 ) {
						done( -1, e );
						// Simply rethrow otherwise
					} else {
						throw e;
					}
				}
			}

			// Callback for when everything is done
			function done( status, nativeStatusText, responses, headers ) {
				var isSuccess, success, error, response, modified,
					statusText = nativeStatusText;

				// Called once
				if ( state === 2 ) {
					return;
				}

				// State is "done" now
				state = 2;

				// Clear timeout if it exists
				if ( timeoutTimer ) {
					clearTimeout( timeoutTimer );
				}

				// Dereference transport for early garbage collection
				// (no matter how long the jqXHR object will be used)
				transport = undefined;

				// Cache response headers
				responseHeadersString = headers || "";

				// Set readyState
				jqXHR.readyState = status > 0 ? 4 : 0;

				// Determine if successful
				isSuccess = status >= 200 && status < 300 || status === 304;

				// Get response data
				if ( responses ) {
					response = ajaxHandleResponses( s, jqXHR, responses );
				}

				// Convert no matter what (that way responseXXX fields are always set)
				response = ajaxConvert( s, response, jqXHR, isSuccess );

				// If successful, handle type chaining
				if ( isSuccess ) {

					// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
					if ( s.ifModified ) {
						modified = jqXHR.getResponseHeader("Last-Modified");
						if ( modified ) {
							jQuery.lastModified[ cacheURL ] = modified;
						}
						modified = jqXHR.getResponseHeader("etag");
						if ( modified ) {
							jQuery.etag[ cacheURL ] = modified;
						}
					}

					// if no content
					if ( status === 204 || s.type === "HEAD" ) {
						statusText = "nocontent";

						// if not modified
					} else if ( status === 304 ) {
						statusText = "notmodified";

						// If we have data, let's convert it
					} else {
						statusText = response.state;
						success = response.data;
						error = response.error;
						isSuccess = !error;
					}
				} else {
					// We extract error from statusText
					// then normalize statusText and status for non-aborts
					error = statusText;
					if ( status || !statusText ) {
						statusText = "error";
						if ( status < 0 ) {
							status = 0;
						}
					}
				}

				// Set data for the fake xhr object
				jqXHR.status = status;
				jqXHR.statusText = ( nativeStatusText || statusText ) + "";

				// Success/Error
				if ( isSuccess ) {
					deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
				} else {
					deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
				}

				// Status-dependent callbacks
				jqXHR.statusCode( statusCode );
				statusCode = undefined;

				if ( fireGlobals ) {
					globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
						[ jqXHR, s, isSuccess ? success : error ] );
				}

				// Complete
				completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );

				if ( fireGlobals ) {
					globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
					// Handle the global AJAX counter
					if ( !( --jQuery.active ) ) {
						jQuery.event.trigger("ajaxStop");
					}
				}
			}

			return jqXHR;
		},

		getJSON: function( url, data, callback ) {
			return jQuery.get( url, data, callback, "json" );
		},

		getScript: function( url, callback ) {
			return jQuery.get( url, undefined, callback, "script" );
		}
	});

	jQuery.each( [ "get", "post" ], function( i, method ) {
		jQuery[ method ] = function( url, data, callback, type ) {
			// shift arguments if data argument was omitted
			if ( jQuery.isFunction( data ) ) {
				type = type || callback;
				callback = data;
				data = undefined;
			}

			return jQuery.ajax({
				url: url,
				type: method,
				dataType: type,
				data: data,
				success: callback
			});
		};
	});

// Attach a bunch of functions for handling common AJAX events
	jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
		jQuery.fn[ type ] = function( fn ) {
			return this.on( type, fn );
		};
	});


	jQuery._evalUrl = function( url ) {
		return jQuery.ajax({
			url: url,
			type: "GET",
			dataType: "script",
			async: false,
			global: false,
			"throws": true
		});
	};


	jQuery.fn.extend({
		wrapAll: function( html ) {
			if ( jQuery.isFunction( html ) ) {
				return this.each(function(i) {
					jQuery(this).wrapAll( html.call(this, i) );
				});
			}

			if ( this[0] ) {
				// The elements to wrap the target around
				var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);

				if ( this[0].parentNode ) {
					wrap.insertBefore( this[0] );
				}

				wrap.map(function() {
					var elem = this;

					while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
						elem = elem.firstChild;
					}

					return elem;
				}).append( this );
			}

			return this;
		},

		wrapInner: function( html ) {
			if ( jQuery.isFunction( html ) ) {
				return this.each(function(i) {
					jQuery(this).wrapInner( html.call(this, i) );
				});
			}

			return this.each(function() {
				var self = jQuery( this ),
					contents = self.contents();

				if ( contents.length ) {
					contents.wrapAll( html );

				} else {
					self.append( html );
				}
			});
		},

		wrap: function( html ) {
			var isFunction = jQuery.isFunction( html );

			return this.each(function(i) {
				jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
			});
		},

		unwrap: function() {
			return this.parent().each(function() {
				if ( !jQuery.nodeName( this, "body" ) ) {
					jQuery( this ).replaceWith( this.childNodes );
				}
			}).end();
		}
	});


	jQuery.expr.filters.hidden = function( elem ) {
		// Support: Opera <= 12.12
		// Opera reports offsetWidths and offsetHeights less than zero on some elements
		return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
			(!support.reliableHiddenOffsets() &&
			((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
	};

	jQuery.expr.filters.visible = function( elem ) {
		return !jQuery.expr.filters.hidden( elem );
	};




	var r20 = /%20/g,
		rbracket = /\[\]$/,
		rCRLF = /\r?\n/g,
		rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
		rsubmittable = /^(?:input|select|textarea|keygen)/i;

	function buildParams( prefix, obj, traditional, add ) {
		var name;

		if ( jQuery.isArray( obj ) ) {
			// Serialize array item.
			jQuery.each( obj, function( i, v ) {
				if ( traditional || rbracket.test( prefix ) ) {
					// Treat each array item as a scalar.
					add( prefix, v );

				} else {
					// Item is non-scalar (array or object), encode its numeric index.
					buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
				}
			});

		} else if ( !traditional && jQuery.type( obj ) === "object" ) {
			// Serialize object item.
			for ( name in obj ) {
				buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
			}

		} else {
			// Serialize scalar item.
			add( prefix, obj );
		}
	}

// Serialize an array of form elements or a set of
// key/values into a query string
	jQuery.param = function( a, traditional ) {
		var prefix,
			s = [],
			add = function( key, value ) {
				// If value is a function, invoke it and return its value
				value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
				s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
			};

		// Set traditional to true for jQuery <= 1.3.2 behavior.
		if ( traditional === undefined ) {
			traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
		}

		// If an array was passed in, assume that it is an array of form elements.
		if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
			// Serialize the form elements
			jQuery.each( a, function() {
				add( this.name, this.value );
			});

		} else {
			// If traditional, encode the "old" way (the way 1.3.2 or older
			// did it), otherwise encode params recursively.
			for ( prefix in a ) {
				buildParams( prefix, a[ prefix ], traditional, add );
			}
		}

		// Return the resulting serialization
		return s.join( "&" ).replace( r20, "+" );
	};

	jQuery.fn.extend({
		serialize: function() {
			return jQuery.param( this.serializeArray() );
		},
		serializeArray: function() {
			return this.map(function() {
				// Can add propHook for "elements" to filter or add form elements
				var elements = jQuery.prop( this, "elements" );
				return elements ? jQuery.makeArray( elements ) : this;
			})
				.filter(function() {
					var type = this.type;
					// Use .is(":disabled") so that fieldset[disabled] works
					return this.name && !jQuery( this ).is( ":disabled" ) &&
						rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
						( this.checked || !rcheckableType.test( type ) );
				})
				.map(function( i, elem ) {
					var val = jQuery( this ).val();

					return val == null ?
						null :
						jQuery.isArray( val ) ?
							jQuery.map( val, function( val ) {
								return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
							}) :
						{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
				}).get();
		}
	});


// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
	jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
		// Support: IE6+
		function() {

			// XHR cannot access local files, always use ActiveX for that case
			return !this.isLocal &&

					// Support: IE7-8
					// oldIE XHR does not support non-RFC2616 methods (#13240)
					// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
					// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
					// Although this check for six methods instead of eight
					// since IE also does not support "trace" and "connect"
				/^(get|post|head|put|delete|options)$/i.test( this.type ) &&

				createStandardXHR() || createActiveXHR();
		} :
		// For all other browsers, use the standard XMLHttpRequest object
		createStandardXHR;

	var xhrId = 0,
		xhrCallbacks = {},
		xhrSupported = jQuery.ajaxSettings.xhr();

// Support: IE<10
// Open requests must be manually aborted on unload (#5280)
	if ( window.ActiveXObject ) {
		jQuery( window ).on( "unload", function() {
			for ( var key in xhrCallbacks ) {
				xhrCallbacks[ key ]( undefined, true );
			}
		});
	}

// Determine support properties
	support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
	xhrSupported = support.ajax = !!xhrSupported;

// Create transport if the browser can provide an xhr
	if ( xhrSupported ) {

		jQuery.ajaxTransport(function( options ) {
			// Cross domain only allowed if supported through XMLHttpRequest
			if ( !options.crossDomain || support.cors ) {

				var callback;

				return {
					send: function( headers, complete ) {
						var i,
							xhr = options.xhr(),
							id = ++xhrId;

						// Open the socket
						xhr.open( options.type, options.url, options.async, options.username, options.password );

						// Apply custom fields if provided
						if ( options.xhrFields ) {
							for ( i in options.xhrFields ) {
								xhr[ i ] = options.xhrFields[ i ];
							}
						}

						// Override mime type if needed
						if ( options.mimeType && xhr.overrideMimeType ) {
							xhr.overrideMimeType( options.mimeType );
						}

						// X-Requested-With header
						// For cross-domain requests, seeing as conditions for a preflight are
						// akin to a jigsaw puzzle, we simply never set it to be sure.
						// (it can always be set on a per-request basis or even using ajaxSetup)
						// For same-domain requests, won't change header if already provided.
						if ( !options.crossDomain && !headers["X-Requested-With"] ) {
							headers["X-Requested-With"] = "XMLHttpRequest";
						}

						// Set headers
						for ( i in headers ) {
							// Support: IE<9
							// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
							// request header to a null-value.
							//
							// To keep consistent with other XHR implementations, cast the value
							// to string and ignore `undefined`.
							if ( headers[ i ] !== undefined ) {
								xhr.setRequestHeader( i, headers[ i ] + "" );
							}
						}

						// Do send the request
						// This may raise an exception which is actually
						// handled in jQuery.ajax (so no try/catch here)
						xhr.send( ( options.hasContent && options.data ) || null );

						// Listener
						callback = function( _, isAbort ) {
							var status, statusText, responses;

							// Was never called and is aborted or complete
							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
								// Clean up
								delete xhrCallbacks[ id ];
								callback = undefined;
								xhr.onreadystatechange = jQuery.noop;

								// Abort manually if needed
								if ( isAbort ) {
									if ( xhr.readyState !== 4 ) {
										xhr.abort();
									}
								} else {
									responses = {};
									status = xhr.status;

									// Support: IE<10
									// Accessing binary-data responseText throws an exception
									// (#11426)
									if ( typeof xhr.responseText === "string" ) {
										responses.text = xhr.responseText;
									}

									// Firefox throws an exception when accessing
									// statusText for faulty cross-domain requests
									try {
										statusText = xhr.statusText;
									} catch( e ) {
										// We normalize with Webkit giving an empty statusText
										statusText = "";
									}

									// Filter status for non standard behaviors

									// If the request is local and we have data: assume a success
									// (success with no data won't get notified, that's the best we
									// can do given current implementations)
									if ( !status && options.isLocal && !options.crossDomain ) {
										status = responses.text ? 200 : 404;
										// IE - #1450: sometimes returns 1223 when it should be 204
									} else if ( status === 1223 ) {
										status = 204;
									}
								}
							}

							// Call complete if needed
							if ( responses ) {
								complete( status, statusText, responses, xhr.getAllResponseHeaders() );
							}
						};

						if ( !options.async ) {
							// if we're in sync mode we fire the callback
							callback();
						} else if ( xhr.readyState === 4 ) {
							// (IE6 & IE7) if it's in cache and has been
							// retrieved directly we need to fire the callback
							setTimeout( callback );
						} else {
							// Add to the list of active xhr callbacks
							xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
						}
					},

					abort: function() {
						if ( callback ) {
							callback( undefined, true );
						}
					}
				};
			}
		});
	}

// Functions to create xhrs
	function createStandardXHR() {
		try {
			return new window.XMLHttpRequest();
		} catch( e ) {}
	}

	function createActiveXHR() {
		try {
			return new window.ActiveXObject( "Microsoft.XMLHTTP" );
		} catch( e ) {}
	}




// Install script dataType
	jQuery.ajaxSetup({
		accepts: {
			script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
		},
		contents: {
			script: /(?:java|ecma)script/
		},
		converters: {
			"text script": function( text ) {
				jQuery.globalEval( text );
				return text;
			}
		}
	});

// Handle cache's special case and global
	jQuery.ajaxPrefilter( "script", function( s ) {
		if ( s.cache === undefined ) {
			s.cache = false;
		}
		if ( s.crossDomain ) {
			s.type = "GET";
			s.global = false;
		}
	});

// Bind script tag hack transport
	jQuery.ajaxTransport( "script", function(s) {

		// This transport only deals with cross domain requests
		if ( s.crossDomain ) {

			var script,
				head = document.head || jQuery("head")[0] || document.documentElement;

			return {

				send: function( _, callback ) {

					script = document.createElement("script");

					script.async = true;

					if ( s.scriptCharset ) {
						script.charset = s.scriptCharset;
					}

					script.src = s.url;

					// Attach handlers for all browsers
					script.onload = script.onreadystatechange = function( _, isAbort ) {

						if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {

							// Handle memory leak in IE
							script.onload = script.onreadystatechange = null;

							// Remove the script
							if ( script.parentNode ) {
								script.parentNode.removeChild( script );
							}

							// Dereference the script
							script = null;

							// Callback if not abort
							if ( !isAbort ) {
								callback( 200, "success" );
							}
						}
					};

					// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
					// Use native DOM manipulation to avoid our domManip AJAX trickery
					head.insertBefore( script, head.firstChild );
				},

				abort: function() {
					if ( script ) {
						script.onload( undefined, true );
					}
				}
			};
		}
	});




	var oldCallbacks = [],
		rjsonp = /(=)\?(?=&|$)|\?\?/;

// Default jsonp settings
	jQuery.ajaxSetup({
		jsonp: "callback",
		jsonpCallback: function() {
			var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
			this[ callback ] = true;
			return callback;
		}
	});

// Detect, normalize options and install callbacks for jsonp requests
	jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

		var callbackName, overwritten, responseContainer,
			jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
					"url" :
				typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
				);

		// Handle iff the expected data type is "jsonp" or we have a parameter to set
		if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {

			// Get callback name, remembering preexisting value associated with it
			callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
				s.jsonpCallback() :
				s.jsonpCallback;

			// Insert callback into url or form data
			if ( jsonProp ) {
				s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
			} else if ( s.jsonp !== false ) {
				s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
			}

			// Use data converter to retrieve json after script execution
			s.converters["script json"] = function() {
				if ( !responseContainer ) {
					jQuery.error( callbackName + " was not called" );
				}
				return responseContainer[ 0 ];
			};

			// force json dataType
			s.dataTypes[ 0 ] = "json";

			// Install callback
			overwritten = window[ callbackName ];
			window[ callbackName ] = function() {
				responseContainer = arguments;
			};

			// Clean-up function (fires after converters)
			jqXHR.always(function() {
				// Restore preexisting value
				window[ callbackName ] = overwritten;

				// Save back as free
				if ( s[ callbackName ] ) {
					// make sure that re-using the options doesn't screw things around
					s.jsonpCallback = originalSettings.jsonpCallback;

					// save the callback name for future use
					oldCallbacks.push( callbackName );
				}

				// Call if it was a function and we have a response
				if ( responseContainer && jQuery.isFunction( overwritten ) ) {
					overwritten( responseContainer[ 0 ] );
				}

				responseContainer = overwritten = undefined;
			});

			// Delegate to script
			return "script";
		}
	});




// data: string of html
// context (optional): If specified, the fragment will be created in this context, defaults to document
// keepScripts (optional): If true, will include scripts passed in the html string
	jQuery.parseHTML = function( data, context, keepScripts ) {
		if ( !data || typeof data !== "string" ) {
			return null;
		}
		if ( typeof context === "boolean" ) {
			keepScripts = context;
			context = false;
		}
		context = context || document;

		var parsed = rsingleTag.exec( data ),
			scripts = !keepScripts && [];

		// Single tag
		if ( parsed ) {
			return [ context.createElement( parsed[1] ) ];
		}

		parsed = jQuery.buildFragment( [ data ], context, scripts );

		if ( scripts && scripts.length ) {
			jQuery( scripts ).remove();
		}

		return jQuery.merge( [], parsed.childNodes );
	};


// Keep a copy of the old load method
	var _load = jQuery.fn.load;

	/**
	 * Load a url into a page
	 */
	jQuery.fn.load = function( url, params, callback ) {
		if ( typeof url !== "string" && _load ) {
			return _load.apply( this, arguments );
		}

		var selector, response, type,
			self = this,
			off = url.indexOf(" ");

		if ( off >= 0 ) {
			selector = jQuery.trim( url.slice( off, url.length ) );
			url = url.slice( 0, off );
		}

		// If it's a function
		if ( jQuery.isFunction( params ) ) {

			// We assume that it's the callback
			callback = params;
			params = undefined;

			// Otherwise, build a param string
		} else if ( params && typeof params === "object" ) {
			type = "POST";
		}

		// If we have elements to modify, make the request
		if ( self.length > 0 ) {
			jQuery.ajax({
				url: url,

				// if "type" variable is undefined, then "GET" method will be used
				type: type,
				dataType: "html",
				data: params
			}).done(function( responseText ) {

				// Save response for use in complete callback
				response = arguments;

				self.html( selector ?

					// If a selector was specified, locate the right elements in a dummy div
					// Exclude scripts to avoid IE 'Permission Denied' errors
					jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :

					// Otherwise use the full result
					responseText );

			}).complete( callback && function( jqXHR, status ) {
				self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
			});
		}

		return this;
	};




	jQuery.expr.filters.animated = function( elem ) {
		return jQuery.grep(jQuery.timers, function( fn ) {
			return elem === fn.elem;
		}).length;
	};





	var docElem = window.document.documentElement;

	/**
	 * Gets a window from an element
	 */
	function getWindow( elem ) {
		return jQuery.isWindow( elem ) ?
			elem :
			elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
				false;
	}

	jQuery.offset = {
		setOffset: function( elem, options, i ) {
			var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
				position = jQuery.css( elem, "position" ),
				curElem = jQuery( elem ),
				props = {};

			// set position first, in-case top/left are set even on static elem
			if ( position === "static" ) {
				elem.style.position = "relative";
			}

			curOffset = curElem.offset();
			curCSSTop = jQuery.css( elem, "top" );
			curCSSLeft = jQuery.css( elem, "left" );
			calculatePosition = ( position === "absolute" || position === "fixed" ) &&
			jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;

			// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
			if ( calculatePosition ) {
				curPosition = curElem.position();
				curTop = curPosition.top;
				curLeft = curPosition.left;
			} else {
				curTop = parseFloat( curCSSTop ) || 0;
				curLeft = parseFloat( curCSSLeft ) || 0;
			}

			if ( jQuery.isFunction( options ) ) {
				options = options.call( elem, i, curOffset );
			}

			if ( options.top != null ) {
				props.top = ( options.top - curOffset.top ) + curTop;
			}
			if ( options.left != null ) {
				props.left = ( options.left - curOffset.left ) + curLeft;
			}

			if ( "using" in options ) {
				options.using.call( elem, props );
			} else {
				curElem.css( props );
			}
		}
	};

	jQuery.fn.extend({
		offset: function( options ) {
			if ( arguments.length ) {
				return options === undefined ?
					this :
					this.each(function( i ) {
						jQuery.offset.setOffset( this, options, i );
					});
			}

			var docElem, win,
				box = { top: 0, left: 0 },
				elem = this[ 0 ],
				doc = elem && elem.ownerDocument;

			if ( !doc ) {
				return;
			}

			docElem = doc.documentElement;

			// Make sure it's not a disconnected DOM node
			if ( !jQuery.contains( docElem, elem ) ) {
				return box;
			}

			// If we don't have gBCR, just use 0,0 rather than error
			// BlackBerry 5, iOS 3 (original iPhone)
			if ( typeof elem.getBoundingClientRect !== strundefined ) {
				box = elem.getBoundingClientRect();
			}
			win = getWindow( doc );
			return {
				top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
				left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
			};
		},

		position: function() {
			if ( !this[ 0 ] ) {
				return;
			}

			var offsetParent, offset,
				parentOffset = { top: 0, left: 0 },
				elem = this[ 0 ];

			// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
			if ( jQuery.css( elem, "position" ) === "fixed" ) {
				// we assume that getBoundingClientRect is available when computed position is fixed
				offset = elem.getBoundingClientRect();
			} else {
				// Get *real* offsetParent
				offsetParent = this.offsetParent();

				// Get correct offsets
				offset = this.offset();
				if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
					parentOffset = offsetParent.offset();
				}

				// Add offsetParent borders
				parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
				parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
			}

			// Subtract parent offsets and element margins
			// note: when an element has margin: auto the offsetLeft and marginLeft
			// are the same in Safari causing offset.left to incorrectly be 0
			return {
				top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
				left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
			};
		},

		offsetParent: function() {
			return this.map(function() {
				var offsetParent = this.offsetParent || docElem;

				while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
					offsetParent = offsetParent.offsetParent;
				}
				return offsetParent || docElem;
			});
		}
	});

// Create scrollLeft and scrollTop methods
	jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
		var top = /Y/.test( prop );

		jQuery.fn[ method ] = function( val ) {
			return access( this, function( elem, method, val ) {
				var win = getWindow( elem );

				if ( val === undefined ) {
					return win ? (prop in win) ? win[ prop ] :
						win.document.documentElement[ method ] :
						elem[ method ];
				}

				if ( win ) {
					win.scrollTo(
						!top ? val : jQuery( win ).scrollLeft(),
						top ? val : jQuery( win ).scrollTop()
					);

				} else {
					elem[ method ] = val;
				}
			}, method, val, arguments.length, null );
		};
	});

// Add the top/left cssHooks using jQuery.fn.position
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
// getComputedStyle returns percent when specified for top/left/bottom/right
// rather than make the css module depend on the offset module, we just check for it here
	jQuery.each( [ "top", "left" ], function( i, prop ) {
		jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
			function( elem, computed ) {
				if ( computed ) {
					computed = curCSS( elem, prop );
					// if curCSS returns percentage, fallback to offset
					return rnumnonpx.test( computed ) ?
					jQuery( elem ).position()[ prop ] + "px" :
						computed;
				}
			}
		);
	});


// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
	jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
		jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
			// margin is only for outerHeight, outerWidth
			jQuery.fn[ funcName ] = function( margin, value ) {
				var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
					extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );

				return access( this, function( elem, type, value ) {
					var doc;

					if ( jQuery.isWindow( elem ) ) {
						// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
						// isn't a whole lot we can do. See pull request at this URL for discussion:
						// https://github.com/jquery/jquery/pull/764
						return elem.document.documentElement[ "client" + name ];
					}

					// Get document width or height
					if ( elem.nodeType === 9 ) {
						doc = elem.documentElement;

						// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
						// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
						return Math.max(
							elem.body[ "scroll" + name ], doc[ "scroll" + name ],
							elem.body[ "offset" + name ], doc[ "offset" + name ],
							doc[ "client" + name ]
						);
					}

					return value === undefined ?
						// Get width or height on the element, requesting but not forcing parseFloat
						jQuery.css( elem, type, extra ) :

						// Set width or height on the element
						jQuery.style( elem, type, value, extra );
				}, type, chainable ? margin : undefined, chainable, null );
			};
		});
	});


// The number of elements contained in the matched element set
	jQuery.fn.size = function() {
		return this.length;
	};

	jQuery.fn.andSelf = jQuery.fn.addBack;




// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.

// Note that for maximum portability, libraries that are not jQuery should
// declare themselves as anonymous modules, and avoid setting a global if an
// AMD loader is present. jQuery is a special case. For more information, see
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon

	if ( typeof define === "function" && define.amd ) {
		define( "jquery", [], function() {
			return jQuery;
		});
	}




	var
	// Map over jQuery in case of overwrite
		_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
		_$ = window.$;

	jQuery.noConflict = function( deep ) {
		if ( window.$ === jQuery ) {
			window.$ = _$;
		}

		if ( deep && window.jQuery === jQuery ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	};

// Expose jQuery and $ identifiers, even in
// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
	if ( typeof noGlobal === strundefined ) {
		window.jQuery = window.$ = jQuery;
	}




	return jQuery;

}));
;(function () {
	'use strict';

	/**
	 * @preserve FastClick: polyfill to remove click delays on browsers with touch UIs.
	 *
	 * @codingstandard ftlabs-jsv2
	 * @copyright The Financial Times Limited [All Rights Reserved]
	 * @license MIT License (see LICENSE.txt)
	 */
/*jslint browser:true, node:true*/
	/*global define, Event, Node*/


	/**
	 * Instantiate fast-clicking listeners on the specified layer.
	 *
	 * @constructor
	 * @param {Element} layer The layer to listen on
	 * @param {Object} [options={}] The options to override the defaults
	 */
	function FastClick(layer, options) {
		var oldOnClick;

		options = options || {};

		/**
		 * Whether a click is currently being tracked.
		 *
		 * @type boolean
		 */
		this.trackingClick = false;


		/**
		 * Timestamp for when click tracking started.
		 *
		 * @type number
		 */
		this.trackingClickStart = 0;


		/**
		 * The element being tracked for a click.
		 *
		 * @type EventTarget
		 */
		this.targetElement = null;


		/**
		 * X-coordinate of touch start event.
		 *
		 * @type number
		 */
		this.touchStartX = 0;


		/**
		 * Y-coordinate of touch start event.
		 *
		 * @type number
		 */
		this.touchStartY = 0;


		/**
		 * ID of the last touch, retrieved from Touch.identifier.
		 *
		 * @type number
		 */
		this.lastTouchIdentifier = 0;


		/**
		 * Touchmove boundary, beyond which a click will be cancelled.
		 *
		 * @type number
		 */
		this.touchBoundary = options.touchBoundary || 10;


		/**
		 * The FastClick layer.
		 *
		 * @type Element
		 */
		this.layer = layer;

		/**
		 * The minimum time between tap(touchstart and touchend) events
		 *
		 * @type number
		 */
		this.tapDelay = options.tapDelay || 200;

		/**
		 * The maximum time for a tap
		 *
		 * @type number
		 */
		this.tapTimeout = options.tapTimeout || 700;

		if (FastClick.notNeeded(layer)) {
			return;
		}

		// Some old versions of Android don't have Function.prototype.bind
		function bind(method, context) {
			return function() { return method.apply(context, arguments); };
		}


		var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel'];
		var context = this;
		for (var i = 0, l = methods.length; i < l; i++) {
			context[methods[i]] = bind(context[methods[i]], context);
		}

		// Set up event handlers as required
		if (deviceIsAndroid) {
			layer.addEventListener('mouseover', this.onMouse, true);
			layer.addEventListener('mousedown', this.onMouse, true);
			layer.addEventListener('mouseup', this.onMouse, true);
		}

		layer.addEventListener('click', this.onClick, true);
		layer.addEventListener('touchstart', this.onTouchStart, false);
		layer.addEventListener('touchmove', this.onTouchMove, false);
		layer.addEventListener('touchend', this.onTouchEnd, false);
		layer.addEventListener('touchcancel', this.onTouchCancel, false);

		// Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
		// which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick
		// layer when they are cancelled.
		if (!Event.prototype.stopImmediatePropagation) {
			layer.removeEventListener = function(type, callback, capture) {
				var rmv = Node.prototype.removeEventListener;
				if (type === 'click') {
					rmv.call(layer, type, callback.hijacked || callback, capture);
				} else {
					rmv.call(layer, type, callback, capture);
				}
			};

			layer.addEventListener = function(type, callback, capture) {
				var adv = Node.prototype.addEventListener;
				if (type === 'click') {
					adv.call(layer, type, callback.hijacked || (callback.hijacked = function(event) {
						if (!event.propagationStopped) {
							callback(event);
						}
					}), capture);
				} else {
					adv.call(layer, type, callback, capture);
				}
			};
		}

		// If a handler is already declared in the element's onclick attribute, it will be fired before
		// FastClick's onClick handler. Fix this by pulling out the user-defined handler function and
		// adding it as listener.
		if (typeof layer.onclick === 'function') {

			// Android browser on at least 3.2 requires a new reference to the function in layer.onclick
			// - the old one won't work if passed to addEventListener directly.
			oldOnClick = layer.onclick;
			layer.addEventListener('click', function(event) {
				oldOnClick(event);
			}, false);
			layer.onclick = null;
		}
	}

	/**
	 * Windows Phone 8.1 fakes user agent string to look like Android and iPhone.
	 *
	 * @type boolean
	 */
	var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0;

	/**
	 * Android requires exceptions.
	 *
	 * @type boolean
	 */
	var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone;


	/**
	 * iOS requires exceptions.
	 *
	 * @type boolean
	 */
	var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone;


	/**
	 * iOS 4 requires an exception for select elements.
	 *
	 * @type boolean
	 */
	var deviceIsIOS4 = deviceIsIOS && (/OS 4_\d(_\d)?/).test(navigator.userAgent);


	/**
	 * iOS 6.0-7.* requires the target element to be manually derived
	 *
	 * @type boolean
	 */
	var deviceIsIOSWithBadTarget = deviceIsIOS && (/OS [6-7]_\d/).test(navigator.userAgent);

	/**
	 * BlackBerry requires exceptions.
	 *
	 * @type boolean
	 */
	var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0;

	/**
	 * Determine whether a given element requires a native click.
	 *
	 * @param {EventTarget|Element} target Target DOM element
	 * @returns {boolean} Returns true if the element needs a native click
	 */
	FastClick.prototype.needsClick = function(target) {
		switch (target.nodeName.toLowerCase()) {

			// Don't send a synthetic click to disabled inputs (issue #62)
			case 'button':
			case 'select':
			case 'textarea':
				if (target.disabled) {
					return true;
				}

				break;
			case 'input':

				// File inputs need real clicks on iOS 6 due to a browser bug (issue #68)
				if ((deviceIsIOS && target.type === 'file') || target.disabled) {
					return true;
				}

				break;
			case 'label':
			case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames
			case 'video':
				return true;
		}

		return (/\bneedsclick\b/).test(target.className);
	};


	/**
	 * Determine whether a given element requires a call to focus to simulate click into element.
	 *
	 * @param {EventTarget|Element} target Target DOM element
	 * @returns {boolean} Returns true if the element requires a call to focus to simulate native click.
	 */
	FastClick.prototype.needsFocus = function(target) {
		switch (target.nodeName.toLowerCase()) {
			case 'textarea':
				return true;
			case 'select':
				return !deviceIsAndroid;
			case 'input':
				switch (target.type) {
					case 'button':
					case 'checkbox':
					case 'file':
					case 'image':
					case 'radio':
					case 'submit':
						return false;
				}

				// No point in attempting to focus disabled inputs
				return !target.disabled && !target.readOnly;
			default:
				return (/\bneedsfocus\b/).test(target.className);
		}
	};


	/**
	 * Send a click event to the specified element.
	 *
	 * @param {EventTarget|Element} targetElement
	 * @param {Event} event
	 */
	FastClick.prototype.sendClick = function(targetElement, event) {
		var clickEvent, touch;

		// On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24)
		if (document.activeElement && document.activeElement !== targetElement) {
			document.activeElement.blur();
		}

		touch = event.changedTouches[0];

		// Synthesise a click event, with an extra attribute so it can be tracked
		clickEvent = document.createEvent('MouseEvents');
		clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
		clickEvent.forwardedTouchEvent = true;
		targetElement.dispatchEvent(clickEvent);
	};

	FastClick.prototype.determineEventType = function(targetElement) {

		//Issue #159: Android Chrome Select Box does not open with a synthetic click event
		if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') {
			return 'mousedown';
		}

		return 'click';
	};


	/**
	 * @param {EventTarget|Element} targetElement
	 */
	FastClick.prototype.focus = function(targetElement) {
		var length;

		// Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724.
		if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month') {
			length = targetElement.value.length;
			targetElement.setSelectionRange(length, length);
		} else {
			targetElement.focus();
		}
	};


	/**
	 * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it.
	 *
	 * @param {EventTarget|Element} targetElement
	 */
	FastClick.prototype.updateScrollParent = function(targetElement) {
		var scrollParent, parentElement;

		scrollParent = targetElement.fastClickScrollParent;

		// Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the
		// target element was moved to another parent.
		if (!scrollParent || !scrollParent.contains(targetElement)) {
			parentElement = targetElement;
			do {
				if (parentElement.scrollHeight > parentElement.offsetHeight) {
					scrollParent = parentElement;
					targetElement.fastClickScrollParent = parentElement;
					break;
				}

				parentElement = parentElement.parentElement;
			} while (parentElement);
		}

		// Always update the scroll top tracker if possible.
		if (scrollParent) {
			scrollParent.fastClickLastScrollTop = scrollParent.scrollTop;
		}
	};


	/**
	 * @param {EventTarget} targetElement
	 * @returns {Element|EventTarget}
	 */
	FastClick.prototype.getTargetElementFromEventTarget = function(eventTarget) {

		// On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node.
		if (eventTarget.nodeType === Node.TEXT_NODE) {
			return eventTarget.parentNode;
		}

		return eventTarget;
	};


	/**
	 * On touch start, record the position and scroll offset.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onTouchStart = function(event) {
		var targetElement, touch, selection;

		// Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111).
		if (event.targetTouches.length > 1) {
			return true;
		}

		targetElement = this.getTargetElementFromEventTarget(event.target);
		touch = event.targetTouches[0];

		if (deviceIsIOS) {

			// Only trusted events will deselect text on iOS (issue #49)
			selection = window.getSelection();
			if (selection.rangeCount && !selection.isCollapsed) {
				return true;
			}

			if (!deviceIsIOS4) {

				// Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23):
				// when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched
				// with the same identifier as the touch event that previously triggered the click that triggered the alert.
				// Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an
				// immediately preceeding touch event (issue #52), so this fix is unavailable on that platform.
				// Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string,
				// which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long,
				// random integers, it's safe to to continue if the identifier is 0 here.
				if (touch.identifier && touch.identifier === this.lastTouchIdentifier) {
					event.preventDefault();
					return false;
				}

				this.lastTouchIdentifier = touch.identifier;

				// If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and:
				// 1) the user does a fling scroll on the scrollable layer
				// 2) the user stops the fling scroll with another tap
				// then the event.target of the last 'touchend' event will be the element that was under the user's finger
				// when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check
				// is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42).
				this.updateScrollParent(targetElement);
			}
		}

		this.trackingClick = true;
		this.trackingClickStart = event.timeStamp;
		this.targetElement = targetElement;

		this.touchStartX = touch.pageX;
		this.touchStartY = touch.pageY;

		// Prevent phantom clicks on fast double-tap (issue #36)
		if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
			event.preventDefault();
		}

		return true;
	};


	/**
	 * Based on a touchmove event object, check whether the touch has moved past a boundary since it started.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.touchHasMoved = function(event) {
		var touch = event.changedTouches[0], boundary = this.touchBoundary;

		if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) {
			return true;
		}

		return false;
	};


	/**
	 * Update the last position.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onTouchMove = function(event) {
		if (!this.trackingClick) {
			return true;
		}

		// If the touch has moved, cancel the click tracking
		if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) {
			this.trackingClick = false;
			this.targetElement = null;
		}

		return true;
	};


	/**
	 * Attempt to find the labelled control for the given label element.
	 *
	 * @param {EventTarget|HTMLLabelElement} labelElement
	 * @returns {Element|null}
	 */
	FastClick.prototype.findControl = function(labelElement) {

		// Fast path for newer browsers supporting the HTML5 control attribute
		if (labelElement.control !== undefined) {
			return labelElement.control;
		}

		// All browsers under test that support touch events also support the HTML5 htmlFor attribute
		if (labelElement.htmlFor) {
			return document.getElementById(labelElement.htmlFor);
		}

		// If no for attribute exists, attempt to retrieve the first labellable descendant element
		// the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label
		return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea');
	};


	/**
	 * On touch end, determine whether to send a click event at once.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onTouchEnd = function(event) {
		var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement;

		if (!this.trackingClick) {
			return true;
		}

		// Prevent phantom clicks on fast double-tap (issue #36)
		if ((event.timeStamp - this.lastClickTime) < this.tapDelay) {
			this.cancelNextClick = true;
			return true;
		}

		if ((event.timeStamp - this.trackingClickStart) > this.tapTimeout) {
			return true;
		}

		// Reset to prevent wrong click cancel on input (issue #156).
		this.cancelNextClick = false;

		this.lastClickTime = event.timeStamp;

		trackingClickStart = this.trackingClickStart;
		this.trackingClick = false;
		this.trackingClickStart = 0;

		// On some iOS devices, the targetElement supplied with the event is invalid if the layer
		// is performing a transition or scroll, and has to be re-detected manually. Note that
		// for this to function correctly, it must be called *after* the event target is checked!
		// See issue #57; also filed as rdar://13048589 .
		if (deviceIsIOSWithBadTarget) {
			touch = event.changedTouches[0];

			// In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null
			targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement;
			targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent;
		}

		targetTagName = targetElement.tagName.toLowerCase();
		if (targetTagName === 'label') {
			forElement = this.findControl(targetElement);
			if (forElement) {
				this.focus(targetElement);
				if (deviceIsAndroid) {
					return false;
				}

				targetElement = forElement;
			}
		} else if (this.needsFocus(targetElement)) {

			// Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through.
			// Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37).
			if ((event.timeStamp - trackingClickStart) > 100 || (deviceIsIOS && window.top !== window && targetTagName === 'input')) {
				this.targetElement = null;
				return false;
			}

			this.focus(targetElement);
			this.sendClick(targetElement, event);

			// Select elements need the event to go through on iOS 4, otherwise the selector menu won't open.
			// Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others)
			if (!deviceIsIOS || targetTagName !== 'select') {
				this.targetElement = null;
				event.preventDefault();
			}

			return false;
		}

		if (deviceIsIOS && !deviceIsIOS4) {

			// Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled
			// and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42).
			scrollParent = targetElement.fastClickScrollParent;
			if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) {
				return true;
			}
		}

		// Prevent the actual click from going though - unless the target node is marked as requiring
		// real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted.
		if (!this.needsClick(targetElement)) {
			event.preventDefault();
			this.sendClick(targetElement, event);
		}

		return false;
	};


	/**
	 * On touch cancel, stop tracking the click.
	 *
	 * @returns {void}
	 */
	FastClick.prototype.onTouchCancel = function() {
		this.trackingClick = false;
		this.targetElement = null;
	};


	/**
	 * Determine mouse events which should be permitted.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onMouse = function(event) {

		// If a target element was never set (because a touch event was never fired) allow the event
		if (!this.targetElement) {
			return true;
		}

		if (event.forwardedTouchEvent) {
			return true;
		}

		// Programmatically generated events targeting a specific element should be permitted
		if (!event.cancelable) {
			return true;
		}

		// Derive and check the target element to see whether the mouse event needs to be permitted;
		// unless explicitly enabled, prevent non-touch click events from triggering actions,
		// to prevent ghost/doubleclicks.
		if (!this.needsClick(this.targetElement) || this.cancelNextClick) {

			// Prevent any user-added listeners declared on FastClick element from being fired.
			if (event.stopImmediatePropagation) {
				event.stopImmediatePropagation();
			} else {

				// Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2)
				event.propagationStopped = true;
			}

			// Cancel the event
			event.stopPropagation();
			event.preventDefault();

			return false;
		}

		// If the mouse event is permitted, return true for the action to go through.
		return true;
	};


	/**
	 * On actual clicks, determine whether this is a touch-generated click, a click action occurring
	 * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or
	 * an actual click which should be permitted.
	 *
	 * @param {Event} event
	 * @returns {boolean}
	 */
	FastClick.prototype.onClick = function(event) {
		var permitted;

		// It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early.
		if (this.trackingClick) {
			this.targetElement = null;
			this.trackingClick = false;
			return true;
		}

		// Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target.
		if (event.target.type === 'submit' && event.detail === 0) {
			return true;
		}

		permitted = this.onMouse(event);

		// Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through.
		if (!permitted) {
			this.targetElement = null;
		}

		// If clicks are permitted, return true for the action to go through.
		return permitted;
	};


	/**
	 * Remove all FastClick's event listeners.
	 *
	 * @returns {void}
	 */
	FastClick.prototype.destroy = function() {
		var layer = this.layer;

		if (deviceIsAndroid) {
			layer.removeEventListener('mouseover', this.onMouse, true);
			layer.removeEventListener('mousedown', this.onMouse, true);
			layer.removeEventListener('mouseup', this.onMouse, true);
		}

		layer.removeEventListener('click', this.onClick, true);
		layer.removeEventListener('touchstart', this.onTouchStart, false);
		layer.removeEventListener('touchmove', this.onTouchMove, false);
		layer.removeEventListener('touchend', this.onTouchEnd, false);
		layer.removeEventListener('touchcancel', this.onTouchCancel, false);
	};


	/**
	 * Check whether FastClick is needed.
	 *
	 * @param {Element} layer The layer to listen on
	 */
	FastClick.notNeeded = function(layer) {
		var metaViewport;
		var chromeVersion;
		var blackberryVersion;
		var firefoxVersion;

		// Devices that don't support touch don't need FastClick
		if (typeof window.ontouchstart === 'undefined') {
			return true;
		}

		// Chrome version - zero for other browsers
		chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];

		if (chromeVersion) {

			if (deviceIsAndroid) {
				metaViewport = document.querySelector('meta[name=viewport]');

				if (metaViewport) {
					// Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89)
					if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
						return true;
					}
					// Chrome 32 and above with width=device-width or less don't need FastClick
					if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) {
						return true;
					}
				}

				// Chrome desktop doesn't need FastClick (issue #15)
			} else {
				return true;
			}
		}

		if (deviceIsBlackBerry10) {
			blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/);

			// BlackBerry 10.3+ does not require Fastclick library.
			// https://github.com/ftlabs/fastclick/issues/251
			if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) {
				metaViewport = document.querySelector('meta[name=viewport]');

				if (metaViewport) {
					// user-scalable=no eliminates click delay.
					if (metaViewport.content.indexOf('user-scalable=no') !== -1) {
						return true;
					}
					// width=device-width (or less than device-width) eliminates click delay.
					if (document.documentElement.scrollWidth <= window.outerWidth) {
						return true;
					}
				}
			}
		}

		// IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97)
		if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') {
			return true;
		}

		// Firefox version - zero for other browsers
		firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [,0])[1];

		if (firefoxVersion >= 27) {
			// Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896

			metaViewport = document.querySelector('meta[name=viewport]');
			if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) {
				return true;
			}
		}

		// IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version
		// http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx
		if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') {
			return true;
		}

		return false;
	};


	/**
	 * Factory method for creating a FastClick object
	 *
	 * @param {Element} layer The layer to listen on
	 * @param {Object} [options={}] The options to override the defaults
	 */
	FastClick.attach = function(layer, options) {
		return new FastClick(layer, options);
	};


	if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {

		// AMD. Register as an anonymous module.
		define(function() {
			return FastClick;
		});
	} else if (typeof module !== 'undefined' && module.exports) {
		module.exports = FastClick.attach;
		module.exports.FastClick = FastClick;
	} else {
		window.FastClick = FastClick;
	}
}());
var BB = BB || {};

(function ($) {

BB.Mobile = {
	
	isAndroid	: false,
	isBlackBerry: false,
	isiOS		: false,
	isMobile	: false,
	isTablet	: false,
	version		: '0',
	hasTouch	: 'ontouchstart' in window,
	eClick		: 'click',
	
	bodyClass	: '',
	
	init: function () {
		var bodyClass = '',
			UA = navigator.userAgent;
		this.isiOS = (/iPad|iPhone|iPod/).test(UA) ? true : false;
		this.isAndroid = !this.isiOS && (/Android/).test(UA) ? true : false;
		this.isBlackBerry = !this.isiOS && !this.isAndroid && (/BlackBerry|BB10/).test(UA) ? true : false;
		this.isMobile = this.isiOS || this.isAndroid || this.isBlackBerry;
		this.isTablet = (/iPad/).test(UA) ? true : false;
		
		if (this.hasTouch) {
			this.eClick = 'fclick';
			bodyClass += ' touch';
		} else {
			bodyClass += ' mouse';
		}
		
		if (this.isAndroid) {
			this.version = (UA.match(/Android (\d+(\.\d+)?(\.\d+)?);/) || [])[1] || '0';
			bodyClass += ' android android' + (this.version.split('.')[0]);
		} else if (this.isiOS) {
			this.version = ((UA.match(/OS (\d+(_\d+)?(_\d+)?)/) || [])[1] || '0').replace(/_/g, '.');
			bodyClass += ' iOS iOS' + (this.version.split('.')[0]);
		}
		

		if (this.isMobile && !this.isTablet) {
			bodyClass += ' mobile';
		} else {
			bodyClass += ' standard';
		}
		
		this.bodyClass = bodyClass;
		$(this.setBodyClass);
	},
	
	setBodyClass: function () {
		$(document.body).removeClass('standard').addClass(BB.Mobile.bodyClass);
	},
	
	// Vergleicht Versionsnummern
	cmpVersion: function (a, b) {
		var i, l, d;
		
		a = a.split('.');
		b = b.split('.');
		l = Math.min(a.length, b.length);

		for (i=0; i<l; i++) {
			d = parseInt(a[i], 10) - parseInt(b[i], 10);
			if (d !== 0) {
				return d;
			}
		}
		
		return a.length - b.length;
	}
};
BB.Mobile.init();
})(jQuery);
(function(window, factory) {
	var lazySizes = factory(window, window.document);
	window.lazySizes = lazySizes;
	if(typeof module == 'object' && module.exports){
		module.exports = lazySizes;
	} else if (typeof define == 'function' && define.amd) {
		define(lazySizes);
	}
}(window, function(window, document) {
	'use strict';
	/*jshint eqnull:true */
	if(!document.getElementsByClassName){return;}

	var lazySizesConfig;

	var docElem = document.documentElement;

	var addEventListener = window.addEventListener;

	var setTimeout = window.setTimeout;

	var rAF = window.requestAnimationFrame || setTimeout;

	var regPicture = /^picture$/i;

	var loadEvents = ['load', 'error', 'lazyincluded', '_lazyloaded'];

	var hasClass = function(ele, cls) {
		var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
		return ele.className.match(reg) && reg;
	};

	var addClass = function(ele, cls) {
		if (!hasClass(ele, cls)){
			ele.className += ' '+cls;
		}
	};

	var removeClass = function(ele, cls) {
		var reg;
		if ((reg = hasClass(ele,cls))) {
			ele.className = ele.className.replace(reg, ' ');
		}
	};

	var addRemoveLoadEvents = function(dom, fn, add){
		var action = add ? 'addEventListener' : 'removeEventListener';
		if(add){
			addRemoveLoadEvents(dom, fn);
		}
		loadEvents.forEach(function(evt){
			dom[action](evt, fn);
		});
	};

	var triggerEvent = function(elem, name, detail, noBubbles, noCancelable){
		var event = document.createEvent('CustomEvent');

		event.initCustomEvent(name, !noBubbles, !noCancelable, detail);

		event.details =  event.detail;

		elem.dispatchEvent(event);
		return event;
	};

	var updatePolyfill = function (el, full){
		var polyfill;
		if(!window.HTMLPictureElement){
			if( ( polyfill = (window.picturefill || window.respimage || lazySizesConfig.pf) ) ){
				polyfill({reevaluate: true, reparse: true, elements: [el]});
			} else if(full && full.src){
				el.src = full.src;
			}
		}
	};

	var getCSS = function (elem, style){
		return getComputedStyle(elem, null)[style];
	};

	var getWidth = function(elem, parent, width){
		width = width || elem.offsetWidth;

		while(width < lazySizesConfig.minSize && parent && !elem._lazysizesWidth){
			width =  parent.offsetWidth;
			parent = parent.parentNode;
		}

		return width;
	};

	var throttle = function(fn){
		var running;
		var lastTime = 0;
		var run = function(){
			running = false;
			lastTime = Date.now();
			fn();
		};
		var afterAF = function(){
			setTimeout(run);
		};
		var getAF = function(){
			rAF(afterAF);
		};

		return function(){
			if(running){
				return;
			}
			var delay = lazySizesConfig.throttle - (Date.now() - lastTime);

			running =  true;

			if(delay < 9){
				delay = 9;
			}
			setTimeout(getAF, delay);
		};
	};

	var loader = (function(){
		var lazyloadElems, preloadElems, isCompleted, resetPreloadingTimer, loadMode;

		var eLvW, elvH, eLtop, eLleft, eLright, eLbottom;

		var defaultExpand, preloadExpand;

		var regImg = /^img$/i;
		var regIframe = /^iframe$/i;

		var supportScroll = ('onscroll' in window) && !(/glebot/.test(navigator.userAgent));

		var shrinkExpand = 0;
		var currentExpand = 0;
		var lowRuns = 0;

		var isLoading = 0;
		var checkElementsIndex = 0;

		var resetPreloading = function(e){
			isLoading--;
			if(e && e.target){
				addRemoveLoadEvents(e.target, resetPreloading);
			}

			if(!e || isLoading < 0 || !e.target){
				isLoading = 0;
			}
		};

		var isNestedVisible = function(elem, elemExpand){
			var outerRect;
			var parent = elem;
			var visible = getCSS(elem, 'visibility') != 'hidden';

			eLtop -= elemExpand;
			eLbottom += elemExpand;
			eLleft -= elemExpand;
			eLright += elemExpand;

			while(visible && (parent = parent.offsetParent)){
				visible = ((getCSS(parent, 'opacity') || 1) > 0);

				if(visible && getCSS(parent, 'overflow') != 'visible'){
					outerRect = parent.getBoundingClientRect();
					visible = eLright > outerRect.left &&
					eLleft < outerRect.right &&
					eLbottom > outerRect.top - 1 &&
					eLtop < outerRect.bottom + 1
					;
				}
			}

			return visible;
		};

		var checkElements = function() {
			var eLlen, i, start, rect, autoLoadElem, loadedSomething, elemExpand, elemNegativeExpand, elemExpandVal, beforeExpandVal;

			if((loadMode = lazySizesConfig.loadMode) && isLoading < 8 && (eLlen = lazyloadElems.length)){

				start = Date.now();
				i = checkElementsIndex;

				lowRuns++;

				if(currentExpand < preloadExpand && isLoading < 1 && lowRuns > 4 && loadMode > 2){
					currentExpand = preloadExpand;
					lowRuns = 0;
				} else if(currentExpand != defaultExpand && loadMode > 1 && lowRuns > 3){
					currentExpand = defaultExpand;
				} else {
					currentExpand = shrinkExpand;
				}

				for(; i < eLlen; i++, checkElementsIndex++){

					if(!lazyloadElems[i] || lazyloadElems[i]._lazyRace){continue;}

					if(!supportScroll){unveilElement(lazyloadElems[i]);continue;}

					if(!(elemExpandVal = lazyloadElems[i].getAttribute('data-expand')) || !(elemExpand = elemExpandVal * 1)){
						elemExpand = currentExpand;
					}

					if(beforeExpandVal !== elemExpand){
						eLvW = innerWidth + elemExpand;
						elvH = innerHeight + elemExpand;
						elemNegativeExpand = elemExpand * -1;
						beforeExpandVal = elemExpand;
					}

					rect = lazyloadElems[i].getBoundingClientRect();

					if ((eLbottom = rect.bottom) >= elemNegativeExpand &&
						(eLtop = rect.top) <= elvH &&
						(eLright = rect.right) >= elemNegativeExpand &&
						(eLleft = rect.left) <= eLvW &&
						(eLbottom || eLright || eLleft || eLtop) &&
						((isCompleted && isLoading < 3 && lowRuns < 4 && !elemExpandVal && loadMode > 2) || isNestedVisible(lazyloadElems[i], elemExpand))){
						unveilElement(lazyloadElems[i], false, rect.width);
						checkElementsIndex--;
						start++;
						loadedSomething = true;
					} else  {
						if(lowRuns && Date.now() - start > 3){
							checkElementsIndex++;
							throttledCheckElements();
							return;
						}
						if(!loadedSomething && isCompleted && !autoLoadElem &&
							isLoading < 3 && lowRuns < 4 && loadMode > 2 &&
							(preloadElems[0] || lazySizesConfig.preloadAfterLoad) &&
							(preloadElems[0] || (!elemExpandVal && ((eLbottom || eLright || eLleft || eLtop) || lazyloadElems[i].getAttribute(lazySizesConfig.sizesAttr) != 'auto')))){
							autoLoadElem = preloadElems[0] || lazyloadElems[i];
						}
					}
				}

				if(autoLoadElem && !loadedSomething){
					unveilElement(autoLoadElem);
				}
			}
			checkElementsIndex = 0;
		};

		var throttledCheckElements = throttle(checkElements);

		var switchLoadingClass = function(e){
			addClass(e.target, lazySizesConfig.loadedClass);
			removeClass(e.target, lazySizesConfig.loadingClass);
			addRemoveLoadEvents(e.target, switchLoadingClass);
		};

		var changeIframeSrc = function(elem, src){
			try {
				elem.contentWindow.location.replace(src);
			} catch(e){
				elem.setAttribute('src', src);
			}
		};

		var unveilElement = function (elem, force, width){
			var sources, i, len, sourceSrcset, src, srcset, parent, isPicture, event, firesLoad, customMedia;

			var curSrc = elem.currentSrc || elem.src;
			var isImg = regImg.test(elem.nodeName);

			//allow using sizes="auto", but don't use. it's invalid. Use data-sizes="auto" or a valid value for sizes instead (i.e.: sizes="80vw")
			var sizes = elem.getAttribute(lazySizesConfig.sizesAttr) || elem.getAttribute('sizes');
			var isAuto = sizes == 'auto';

			if( (isAuto || !isCompleted) && isImg && curSrc && !elem.complete && !hasClass(elem, lazySizesConfig.errorClass)){return;}

			elem._lazyRace = true;

			rAF(function lazyUnveil(){

				if(elem._lazyRace){
					delete elem._lazyRace;
				}

				removeClass(elem, lazySizesConfig.lazyClass);

				if(!(event = triggerEvent(elem, 'lazybeforeunveil', {force: !!force})).defaultPrevented){

					if(sizes){
						if(isAuto){
							autoSizer.updateElem(elem, true, width);
							addClass(elem, lazySizesConfig.autosizesClass);
						} else {
							elem.setAttribute('sizes', sizes);
						}
					}

					srcset = elem.getAttribute(lazySizesConfig.srcsetAttr);
					src = elem.getAttribute(lazySizesConfig.srcAttr);

					if(isImg) {
						parent = elem.parentNode;
						isPicture = regPicture.test(parent.nodeName || '');
					}

					firesLoad = event.detail.firesLoad || (('src' in elem) && (srcset || src || isPicture));

					if(firesLoad){
						isLoading++;
						addRemoveLoadEvents(elem, resetPreloading, true);
						clearTimeout(resetPreloadingTimer);
						resetPreloadingTimer = setTimeout(resetPreloading, 2500);

						addClass(elem, lazySizesConfig.loadingClass);
						addRemoveLoadEvents(elem, switchLoadingClass, true);
					}

					if(isPicture){
						sources = parent.getElementsByTagName('source');
						for(i = 0, len = sources.length; i < len; i++){
							if( (customMedia = lazySizesConfig.customMedia[sources[i].getAttribute('data-media') || sources[i].getAttribute('media')]) ){
								sources[i].setAttribute('media', customMedia);
							}
							sourceSrcset = sources[i].getAttribute(lazySizesConfig.srcsetAttr);
							if(sourceSrcset){
								sources[i].setAttribute('srcset', sourceSrcset);
							}
						}
					}

					if(srcset){
						elem.setAttribute('srcset', srcset);
					} else if(src){
						if(regIframe.test(elem.nodeName)){
							changeIframeSrc(elem, src);
						} else {
							elem.setAttribute('src', src);
						}
					}

					if(srcset || isPicture){
						updatePolyfill(elem, {src: src});
					}
				}

				//remove curSrc == (elem.currentSrc || elem.src) in July/August 2015 it's a workaround for FF. see: https://bugzilla.mozilla.org/show_bug.cgi?id=608261
				if( !firesLoad || (elem.complete && curSrc == (elem.currentSrc || elem.src)) ){
					if(firesLoad){
						resetPreloading(event);
					}
					switchLoadingClass(event);
				}

				elem = null;
			});
		};

		var onload = function(){
			var scrollTimer;
			var afterScroll = function(){
				lazySizesConfig.loadMode = 3;
				throttledCheckElements();
			};

			isCompleted = true;
			lowRuns += 8;

			lazySizesConfig.loadMode = 3;

			addEventListener('scroll', function(){
				if(lazySizesConfig.loadMode == 3){
					lazySizesConfig.loadMode = 2;
				}
				clearTimeout(scrollTimer);
				scrollTimer = setTimeout(afterScroll, 99);
			}, true);
		};

		return {
			_: function(){

				lazyloadElems = document.getElementsByClassName(lazySizesConfig.lazyClass);
				preloadElems = document.getElementsByClassName(lazySizesConfig.lazyClass + ' ' + lazySizesConfig.preloadClass);

				defaultExpand = lazySizesConfig.expand;
				preloadExpand = Math.round(defaultExpand * lazySizesConfig.expFactor);

				addEventListener('scroll', throttledCheckElements, true);

				addEventListener('resize', throttledCheckElements, true);

				if(window.MutationObserver){
					new MutationObserver( throttledCheckElements ).observe( docElem, {childList: true, subtree: true, attributes: true} );
				} else {
					docElem.addEventListener('DOMNodeInserted', throttledCheckElements, true);
					docElem.addEventListener('DOMAttrModified', throttledCheckElements, true);
					setInterval(throttledCheckElements, 999);
				}

				addEventListener('hashchange', throttledCheckElements, true);

				//, 'fullscreenchange'
				['focus', 'mouseover', 'click', 'load', 'transitionend', 'animationend', 'webkitAnimationEnd'].forEach(function(name){
					document.addEventListener(name, throttledCheckElements, true);
				});

				if(!(isCompleted = /d$|^c/.test(document.readyState))){
					addEventListener('load', onload);
					document.addEventListener('DOMContentLoaded', throttledCheckElements);
				} else {
					onload();
				}

				throttledCheckElements();
			},
			checkElems: throttledCheckElements,
			unveil: unveilElement
		};
	})();


	var autoSizer = (function(){
		var autosizesElems;

		var sizeElement = function (elem, dataAttr, width){
			var sources, i, len, event;
			var parent = elem.parentNode;

			if(parent){
				width = getWidth(elem, parent, width);
				event = triggerEvent(elem, 'lazybeforesizes', {width: width, dataAttr: !!dataAttr});

				if(!event.defaultPrevented){
					width = event.detail.width;

					if(width && width !== elem._lazysizesWidth){
						elem._lazysizesWidth = width;
						width += 'px';
						elem.setAttribute('sizes', width);

						if(regPicture.test(parent.nodeName || '')){
							sources = parent.getElementsByTagName('source');
							for(i = 0, len = sources.length; i < len; i++){
								sources[i].setAttribute('sizes', width);
							}
						}

						if(!event.detail.dataAttr){
							updatePolyfill(elem, event.detail);
						}
					}
				}
			}
		};

		var updateElementsSizes = function(){
			var i;
			var len = autosizesElems.length;
			if(len){
				i = 0;

				for(; i < len; i++){
					sizeElement(autosizesElems[i]);
				}
			}
		};

		var throttledUpdateElementsSizes = throttle(updateElementsSizes);

		return {
			_: function(){
				autosizesElems = document.getElementsByClassName(lazySizesConfig.autosizesClass);
				addEventListener('resize', throttledUpdateElementsSizes);
			},
			checkElems: throttledUpdateElementsSizes,
			updateElem: sizeElement
		};
	})();

	var init = function(){
		if(!init.i){
			init.i = true;
			autoSizer._();
			loader._();
		}
	};

	(function(){
		var prop;
		var lazySizesDefaults = {
			lazyClass: 'lazyload',
			loadedClass: 'lazyloaded',
			loadingClass: 'lazyloading',
			preloadClass: 'lazypreload',
			errorClass: 'lazyerror',
			autosizesClass: 'lazyautosizes',
			srcAttr: 'data-src',
			srcsetAttr: 'data-srcset',
			sizesAttr: 'data-sizes',
			//preloadAfterLoad: false,
			minSize: 40,
			customMedia: {},
			init: true,
			expFactor: 2,
			expand: 359,
			loadMode: 2,
			throttle: 99
		};

		lazySizesConfig = window.lazySizesConfig || window.lazysizesConfig || {};

		for(prop in lazySizesDefaults){
			if(!(prop in lazySizesConfig)){
				lazySizesConfig[prop] = lazySizesDefaults[prop];
			}
		}

		window.lazySizesConfig = lazySizesConfig;

		setTimeout(function(){
			if(lazySizesConfig.init){
				init();
			}
		});
	})();

	return {
		cfg: lazySizesConfig,
		autoSizer: autoSizer,
		loader: loader,
		init: init,
		uP: updatePolyfill,
		aC: addClass,
		rC: removeClass,
		hC: hasClass,
		fire: triggerEvent,
		gW: getWidth
	};
}));
/*! Picturefill - Responsive Images that work today.
 *  Author: Scott Jehl, Filament Group, 2012 ( new proposal implemented by Shawn Jansepar )
 *  License: MIT/GPLv2
 *  Spec: http://picture.responsiveimages.org/
 */
(function( w, doc, image ) {
	// Enable strict mode
	"use strict";

	function expose(picturefill) {
		/* expose picturefill */
		if ( typeof module === "object" && typeof module.exports === "object" ) {
			// CommonJS, just export
			module.exports = picturefill;
		} else if ( typeof define === "function" && define.amd ) {
			// AMD support
			define( "picturefill", function() { return picturefill; } );
		}
		if ( typeof w === "object" ) {
			// If no AMD and we are in the browser, attach to window
			w.picturefill = picturefill;
		}
	}

	// If picture is supported, well, that's awesome. Let's get outta here...
	if ( w.HTMLPictureElement ) {
		expose(function() { });
		return;
	}

	// HTML shim|v it for old IE (IE9 will still need the HTML video tag workaround)
	doc.createElement( "picture" );

	// local object for method references and testing exposure
	var pf = w.picturefill || {};

	var regWDesc = /\s+\+?\d+(e\d+)?w/;

	// namespace
	pf.ns = "picturefill";

	// srcset support test
	(function() {
		pf.srcsetSupported = "srcset" in image;
		pf.sizesSupported = "sizes" in image;
		pf.curSrcSupported = "currentSrc" in image;
	})();

	// just a string trim workaround
	pf.trim = function( str ) {
		return str.trim ? str.trim() : str.replace( /^\s+|\s+$/g, "" );
	};

	/**
	 * Gets a string and returns the absolute URL
	 * @param src
	 * @returns {String} absolute URL
	 */
	pf.makeUrl = (function() {
		var anchor = doc.createElement( "a" );
		return function(src) {
			anchor.href = src;
			return anchor.href;
		};
	})();

	/**
	 * Shortcut method for https://w3c.github.io/webappsec/specs/mixedcontent/#restricts-mixed-content ( for easy overriding in tests )
	 */
	pf.restrictsMixedContent = function() {
		return w.location.protocol === "https:";
	};
	/**
	 * Shortcut method for matchMedia ( for easy overriding in tests )
	 */

	pf.matchesMedia = function( media ) {
		return w.matchMedia && w.matchMedia( media ).matches;
	};

	// Shortcut method for `devicePixelRatio` ( for easy overriding in tests )
	pf.getDpr = function() {
		return ( w.devicePixelRatio || 1 );
	};

	/**
	 * Get width in css pixel value from a "length" value
	 * http://dev.w3.org/csswg/css-values-3/#length-value
	 */
	pf.getWidthFromLength = function( length ) {
		var cssValue;
		// If a length is specified and doesn’t contain a percentage, and it is greater than 0 or using `calc`, use it. Else, abort.
		if ( !(length && length.indexOf( "%" ) > -1 === false && ( parseFloat( length ) > 0 || length.indexOf( "calc(" ) > -1 )) ) {
			return false;
		}

		/**
		 * If length is specified in  `vw` units, use `%` instead since the div we’re measuring
		 * is injected at the top of the document.
		 *
		 * TODO: maybe we should put this behind a feature test for `vw`? The risk of doing this is possible browser inconsistancies with vw vs %
		 */
		length = length.replace( "vw", "%" );

		// Create a cached element for getting length value widths
		if ( !pf.lengthEl ) {
			pf.lengthEl = doc.createElement( "div" );

			// Positioning styles help prevent padding/margin/width on `html` or `body` from throwing calculations off.
			pf.lengthEl.style.cssText = "border:0;display:block;font-size:1em;left:0;margin:0;padding:0;position:absolute;visibility:hidden";

			// Add a class, so that everyone knows where this element comes from
			pf.lengthEl.className = "helper-from-picturefill-js";
		}

		pf.lengthEl.style.width = "0px";

		try {
			pf.lengthEl.style.width = length;
		} catch ( e ) {}

		doc.body.appendChild(pf.lengthEl);

		cssValue = pf.lengthEl.offsetWidth;

		if ( cssValue <= 0 ) {
			cssValue = false;
		}

		doc.body.removeChild( pf.lengthEl );

		return cssValue;
	};

	pf.detectTypeSupport = function( type, typeUri ) {
		// based on Modernizr's lossless img-webp test
		// note: asynchronous
		var image = new w.Image();
		image.onerror = function() {
			pf.types[ type ] = false;
			picturefill();
		};
		image.onload = function() {
			pf.types[ type ] = image.width === 1;
			picturefill();
		};
		image.src = typeUri;

		return "pending";
	};
	// container of supported mime types that one might need to qualify before using
	pf.types = pf.types || {};

	pf.initTypeDetects = function() {
		// Add support for standard mime types
		pf.types[ "image/jpeg" ] = true;
		pf.types[ "image/gif" ] = true;
		pf.types[ "image/png" ] = true;
		pf.types[ "image/svg+xml" ] = doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1");
		pf.types[ "image/webp" ] = pf.detectTypeSupport("image/webp", "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=");
	};

	pf.verifyTypeSupport = function( source ) {
		var type = source.getAttribute( "type" );
		// if type attribute exists, return test result, otherwise return true
		if ( type === null || type === "" ) {
			return true;
		} else {
			var pfType = pf.types[ type ];
			// if the type test is a function, run it and return "pending" status. The function will rerun picturefill on pending elements once finished.
			if ( typeof pfType === "string" && pfType !== "pending") {
				pf.types[ type ] = pf.detectTypeSupport( type, pfType );
				return "pending";
			} else if ( typeof pfType === "function" ) {
				pfType();
				return "pending";
			} else {
				return pfType;
			}
		}
	};

	// Parses an individual `size` and returns the length, and optional media query
	pf.parseSize = function( sourceSizeStr ) {
		var match = /(\([^)]+\))?\s*(.+)/g.exec( sourceSizeStr );
		return {
			media: match && match[1],
			length: match && match[2]
		};
	};

	// Takes a string of sizes and returns the width in pixels as a number
	pf.findWidthFromSourceSize = function( sourceSizeListStr ) {
		// Split up source size list, ie ( max-width: 30em ) 100%, ( max-width: 50em ) 50%, 33%
		//                            or (min-width:30em) calc(30% - 15px)
		var sourceSizeList = pf.trim( sourceSizeListStr ).split( /\s*,\s*/ ),
			winningLength;

		for ( var i = 0, len = sourceSizeList.length; i < len; i++ ) {
			// Match <media-condition>? length, ie ( min-width: 50em ) 100%
			var sourceSize = sourceSizeList[ i ],
			// Split "( min-width: 50em ) 100%" into separate strings
				parsedSize = pf.parseSize( sourceSize ),
				length = parsedSize.length,
				media = parsedSize.media;

			if ( !length ) {
				continue;
			}
			// if there is no media query or it matches, choose this as our winning length
			if ( (!media || pf.matchesMedia( media )) &&
					// pass the length to a method that can properly determine length
					// in pixels based on these formats: http://dev.w3.org/csswg/css-values-3/#length-value
				(winningLength = pf.getWidthFromLength( length )) ) {
				break;
			}
		}

		//if we have no winningLength fallback to 100vw
		return winningLength || Math.max(w.innerWidth || 0, doc.documentElement.clientWidth);
	};

	pf.parseSrcset = function( srcset ) {
		/**
		 * A lot of this was pulled from Boris Smus’ parser for the now-defunct WHATWG `srcset`
		 * https://github.com/borismus/srcset-polyfill/blob/master/js/srcset-info.js
		 *
		 * 1. Let input (`srcset`) be the value passed to this algorithm.
		 * 2. Let position be a pointer into input, initially pointing at the start of the string.
		 * 3. Let raw candidates be an initially empty ordered list of URLs with associated
		 *    unparsed descriptors. The order of entries in the list is the order in which entries
		 *    are added to the list.
		 */
		var candidates = [];

		while ( srcset !== "" ) {
			srcset = srcset.replace( /^\s+/g, "" );

			// 5. Collect a sequence of characters that are not space characters, and let that be url.
			var pos = srcset.search(/\s/g),
				url, descriptor = null;

			if ( pos !== -1 ) {
				url = srcset.slice( 0, pos );

				var last = url.slice(-1);

				// 6. If url ends with a U+002C COMMA character (,), remove that character from url
				// and let descriptors be the empty string. Otherwise, follow these substeps
				// 6.1. If url is empty, then jump to the step labeled descriptor parser.

				if ( last === "," || url === "" ) {
					url = url.replace( /,+$/, "" );
					descriptor = "";
				}
				srcset = srcset.slice( pos + 1 );

				// 6.2. Collect a sequence of characters that are not U+002C COMMA characters (,), and
				// let that be descriptors.
				if ( descriptor === null ) {
					var descpos = srcset.indexOf( "," );
					if ( descpos !== -1 ) {
						descriptor = srcset.slice( 0, descpos );
						srcset = srcset.slice( descpos + 1 );
					} else {
						descriptor = srcset;
						srcset = "";
					}
				}
			} else {
				url = srcset;
				srcset = "";
			}

			// 7. Add url to raw candidates, associated with descriptors.
			if ( url || descriptor ) {
				candidates.push({
					url: url,
					descriptor: descriptor
				});
			}
		}
		return candidates;
	};

	pf.parseDescriptor = function( descriptor, sizesattr ) {
		// 11. Descriptor parser: Let candidates be an initially empty source set. The order of entries in the list
		// is the order in which entries are added to the list.
		var sizes = sizesattr || "100vw",
			sizeDescriptor = descriptor && descriptor.replace( /(^\s+|\s+$)/g, "" ),
			widthInCssPixels = pf.findWidthFromSourceSize( sizes ),
			resCandidate;

		if ( sizeDescriptor ) {
			var splitDescriptor = sizeDescriptor.split(" ");

			for (var i = splitDescriptor.length - 1; i >= 0; i--) {
				var curr = splitDescriptor[ i ],
					lastchar = curr && curr.slice( curr.length - 1 );

				if ( ( lastchar === "h" || lastchar === "w" ) && !pf.sizesSupported ) {
					resCandidate = parseFloat( ( parseInt( curr, 10 ) / widthInCssPixels ) );
				} else if ( lastchar === "x" ) {
					var res = curr && parseFloat( curr, 10 );
					resCandidate = res && !isNaN( res ) ? res : 1;
				}
			}
		}
		return resCandidate || 1;
	};

	/**
	 * Takes a srcset in the form of url/
	 * ex. "images/pic-medium.png 1x, images/pic-medium-2x.png 2x" or
	 *     "images/pic-medium.png 400w, images/pic-medium-2x.png 800w" or
	 *     "images/pic-small.png"
	 * Get an array of image candidates in the form of
	 *      {url: "/foo/bar.png", resolution: 1}
	 * where resolution is http://dev.w3.org/csswg/css-values-3/#resolution-value
	 * If sizes is specified, resolution is calculated
	 */
	pf.getCandidatesFromSourceSet = function( srcset, sizes ) {
		var candidates = pf.parseSrcset( srcset ),
			formattedCandidates = [];

		for ( var i = 0, len = candidates.length; i < len; i++ ) {
			var candidate = candidates[ i ];

			formattedCandidates.push({
				url: candidate.url,
				resolution: pf.parseDescriptor( candidate.descriptor, sizes )
			});
		}
		return formattedCandidates;
	};

	/**
	 * if it's an img element and it has a srcset property,
	 * we need to remove the attribute so we can manipulate src
	 * (the property's existence infers native srcset support, and a srcset-supporting browser will prioritize srcset's value over our winning picture candidate)
	 * this moves srcset's value to memory for later use and removes the attr
	 */
	pf.dodgeSrcset = function( img ) {
		if ( img.srcset ) {
			img[ pf.ns ].srcset = img.srcset;
			img.srcset = "";
			img.setAttribute( "data-pfsrcset", img[ pf.ns ].srcset );
		}
	};

	// Accept a source or img element and process its srcset and sizes attrs
	pf.processSourceSet = function( el ) {
		var srcset = el.getAttribute( "srcset" ),
			sizes = el.getAttribute( "sizes" ),
			candidates = [];

		// if it's an img element, use the cached srcset property (defined or not)
		if ( el.nodeName.toUpperCase() === "IMG" && el[ pf.ns ] && el[ pf.ns ].srcset ) {
			srcset = el[ pf.ns ].srcset;
		}

		if ( srcset ) {
			candidates = pf.getCandidatesFromSourceSet( srcset, sizes );
		}
		return candidates;
	};

	pf.backfaceVisibilityFix = function( picImg ) {
		// See: https://github.com/scottjehl/picturefill/issues/332
		var style = picImg.style || {},
			WebkitBackfaceVisibility = "webkitBackfaceVisibility" in style,
			currentZoom = style.zoom;

		if (WebkitBackfaceVisibility) {
			style.zoom = ".999";

			WebkitBackfaceVisibility = picImg.offsetWidth;

			style.zoom = currentZoom;
		}
	};

	pf.setIntrinsicSize = (function() {
		var urlCache = {};
		var setSize = function( picImg, width, res ) {
			if ( width ) {
				picImg.setAttribute( "width", parseInt(width / res, 10) );
			}
		};
		return function( picImg, bestCandidate ) {
			var img;
			if ( !picImg[ pf.ns ] || w.pfStopIntrinsicSize ) {
				return;
			}
			if ( picImg[ pf.ns ].dims === undefined ) {
				picImg[ pf.ns].dims = picImg.getAttribute("width") || picImg.getAttribute("height");
			}
			if ( picImg[ pf.ns].dims ) { return; }

			if ( bestCandidate.url in urlCache ) {
				setSize( picImg, urlCache[bestCandidate.url], bestCandidate.resolution );
			} else {
				img = doc.createElement( "img" );
				img.onload = function() {
					urlCache[bestCandidate.url] = img.width;

					//IE 10/11 don't calculate width for svg outside document
					if ( !urlCache[bestCandidate.url] ) {
						try {
							doc.body.appendChild( img );
							urlCache[bestCandidate.url] = img.width || img.offsetWidth;
							doc.body.removeChild( img );
						} catch(e){}
					}

					if ( picImg.src === bestCandidate.url ) {
						setSize( picImg, urlCache[bestCandidate.url], bestCandidate.resolution );
					}
					picImg = null;
					img.onload = null;
					img = null;
				};
				img.src = bestCandidate.url;
			}
		};
	})();

	pf.applyBestCandidate = function( candidates, picImg ) {
		var candidate,
			length,
			bestCandidate;

		candidates.sort( pf.ascendingSort );

		length = candidates.length;
		bestCandidate = candidates[ length - 1 ];

		for ( var i = 0; i < length; i++ ) {
			candidate = candidates[ i ];
			if ( candidate.resolution >= pf.getDpr() ) {
				bestCandidate = candidate;
				break;
			}
		}

		if ( bestCandidate ) {

			bestCandidate.url = pf.makeUrl( bestCandidate.url );

			if ( picImg.src !== bestCandidate.url ) {
				if ( pf.restrictsMixedContent() && bestCandidate.url.substr(0, "http:".length).toLowerCase() === "http:" ) {
					if ( window.console !== undefined ) {
						console.warn( "Blocked mixed content image " + bestCandidate.url );
					}
				} else {
					picImg.src = bestCandidate.url;
					// currentSrc attribute and property to match
					// http://picture.responsiveimages.org/#the-img-element
					if ( !pf.curSrcSupported ) {
						picImg.currentSrc = picImg.src;
					}

					pf.backfaceVisibilityFix( picImg );
				}
			}

			pf.setIntrinsicSize(picImg, bestCandidate);
		}
	};

	pf.ascendingSort = function( a, b ) {
		return a.resolution - b.resolution;
	};

	/**
	 * In IE9, <source> elements get removed if they aren't children of
	 * video elements. Thus, we conditionally wrap source elements
	 * using <!--[if IE 9]><video style="display: none;"><![endif]-->
	 * and must account for that here by moving those source elements
	 * back into the picture element.
	 */
	pf.removeVideoShim = function( picture ) {
		var videos = picture.getElementsByTagName( "video" );
		if ( videos.length ) {
			var video = videos[ 0 ],
				vsources = video.getElementsByTagName( "source" );
			while ( vsources.length ) {
				picture.insertBefore( vsources[ 0 ], video );
			}
			// Remove the video element once we're finished removing its children
			video.parentNode.removeChild( video );
		}
	};

	/**
	 * Find all `img` elements, and add them to the candidate list if they have
	 * a `picture` parent, a `sizes` attribute in basic `srcset` supporting browsers,
	 * a `srcset` attribute at all, and they haven’t been evaluated already.
	 */
	pf.getAllElements = function() {
		var elems = [],
			imgs = doc.getElementsByTagName( "img" );

		for ( var h = 0, len = imgs.length; h < len; h++ ) {
			var currImg = imgs[ h ];

			if ( currImg.parentNode.nodeName.toUpperCase() === "PICTURE" ||
				( currImg.getAttribute( "srcset" ) !== null ) || currImg[ pf.ns ] && currImg[ pf.ns ].srcset !== null ) {
				elems.push( currImg );
			}
		}
		return elems;
	};

	pf.getMatch = function( img, picture ) {
		var sources = picture.childNodes,
			match;

		// Go through each child, and if they have media queries, evaluate them
		for ( var j = 0, slen = sources.length; j < slen; j++ ) {
			var source = sources[ j ];

			// ignore non-element nodes
			if ( source.nodeType !== 1 ) {
				continue;
			}

			// Hitting the `img` element that started everything stops the search for `sources`.
			// If no previous `source` matches, the `img` itself is evaluated later.
			if ( source === img ) {
				return match;
			}

			// ignore non-`source` nodes
			if ( source.nodeName.toUpperCase() !== "SOURCE" ) {
				continue;
			}
			// if it's a source element that has the `src` property set, throw a warning in the console
			if ( source.getAttribute( "src" ) !== null && typeof console !== undefined ) {
				console.warn("The `src` attribute is invalid on `picture` `source` element; instead, use `srcset`.");
			}

			var media = source.getAttribute( "media" );

			// if source does not have a srcset attribute, skip
			if ( !source.getAttribute( "srcset" ) ) {
				continue;
			}

			// if there's no media specified, OR w.matchMedia is supported
			if ( ( !media || pf.matchesMedia( media ) ) ) {
				var typeSupported = pf.verifyTypeSupport( source );

				if ( typeSupported === true ) {
					match = source;
					break;
				} else if ( typeSupported === "pending" ) {
					return false;
				}
			}
		}

		return match;
	};

	function picturefill( opt ) {
		var elements,
			element,
			parent,
			firstMatch,
			candidates,
			options = opt || {};

		elements = options.elements || pf.getAllElements();

		// Loop through all elements
		for ( var i = 0, plen = elements.length; i < plen; i++ ) {
			element = elements[ i ];
			parent = element.parentNode;
			firstMatch = undefined;
			candidates = undefined;

			// immediately skip non-`img` nodes
			if ( element.nodeName.toUpperCase() !== "IMG" ) {
				continue;
			}

			// expando for caching data on the img
			if ( !element[ pf.ns ] ) {
				element[ pf.ns ] = {};
			}

			// if the element has already been evaluated, skip it unless
			// `options.reevaluate` is set to true ( this, for example,
			// is set to true when running `picturefill` on `resize` ).
			if ( !options.reevaluate && element[ pf.ns ].evaluated ) {
				continue;
			}

			// if `img` is in a `picture` element
			if ( parent && parent.nodeName.toUpperCase() === "PICTURE" ) {

				// IE9 video workaround
				pf.removeVideoShim( parent );

				// return the first match which might undefined
				// returns false if there is a pending source
				// TODO the return type here is brutal, cleanup
				firstMatch = pf.getMatch( element, parent );

				// if any sources are pending in this picture due to async type test(s)
				// remove the evaluated attr and skip for now ( the pending test will
				// rerun picturefill on this element when complete)
				if ( firstMatch === false ) {
					continue;
				}
			} else {
				firstMatch = undefined;
			}

			// Cache and remove `srcset` if present and we’re going to be doing `picture`/`srcset`/`sizes` polyfilling to it.
			if ( ( parent && parent.nodeName.toUpperCase() === "PICTURE" ) ||
				( !pf.sizesSupported && ( element.srcset && regWDesc.test( element.srcset ) ) ) ) {
				pf.dodgeSrcset( element );
			}

			if ( firstMatch ) {
				candidates = pf.processSourceSet( firstMatch );
				pf.applyBestCandidate( candidates, element );
			} else {
				// No sources matched, so we’re down to processing the inner `img` as a source.
				candidates = pf.processSourceSet( element );

				if ( element.srcset === undefined || element[ pf.ns ].srcset ) {
					// Either `srcset` is completely unsupported, or we need to polyfill `sizes` functionality.
					pf.applyBestCandidate( candidates, element );
				} // Else, resolution-only `srcset` is supported natively.
			}

			// set evaluated to true to avoid unnecessary reparsing
			element[ pf.ns ].evaluated = true;
		}
	}

	/**
	 * Sets up picture polyfill by polling the document and running
	 * the polyfill every 250ms until the document is ready.
	 * Also attaches picturefill on resize
	 */
	function runPicturefill() {
		pf.initTypeDetects();
		picturefill();
		var intervalId = setInterval( function() {
			// When the document has finished loading, stop checking for new images
			// https://github.com/ded/domready/blob/master/ready.js#L15
			picturefill();

			if ( /^loaded|^i|^c/.test( doc.readyState ) ) {
				clearInterval( intervalId );
				return;
			}
		}, 250 );

		var resizeTimer;
		var handleResize = function() {
			picturefill({ reevaluate: true });
		};
		function checkResize() {
			clearTimeout(resizeTimer);
			resizeTimer = setTimeout( handleResize, 60 );
		}

		if ( w.addEventListener ) {
			w.addEventListener( "resize", checkResize, false );
		} else if ( w.attachEvent ) {
			w.attachEvent( "onresize", checkResize );
		}
	}

	runPicturefill();

	/* expose methods for testing */
	picturefill._ = pf;

	expose( picturefill );

} )( window, window.document, new window.Image() );
/* Respond.js: min/max-width media query polyfill. (c) Scott Jehl. MIT Lic. j.mp/respondjs  */
(function( w ){

	"use strict";

	//exposed namespace
	var respond = {};
	w.respond = respond;

	//define update even in native-mq-supporting browsers, to avoid errors
	respond.update = function(){};

	//define ajax obj
	var requestQueue = [],
		xmlHttp = (function() {
			var xmlhttpmethod = false;
			try {
				xmlhttpmethod = new w.XMLHttpRequest();
			}
			catch( e ){
				xmlhttpmethod = new w.ActiveXObject( "Microsoft.XMLHTTP" );
			}
			return function(){
				return xmlhttpmethod;
			};
		})(),

	//tweaked Ajax functions from Quirksmode
		ajax = function( url, callback ) {
			var req = xmlHttp();
			if (!req){
				return;
			}
			req.open( "GET", url, true );
			req.onreadystatechange = function () {
				if ( req.readyState !== 4 || req.status !== 200 && req.status !== 304 ){
					return;
				}
				callback( req.responseText );
			};
			if ( req.readyState === 4 ){
				return;
			}
			req.send( null );
		},
		isUnsupportedMediaQuery = function( query ) {
			return query.replace( respond.regex.minmaxwh, '' ).match( respond.regex.other );
		};

	//expose for testing
	respond.ajax = ajax;
	respond.queue = requestQueue;
	respond.unsupportedmq = isUnsupportedMediaQuery;
	respond.regex = {
		media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,
		keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,
		comments: /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,
		urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,
		findStyles: /@media *([^\{]+)\{([\S\s]+?)$/,
		only: /(only\s+)?([a-zA-Z]+)\s?/,
		minw: /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
		maxw: /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
		minmaxwh: /\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,
		other: /\([^\)]*\)/g
	};

	//expose media query support flag for external use
	respond.mediaQueriesSupported = w.matchMedia && w.matchMedia( "only all" ) !== null && w.matchMedia( "only all" ).matches;

	//if media queries are supported, exit here
	if( respond.mediaQueriesSupported ){
		return;
	}

	//define vars
	var doc = w.document,
		docElem = doc.documentElement,
		mediastyles = [],
		rules = [],
		appendedEls = [],
		parsedSheets = {},
		resizeThrottle = 30,
		head = doc.getElementsByTagName( "head" )[0] || docElem,
		base = doc.getElementsByTagName( "base" )[0],
		links = head.getElementsByTagName( "link" ),

		lastCall,
		resizeDefer,

	//cached container for 1em value, populated the first time it's needed
		eminpx,

	// returns the value of 1em in pixels
		getEmValue = function() {
			var ret,
				div = doc.createElement('div'),
				body = doc.body,
				originalHTMLFontSize = docElem.style.fontSize,
				originalBodyFontSize = body && body.style.fontSize,
				fakeUsed = false;

			div.style.cssText = "position:absolute;font-size:1em;width:1em";

			if( !body ){
				body = fakeUsed = doc.createElement( "body" );
				body.style.background = "none";
			}

			// 1em in a media query is the value of the default font size of the browser
			// reset docElem and body to ensure the correct value is returned
			docElem.style.fontSize = "100%";
			body.style.fontSize = "100%";

			body.appendChild( div );

			if( fakeUsed ){
				docElem.insertBefore( body, docElem.firstChild );
			}

			ret = div.offsetWidth;

			if( fakeUsed ){
				docElem.removeChild( body );
			}
			else {
				body.removeChild( div );
			}

			// restore the original values
			docElem.style.fontSize = originalHTMLFontSize;
			if( originalBodyFontSize ) {
				body.style.fontSize = originalBodyFontSize;
			}


			//also update eminpx before returning
			ret = eminpx = parseFloat(ret);

			return ret;
		},

	//enable/disable styles
		applyMedia = function( fromResize ){
			var name = "clientWidth",
				docElemProp = docElem[ name ],
				currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
				styleBlocks	= {},
				lastLink = links[ links.length-1 ],
				now = (new Date()).getTime();

			//throttle resize calls
			if( fromResize && lastCall && now - lastCall < resizeThrottle ){
				w.clearTimeout( resizeDefer );
				resizeDefer = w.setTimeout( applyMedia, resizeThrottle );
				return;
			}
			else {
				lastCall = now;
			}

			for( var i in mediastyles ){
				if( mediastyles.hasOwnProperty( i ) ){
					var thisstyle = mediastyles[ i ],
						min = thisstyle.minw,
						max = thisstyle.maxw,
						minnull = min === null,
						maxnull = max === null,
						em = "em";

					if( !!min ){
						min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
					}
					if( !!max ){
						max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
					}

					// if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true
					if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
						if( !styleBlocks[ thisstyle.media ] ){
							styleBlocks[ thisstyle.media ] = [];
						}
						styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
					}
				}
			}

			//remove any existing respond style element(s)
			for( var j in appendedEls ){
				if( appendedEls.hasOwnProperty( j ) ){
					if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){
						head.removeChild( appendedEls[ j ] );
					}
				}
			}
			appendedEls.length = 0;

			//inject active styles, grouped by media type
			for( var k in styleBlocks ){
				if( styleBlocks.hasOwnProperty( k ) ){
					var ss = doc.createElement( "style" ),
						css = styleBlocks[ k ].join( "\n" );

					ss.type = "text/css";
					ss.media = k;

					//originally, ss was appended to a documentFragment and sheets were appended in bulk.
					//this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one!
					head.insertBefore( ss, lastLink.nextSibling );

					if ( ss.styleSheet ){
						ss.styleSheet.cssText = css;
					}
					else {
						ss.appendChild( doc.createTextNode( css ) );
					}

					//push to appendedEls to track for later removal
					appendedEls.push( ss );
				}
			}
		},
	//find media blocks in css text, convert to style blocks
		translate = function( styles, href, media ){
			var qs = styles.replace( respond.regex.comments, '' )
					.replace( respond.regex.keyframes, '' )
					.match( respond.regex.media ),
				ql = qs && qs.length || 0;

			//try to get CSS path
			href = href.substring( 0, href.lastIndexOf( "/" ) );

			var repUrls = function( css ){
					return css.replace( respond.regex.urls, "$1" + href + "$2$3" );
				},
				useMedia = !ql && media;

			//if path exists, tack on trailing slash
			if( href.length ){ href += "/"; }

			//if no internal queries exist, but media attr does, use that
			//note: this currently lacks support for situations where a media attr is specified on a link AND
			//its associated stylesheet has internal CSS media queries.
			//In those cases, the media attribute will currently be ignored.
			if( useMedia ){
				ql = 1;
			}

			for( var i = 0; i < ql; i++ ){
				var fullq, thisq, eachq, eql;

				//media attr
				if( useMedia ){
					fullq = media;
					rules.push( repUrls( styles ) );
				}
				//parse for styles
				else{
					fullq = qs[ i ].match( respond.regex.findStyles ) && RegExp.$1;
					rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
				}

				eachq = fullq.split( "," );
				eql = eachq.length;

				for( var j = 0; j < eql; j++ ){
					thisq = eachq[ j ];

					if( isUnsupportedMediaQuery( thisq ) ) {
						continue;
					}

					mediastyles.push( {
						media : thisq.split( "(" )[ 0 ].match( respond.regex.only ) && RegExp.$2 || "all",
						rules : rules.length - 1,
						hasquery : thisq.indexOf("(") > -1,
						minw : thisq.match( respond.regex.minw ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
						maxw : thisq.match( respond.regex.maxw ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
					} );
				}
			}

			applyMedia();
		},

	//recurse through request queue, get css text
		makeRequests = function(){
			if( requestQueue.length ){
				var thisRequest = requestQueue.shift();

				ajax( thisRequest.href, function( styles ){
					translate( styles, thisRequest.href, thisRequest.media );
					parsedSheets[ thisRequest.href ] = true;

					// by wrapping recursive function call in setTimeout
					// we prevent "Stack overflow" error in IE7
					w.setTimeout(function(){ makeRequests(); },0);
				} );
			}
		},

	//loop stylesheets, send text content to translate
		ripCSS = function(){

			for( var i = 0; i < links.length; i++ ){
				var sheet = links[ i ],
					href = sheet.href,
					media = sheet.media,
					isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";

				//only links plz and prevent re-parsing
				if( !!href && isCSS && !parsedSheets[ href ] ){
					// selectivizr exposes css through the rawCssText expando
					if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
						translate( sheet.styleSheet.rawCssText, href, media );
						parsedSheets[ href ] = true;
					} else {
						if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) ||
							href.replace( RegExp.$1, "" ).split( "/" )[0] === w.location.host ){
							// IE7 doesn't handle urls that start with '//' for ajax request
							// manually add in the protocol
							if ( href.substring(0,2) === "//" ) { href = w.location.protocol + href; }
							requestQueue.push( {
								href: href,
								media: media
							} );
						}
					}
				}
			}
			makeRequests();
		};

	//translate CSS
	ripCSS();

	//expose update for re-running respond later on
	respond.update = ripCSS;

	//expose getEmValue
	respond.getEmValue = getEmValue;

	//adjust on resize
	function callMedia(){
		applyMedia( true );
	}

	if( w.addEventListener ){
		w.addEventListener( "resize", callMedia, false );
	}
	else if( w.attachEvent ){
		w.attachEvent( "onresize", callMedia );
	}
})(this);
/*! VelocityJS.org (1.2.2). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */

/*************************
 Velocity jQuery Shim
 *************************/

/*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */

/* This file contains the jQuery functions that Velocity relies on, thereby removing Velocity's dependency on a full copy of jQuery, and allowing it to work in any environment. */
/* These shimmed functions are only used if jQuery isn't present. If both this shim and jQuery are loaded, Velocity defaults to jQuery proper. */
/* Browser support: Using this shim instead of jQuery proper removes support for IE8. */

;(function (window) {
	/***************
	 Setup
	 ***************/

	/* If jQuery is already loaded, there's no point in loading this shim. */
	if (window.jQuery) {
		return;
	}

	/* jQuery base. */
	var $ = function (selector, context) {
		return new $.fn.init(selector, context);
	};

	/********************
	 Private Methods
	 ********************/

	/* jQuery */
	$.isWindow = function (obj) {
		/* jshint eqeqeq: false */
		return obj != null && obj == obj.window;
	};

	/* jQuery */
	$.type = function (obj) {
		if (obj == null) {
			return obj + "";
		}

		return typeof obj === "object" || typeof obj === "function" ?
		class2type[toString.call(obj)] || "object" :
			typeof obj;
	};

	/* jQuery */
	$.isArray = Array.isArray || function (obj) {
		return $.type(obj) === "array";
	};

	/* jQuery */
	function isArraylike (obj) {
		var length = obj.length,
			type = $.type(obj);

		if (type === "function" || $.isWindow(obj)) {
			return false;
		}

		if (obj.nodeType === 1 && length) {
			return true;
		}

		return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj;
	}

	/***************
	 $ Methods
	 ***************/

	/* jQuery: Support removed for IE<9. */
	$.isPlainObject = function (obj) {
		var key;

		if (!obj || $.type(obj) !== "object" || obj.nodeType || $.isWindow(obj)) {
			return false;
		}

		try {
			if (obj.constructor &&
				!hasOwn.call(obj, "constructor") &&
				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
				return false;
			}
		} catch (e) {
			return false;
		}

		for (key in obj) {}

		return key === undefined || hasOwn.call(obj, key);
	};

	/* jQuery */
	$.each = function(obj, callback, args) {
		var value,
			i = 0,
			length = obj.length,
			isArray = isArraylike(obj);

		if (args) {
			if (isArray) {
				for (; i < length; i++) {
					value = callback.apply(obj[i], args);

					if (value === false) {
						break;
					}
				}
			} else {
				for (i in obj) {
					value = callback.apply(obj[i], args);

					if (value === false) {
						break;
					}
				}
			}

		} else {
			if (isArray) {
				for (; i < length; i++) {
					value = callback.call(obj[i], i, obj[i]);

					if (value === false) {
						break;
					}
				}
			} else {
				for (i in obj) {
					value = callback.call(obj[i], i, obj[i]);

					if (value === false) {
						break;
					}
				}
			}
		}

		return obj;
	};

	/* Custom */
	$.data = function (node, key, value) {
		/* $.getData() */
		if (value === undefined) {
			var id = node[$.expando],
				store = id && cache[id];

			if (key === undefined) {
				return store;
			} else if (store) {
				if (key in store) {
					return store[key];
				}
			}
			/* $.setData() */
		} else if (key !== undefined) {
			var id = node[$.expando] || (node[$.expando] = ++$.uuid);

			cache[id] = cache[id] || {};
			cache[id][key] = value;

			return value;
		}
	};

	/* Custom */
	$.removeData = function (node, keys) {
		var id = node[$.expando],
			store = id && cache[id];

		if (store) {
			$.each(keys, function(_, key) {
				delete store[key];
			});
		}
	};

	/* jQuery */
	$.extend = function () {
		var src, copyIsArray, copy, name, options, clone,
			target = arguments[0] || {},
			i = 1,
			length = arguments.length,
			deep = false;

		if (typeof target === "boolean") {
			deep = target;

			target = arguments[i] || {};
			i++;
		}

		if (typeof target !== "object" && $.type(target) !== "function") {
			target = {};
		}

		if (i === length) {
			target = this;
			i--;
		}

		for (; i < length; i++) {
			if ((options = arguments[i]) != null) {
				for (name in options) {
					src = target[name];
					copy = options[name];

					if (target === copy) {
						continue;
					}

					if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
						if (copyIsArray) {
							copyIsArray = false;
							clone = src && $.isArray(src) ? src : [];

						} else {
							clone = src && $.isPlainObject(src) ? src : {};
						}

						target[name] = $.extend(deep, clone, copy);

					} else if (copy !== undefined) {
						target[name] = copy;
					}
				}
			}
		}

		return target;
	};

	/* jQuery 1.4.3 */
	$.queue = function (elem, type, data) {
		function $makeArray (arr, results) {
			var ret = results || [];

			if (arr != null) {
				if (isArraylike(Object(arr))) {
					/* $.merge */
					(function(first, second) {
						var len = +second.length,
							j = 0,
							i = first.length;

						while (j < len) {
							first[i++] = second[j++];
						}

						if (len !== len) {
							while (second[j] !== undefined) {
								first[i++] = second[j++];
							}
						}

						first.length = i;

						return first;
					})(ret, typeof arr === "string" ? [arr] : arr);
				} else {
					[].push.call(ret, arr);
				}
			}

			return ret;
		}

		if (!elem) {
			return;
		}

		type = (type || "fx") + "queue";

		var q = $.data(elem, type);

		if (!data) {
			return q || [];
		}

		if (!q || $.isArray(data)) {
			q = $.data(elem, type, $makeArray(data));
		} else {
			q.push(data);
		}

		return q;
	};

	/* jQuery 1.4.3 */
	$.dequeue = function (elems, type) {
		/* Custom: Embed element iteration. */
		$.each(elems.nodeType ? [ elems ] : elems, function(i, elem) {
			type = type || "fx";

			var queue = $.queue(elem, type),
				fn = queue.shift();

			if (fn === "inprogress") {
				fn = queue.shift();
			}

			if (fn) {
				if (type === "fx") {
					queue.unshift("inprogress");
				}

				fn.call(elem, function() {
					$.dequeue(elem, type);
				});
			}
		});
	};

	/******************
	 $.fn Methods
	 ******************/

	/* jQuery */
	$.fn = $.prototype = {
		init: function (selector) {
			/* Just return the element wrapped inside an array; don't proceed with the actual jQuery node wrapping process. */
			if (selector.nodeType) {
				this[0] = selector;

				return this;
			} else {
				throw new Error("Not a DOM node.");
			}
		},

		offset: function () {
			/* jQuery altered code: Dropped disconnected DOM node checking. */
			var box = this[0].getBoundingClientRect ? this[0].getBoundingClientRect() : { top: 0, left: 0 };

			return {
				top: box.top + (window.pageYOffset || document.scrollTop  || 0)  - (document.clientTop  || 0),
				left: box.left + (window.pageXOffset || document.scrollLeft  || 0) - (document.clientLeft || 0)
			};
		},

		position: function () {
			/* jQuery */
			function offsetParent() {
				var offsetParent = this.offsetParent || document;

				while (offsetParent && (!offsetParent.nodeType.toLowerCase === "html" && offsetParent.style.position === "static")) {
					offsetParent = offsetParent.offsetParent;
				}

				return offsetParent || document;
			}

			/* Zepto */
			var elem = this[0],
				offsetParent = offsetParent.apply(elem),
				offset = this.offset(),
				parentOffset = /^(?:body|html)$/i.test(offsetParent.nodeName) ? { top: 0, left: 0 } : $(offsetParent).offset()

			offset.top -= parseFloat(elem.style.marginTop) || 0;
			offset.left -= parseFloat(elem.style.marginLeft) || 0;

			if (offsetParent.style) {
				parentOffset.top += parseFloat(offsetParent.style.borderTopWidth) || 0
				parentOffset.left += parseFloat(offsetParent.style.borderLeftWidth) || 0
			}

			return {
				top: offset.top - parentOffset.top,
				left: offset.left - parentOffset.left
			};
		}
	};

	/**********************
	 Private Variables
	 **********************/

	/* For $.data() */
	var cache = {};
	$.expando = "velocity" + (new Date().getTime());
	$.uuid = 0;

	/* For $.queue() */
	var class2type = {},
		hasOwn = class2type.hasOwnProperty,
		toString = class2type.toString;

	var types = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
	for (var i = 0; i < types.length; i++) {
		class2type["[object " + types[i] + "]"] = types[i].toLowerCase();
	}

	/* Makes $(node) possible, without having to call init. */
	$.fn.init.prototype = $.fn;

	/* Globalize Velocity onto the window, and assign its Utilities property. */
	window.Velocity = { Utilities: $ };
})(window);

/******************
 Velocity.js
 ******************/

;(function (factory) {
	/* CommonJS module. */
	if (typeof module === "object" && typeof module.exports === "object") {
		module.exports = factory();
		/* AMD module. */
	} else if (typeof define === "function" && define.amd) {
		define(factory);
		/* Browser globals. */
	} else {
		factory();
	}
}(function() {
	return function (global, window, document, undefined) {

		/***************
		 Summary
		 ***************/

		/*
		 - CSS: CSS stack that works independently from the rest of Velocity.
		 - animate(): Core animation method that iterates over the targeted elements and queues the incoming call onto each element individually.
		 - Pre-Queueing: Prepare the element for animation by instantiating its data cache and processing the call's options.
		 - Queueing: The logic that runs once the call has reached its point of execution in the element's $.queue() stack.
		 Most logic is placed here to avoid risking it becoming stale (if the element's properties have changed).
		 - Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container.
		 - tick(): The single requestAnimationFrame loop responsible for tweening all in-progress calls.
		 - completeCall(): Handles the cleanup process for each Velocity call.
		 */

		/*********************
		 Helper Functions
		 *********************/

		/* IE detection. Gist: https://gist.github.com/julianshapiro/9098609 */
		var IE = (function() {
			if (document.documentMode) {
				return document.documentMode;
			} else {
				for (var i = 7; i > 4; i--) {
					var div = document.createElement("div");

					div.innerHTML = "<!--[if IE " + i + "]><span></span><![endif]-->";

					if (div.getElementsByTagName("span").length) {
						div = null;

						return i;
					}
				}
			}

			return undefined;
		})();

		/* rAF shim. Gist: https://gist.github.com/julianshapiro/9497513 */
		var rAFShim = (function() {
			var timeLast = 0;

			return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
					var timeCurrent = (new Date()).getTime(),
						timeDelta;

					/* Dynamically set delay on a per-tick basis to match 60fps. */
					/* Technique by Erik Moller. MIT license: https://gist.github.com/paulirish/1579671 */
					timeDelta = Math.max(0, 16 - (timeCurrent - timeLast));
					timeLast = timeCurrent + timeDelta;

					return setTimeout(function() { callback(timeCurrent + timeDelta); }, timeDelta);
				};
		})();

		/* Array compacting. Copyright Lo-Dash. MIT License: https://github.com/lodash/lodash/blob/master/LICENSE.txt */
		function compactSparseArray (array) {
			var index = -1,
				length = array ? array.length : 0,
				result = [];

			while (++index < length) {
				var value = array[index];

				if (value) {
					result.push(value);
				}
			}

			return result;
		}

		function sanitizeElements (elements) {
			/* Unwrap jQuery/Zepto objects. */
			if (Type.isWrapped(elements)) {
				elements = [].slice.call(elements);
				/* Wrap a single element in an array so that $.each() can iterate with the element instead of its node's children. */
			} else if (Type.isNode(elements)) {
				elements = [ elements ];
			}

			return elements;
		}

		var Type = {
			isString: function (variable) {
				return (typeof variable === "string");
			},
			isArray: Array.isArray || function (variable) {
				return Object.prototype.toString.call(variable) === "[object Array]";
			},
			isFunction: function (variable) {
				return Object.prototype.toString.call(variable) === "[object Function]";
			},
			isNode: function (variable) {
				return variable && variable.nodeType;
			},
			/* Copyright Martin Bohm. MIT License: https://gist.github.com/Tomalak/818a78a226a0738eaade */
			isNodeList: function (variable) {
				return typeof variable === "object" &&
					/^\[object (HTMLCollection|NodeList|Object)\]$/.test(Object.prototype.toString.call(variable)) &&
					variable.length !== undefined &&
					(variable.length === 0 || (typeof variable[0] === "object" && variable[0].nodeType > 0));
			},
			/* Determine if variable is a wrapped jQuery or Zepto element. */
			isWrapped: function (variable) {
				return variable && (variable.jquery || (window.Zepto && window.Zepto.zepto.isZ(variable)));
			},
			isSVG: function (variable) {
				return window.SVGElement && (variable instanceof window.SVGElement);
			},
			isEmptyObject: function (variable) {
				for (var name in variable) {
					return false;
				}

				return true;
			}
		};

		/*****************
		 Dependencies
		 *****************/

		var $,
			isJQuery = false;

		if (global.fn && global.fn.jquery) {
			$ = global;
			isJQuery = true;
		} else {
			$ = window.Velocity.Utilities;
		}

		if (IE <= 8 && !isJQuery) {
			throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity.");
		} else if (IE <= 7) {
			/* Revert to jQuery's $.animate(), and lose Velocity's extra features. */
			jQuery.fn.velocity = jQuery.fn.animate;

			/* Now that $.fn.velocity is aliased, abort this Velocity declaration. */
			return;
		}

		/*****************
		 Constants
		 *****************/

		var DURATION_DEFAULT = 400,
			EASING_DEFAULT = "swing";

		/*************
		 State
		 *************/

		var Velocity = {
			/* Container for page-wide Velocity state data. */
			State: {
				/* Detect mobile devices to determine if mobileHA should be turned on. */
				isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
				/* The mobileHA option's behavior changes on older Android devices (Gingerbread, versions 2.3.3-2.3.7). */
				isAndroid: /Android/i.test(navigator.userAgent),
				isGingerbread: /Android 2\.3\.[3-7]/i.test(navigator.userAgent),
				isChrome: window.chrome,
				isFirefox: /Firefox/i.test(navigator.userAgent),
				/* Create a cached element for re-use when checking for CSS property prefixes. */
				prefixElement: document.createElement("div"),
				/* Cache every prefix match to avoid repeating lookups. */
				prefixMatches: {},
				/* Cache the anchor used for animating window scrolling. */
				scrollAnchor: null,
				/* Cache the browser-specific property names associated with the scroll anchor. */
				scrollPropertyLeft: null,
				scrollPropertyTop: null,
				/* Keep track of whether our RAF tick is running. */
				isTicking: false,
				/* Container for every in-progress call to Velocity. */
				calls: []
			},
			/* Velocity's custom CSS stack. Made global for unit testing. */
			CSS: { /* Defined below. */ },
			/* A shim of the jQuery utility functions used by Velocity -- provided by Velocity's optional jQuery shim. */
			Utilities: $,
			/* Container for the user's custom animation redirects that are referenced by name in place of the properties map argument. */
			Redirects: { /* Manually registered by the user. */ },
			Easings: { /* Defined below. */ },
			/* Attempt to use ES6 Promises by default. Users can override this with a third-party promises library. */
			Promise: window.Promise,
			/* Velocity option defaults, which can be overriden by the user. */
			defaults: {
				queue: "",
				duration: DURATION_DEFAULT,
				easing: EASING_DEFAULT,
				begin: undefined,
				complete: undefined,
				progress: undefined,
				display: undefined,
				visibility: undefined,
				loop: false,
				delay: false,
				mobileHA: true,
				/* Advanced: Set to false to prevent property values from being cached between consecutive Velocity-initiated chain calls. */
				_cacheValues: true
			},
			/* A design goal of Velocity is to cache data wherever possible in order to avoid DOM requerying. Accordingly, each element has a data cache. */
			init: function (element) {
				$.data(element, "velocity", {
					/* Store whether this is an SVG element, since its properties are retrieved and updated differently than standard HTML elements. */
					isSVG: Type.isSVG(element),
					/* Keep track of whether the element is currently being animated by Velocity.
					 This is used to ensure that property values are not transferred between non-consecutive (stale) calls. */
					isAnimating: false,
					/* A reference to the element's live computedStyle object. Learn more here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */
					computedStyle: null,
					/* Tween data is cached for each animation on the element so that data can be passed across calls --
					 in particular, end values are used as subsequent start values in consecutive Velocity calls. */
					tweensContainer: null,
					/* The full root property values of each CSS hook being animated on this element are cached so that:
					 1) Concurrently-animating hooks sharing the same root can have their root values' merged into one while tweening.
					 2) Post-hook-injection root values can be transferred over to consecutively chained Velocity calls as starting root values. */
					rootPropertyValueCache: {},
					/* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */
					transformCache: {}
				});
			},
			/* A parallel to jQuery's $.css(), used for getting/setting Velocity's hooked CSS properties. */
			hook: null, /* Defined below. */
			/* Velocity-wide animation time remapping for testing purposes. */
			mock: false,
			version: { major: 1, minor: 2, patch: 2 },
			/* Set to 1 or 2 (most verbose) to output debug info to console. */
			debug: false
		};

		/* Retrieve the appropriate scroll anchor and property name for the browser: https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY */
		if (window.pageYOffset !== undefined) {
			Velocity.State.scrollAnchor = window;
			Velocity.State.scrollPropertyLeft = "pageXOffset";
			Velocity.State.scrollPropertyTop = "pageYOffset";
		} else {
			Velocity.State.scrollAnchor = document.documentElement || document.body.parentNode || document.body;
			Velocity.State.scrollPropertyLeft = "scrollLeft";
			Velocity.State.scrollPropertyTop = "scrollTop";
		}

		/* Shorthand alias for jQuery's $.data() utility. */
		function Data (element) {
			/* Hardcode a reference to the plugin name. */
			var response = $.data(element, "velocity");

			/* jQuery <=1.4.2 returns null instead of undefined when no match is found. We normalize this behavior. */
			return response === null ? undefined : response;
		};

		/**************
		 Easing
		 **************/

		/* Step easing generator. */
		function generateStep (steps) {
			return function (p) {
				return Math.round(p * steps) * (1 / steps);
			};
		}

		/* Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */
		function generateBezier (mX1, mY1, mX2, mY2) {
			var NEWTON_ITERATIONS = 4,
				NEWTON_MIN_SLOPE = 0.001,
				SUBDIVISION_PRECISION = 0.0000001,
				SUBDIVISION_MAX_ITERATIONS = 10,
				kSplineTableSize = 11,
				kSampleStepSize = 1.0 / (kSplineTableSize - 1.0),
				float32ArraySupported = "Float32Array" in window;

			/* Must contain four arguments. */
			if (arguments.length !== 4) {
				return false;
			}

			/* Arguments must be numbers. */
			for (var i = 0; i < 4; ++i) {
				if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) {
					return false;
				}
			}

			/* X values must be in the [0, 1] range. */
			mX1 = Math.min(mX1, 1);
			mX2 = Math.min(mX2, 1);
			mX1 = Math.max(mX1, 0);
			mX2 = Math.max(mX2, 0);

			var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);

			function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
			function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
			function C (aA1)      { return 3.0 * aA1; }

			function calcBezier (aT, aA1, aA2) {
				return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
			}

			function getSlope (aT, aA1, aA2) {
				return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
			}

			function newtonRaphsonIterate (aX, aGuessT) {
				for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
					var currentSlope = getSlope(aGuessT, mX1, mX2);

					if (currentSlope === 0.0) return aGuessT;

					var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
					aGuessT -= currentX / currentSlope;
				}

				return aGuessT;
			}

			function calcSampleValues () {
				for (var i = 0; i < kSplineTableSize; ++i) {
					mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
				}
			}

			function binarySubdivide (aX, aA, aB) {
				var currentX, currentT, i = 0;

				do {
					currentT = aA + (aB - aA) / 2.0;
					currentX = calcBezier(currentT, mX1, mX2) - aX;
					if (currentX > 0.0) {
						aB = currentT;
					} else {
						aA = currentT;
					}
				} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);

				return currentT;
			}

			function getTForX (aX) {
				var intervalStart = 0.0,
					currentSample = 1,
					lastSample = kSplineTableSize - 1;

				for (; currentSample != lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
					intervalStart += kSampleStepSize;
				}

				--currentSample;

				var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample+1] - mSampleValues[currentSample]),
					guessForT = intervalStart + dist * kSampleStepSize,
					initialSlope = getSlope(guessForT, mX1, mX2);

				if (initialSlope >= NEWTON_MIN_SLOPE) {
					return newtonRaphsonIterate(aX, guessForT);
				} else if (initialSlope == 0.0) {
					return guessForT;
				} else {
					return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize);
				}
			}

			var _precomputed = false;

			function precompute() {
				_precomputed = true;
				if (mX1 != mY1 || mX2 != mY2) calcSampleValues();
			}

			var f = function (aX) {
				if (!_precomputed) precompute();
				if (mX1 === mY1 && mX2 === mY2) return aX;
				if (aX === 0) return 0;
				if (aX === 1) return 1;

				return calcBezier(getTForX(aX), mY1, mY2);
			};

			f.getControlPoints = function() { return [{ x: mX1, y: mY1 }, { x: mX2, y: mY2 }]; };

			var str = "generateBezier(" + [mX1, mY1, mX2, mY2] + ")";
			f.toString = function () { return str; };

			return f;
		}

		/* Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */
		/* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass
		 then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */
		var generateSpringRK4 = (function () {
			function springAccelerationForState (state) {
				return (-state.tension * state.x) - (state.friction * state.v);
			}

			function springEvaluateStateWithDerivative (initialState, dt, derivative) {
				var state = {
					x: initialState.x + derivative.dx * dt,
					v: initialState.v + derivative.dv * dt,
					tension: initialState.tension,
					friction: initialState.friction
				};

				return { dx: state.v, dv: springAccelerationForState(state) };
			}

			function springIntegrateState (state, dt) {
				var a = {
						dx: state.v,
						dv: springAccelerationForState(state)
					},
					b = springEvaluateStateWithDerivative(state, dt * 0.5, a),
					c = springEvaluateStateWithDerivative(state, dt * 0.5, b),
					d = springEvaluateStateWithDerivative(state, dt, c),
					dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),
					dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);

				state.x = state.x + dxdt * dt;
				state.v = state.v + dvdt * dt;

				return state;
			}

			return function springRK4Factory (tension, friction, duration) {

				var initState = {
						x: -1,
						v: 0,
						tension: null,
						friction: null
					},
					path = [0],
					time_lapsed = 0,
					tolerance = 1 / 10000,
					DT = 16 / 1000,
					have_duration, dt, last_state;

				tension = parseFloat(tension) || 500;
				friction = parseFloat(friction) || 20;
				duration = duration || null;

				initState.tension = tension;
				initState.friction = friction;

				have_duration = duration !== null;

				/* Calculate the actual time it takes for this animation to complete with the provided conditions. */
				if (have_duration) {
					/* Run the simulation without a duration. */
					time_lapsed = springRK4Factory(tension, friction);
					/* Compute the adjusted time delta. */
					dt = time_lapsed / duration * DT;
				} else {
					dt = DT;
				}

				while (true) {
					/* Next/step function .*/
					last_state = springIntegrateState(last_state || initState, dt);
					/* Store the position. */
					path.push(1 + last_state.x);
					time_lapsed += 16;
					/* If the change threshold is reached, break. */
					if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {
						break;
					}
				}

				/* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the
				 computed path and returns a snapshot of the position according to a given percentComplete. */
				return !have_duration ? time_lapsed : function(percentComplete) { return path[ (percentComplete * (path.length - 1)) | 0 ]; };
			};
		}());

		/* jQuery easings. */
		Velocity.Easings = {
			linear: function(p) { return p; },
			swing: function(p) { return 0.5 - Math.cos( p * Math.PI ) / 2 },
			/* Bonus "spring" easing, which is a less exaggerated version of easeInOutElastic. */
			spring: function(p) { return 1 - (Math.cos(p * 4.5 * Math.PI) * Math.exp(-p * 6)); }
		};

		/* CSS3 and Robert Penner easings. */
		$.each(
			[
				[ "ease", [ 0.25, 0.1, 0.25, 1.0 ] ],
				[ "ease-in", [ 0.42, 0.0, 1.00, 1.0 ] ],
				[ "ease-out", [ 0.00, 0.0, 0.58, 1.0 ] ],
				[ "ease-in-out", [ 0.42, 0.0, 0.58, 1.0 ] ],
				[ "easeInSine", [ 0.47, 0, 0.745, 0.715 ] ],
				[ "easeOutSine", [ 0.39, 0.575, 0.565, 1 ] ],
				[ "easeInOutSine", [ 0.445, 0.05, 0.55, 0.95 ] ],
				[ "easeInQuad", [ 0.55, 0.085, 0.68, 0.53 ] ],
				[ "easeOutQuad", [ 0.25, 0.46, 0.45, 0.94 ] ],
				[ "easeInOutQuad", [ 0.455, 0.03, 0.515, 0.955 ] ],
				[ "easeInCubic", [ 0.55, 0.055, 0.675, 0.19 ] ],
				[ "easeOutCubic", [ 0.215, 0.61, 0.355, 1 ] ],
				[ "easeInOutCubic", [ 0.645, 0.045, 0.355, 1 ] ],
				[ "easeInQuart", [ 0.895, 0.03, 0.685, 0.22 ] ],
				[ "easeOutQuart", [ 0.165, 0.84, 0.44, 1 ] ],
				[ "easeInOutQuart", [ 0.77, 0, 0.175, 1 ] ],
				[ "easeInQuint", [ 0.755, 0.05, 0.855, 0.06 ] ],
				[ "easeOutQuint", [ 0.23, 1, 0.32, 1 ] ],
				[ "easeInOutQuint", [ 0.86, 0, 0.07, 1 ] ],
				[ "easeInExpo", [ 0.95, 0.05, 0.795, 0.035 ] ],
				[ "easeOutExpo", [ 0.19, 1, 0.22, 1 ] ],
				[ "easeInOutExpo", [ 1, 0, 0, 1 ] ],
				[ "easeInCirc", [ 0.6, 0.04, 0.98, 0.335 ] ],
				[ "easeOutCirc", [ 0.075, 0.82, 0.165, 1 ] ],
				[ "easeInOutCirc", [ 0.785, 0.135, 0.15, 0.86 ] ]
			], function(i, easingArray) {
				Velocity.Easings[easingArray[0]] = generateBezier.apply(null, easingArray[1]);
			});

		/* Determine the appropriate easing type given an easing input. */
		function getEasing(value, duration) {
			var easing = value;

			/* The easing option can either be a string that references a pre-registered easing,
			 or it can be a two-/four-item array of integers to be converted into a bezier/spring function. */
			if (Type.isString(value)) {
				/* Ensure that the easing has been assigned to jQuery's Velocity.Easings object. */
				if (!Velocity.Easings[value]) {
					easing = false;
				}
			} else if (Type.isArray(value) && value.length === 1) {
				easing = generateStep.apply(null, value);
			} else if (Type.isArray(value) && value.length === 2) {
				/* springRK4 must be passed the animation's duration. */
				/* Note: If the springRK4 array contains non-numbers, generateSpringRK4() returns an easing
				 function generated with default tension and friction values. */
				easing = generateSpringRK4.apply(null, value.concat([ duration ]));
			} else if (Type.isArray(value) && value.length === 4) {
				/* Note: If the bezier array contains non-numbers, generateBezier() returns false. */
				easing = generateBezier.apply(null, value);
			} else {
				easing = false;
			}

			/* Revert to the Velocity-wide default easing type, or fall back to "swing" (which is also jQuery's default)
			 if the Velocity-wide default has been incorrectly modified. */
			if (easing === false) {
				if (Velocity.Easings[Velocity.defaults.easing]) {
					easing = Velocity.defaults.easing;
				} else {
					easing = EASING_DEFAULT;
				}
			}

			return easing;
		}

		/*****************
		 CSS Stack
		 *****************/

		/* The CSS object is a highly condensed and performant CSS stack that fully replaces jQuery's.
		 It handles the validation, getting, and setting of both standard CSS properties and CSS property hooks. */
		/* Note: A "CSS" shorthand is aliased so that our code is easier to read. */
		var CSS = Velocity.CSS = {

			/*************
			 RegEx
			 *************/

			RegEx: {
				isHex: /^#([A-f\d]{3}){1,2}$/i,
				/* Unwrap a property value's surrounding text, e.g. "rgba(4, 3, 2, 1)" ==> "4, 3, 2, 1" and "rect(4px 3px 2px 1px)" ==> "4px 3px 2px 1px". */
				valueUnwrap: /^[A-z]+\((.*)\)$/i,
				wrappedValueAlreadyExtracted: /[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/,
				/* Split a multi-value property into an array of subvalues, e.g. "rgba(4, 3, 2, 1) 4px 3px 2px 1px" ==> [ "rgba(4, 3, 2, 1)", "4px", "3px", "2px", "1px" ]. */
				valueSplit: /([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/ig
			},

			/************
			 Lists
			 ************/

			Lists: {
				colors: [ "fill", "stroke", "stopColor", "color", "backgroundColor", "borderColor", "borderTopColor", "borderRightColor", "borderBottomColor", "borderLeftColor", "outlineColor" ],
				transformsBase: [ "translateX", "translateY", "scale", "scaleX", "scaleY", "skewX", "skewY", "rotateZ" ],
				transforms3D: [ "transformPerspective", "translateZ", "scaleZ", "rotateX", "rotateY" ]
			},

			/************
			 Hooks
			 ************/

			/* Hooks allow a subproperty (e.g. "boxShadowBlur") of a compound-value CSS property
			 (e.g. "boxShadow: X Y Blur Spread Color") to be animated as if it were a discrete property. */
			/* Note: Beyond enabling fine-grained property animation, hooking is necessary since Velocity only
			 tweens properties with single numeric values; unlike CSS transitions, Velocity does not interpolate compound-values. */
			Hooks: {
				/********************
				 Registration
				 ********************/

				/* Templates are a concise way of indicating which subproperties must be individually registered for each compound-value CSS property. */
				/* Each template consists of the compound-value's base name, its constituent subproperty names, and those subproperties' default values. */
				templates: {
					"textShadow": [ "Color X Y Blur", "black 0px 0px 0px" ],
					"boxShadow": [ "Color X Y Blur Spread", "black 0px 0px 0px 0px" ],
					"clip": [ "Top Right Bottom Left", "0px 0px 0px 0px" ],
					"backgroundPosition": [ "X Y", "0% 0%" ],
					"transformOrigin": [ "X Y Z", "50% 50% 0px" ],
					"perspectiveOrigin": [ "X Y", "50% 50%" ]
				},

				/* A "registered" hook is one that has been converted from its template form into a live,
				 tweenable property. It contains data to associate it with its root property. */
				registered: {
					/* Note: A registered hook looks like this ==> textShadowBlur: [ "textShadow", 3 ],
					 which consists of the subproperty's name, the associated root property's name,
					 and the subproperty's position in the root's value. */
				},
				/* Convert the templates into individual hooks then append them to the registered object above. */
				register: function () {
					/* Color hooks registration: Colors are defaulted to white -- as opposed to black -- since colors that are
					 currently set to "transparent" default to their respective template below when color-animated,
					 and white is typically a closer match to transparent than black is. An exception is made for text ("color"),
					 which is almost always set closer to black than white. */
					for (var i = 0; i < CSS.Lists.colors.length; i++) {
						var rgbComponents = (CSS.Lists.colors[i] === "color") ? "0 0 0 1" : "255 255 255 1";
						CSS.Hooks.templates[CSS.Lists.colors[i]] = [ "Red Green Blue Alpha", rgbComponents ];
					}

					var rootProperty,
						hookTemplate,
						hookNames;

					/* In IE, color values inside compound-value properties are positioned at the end the value instead of at the beginning.
					 Thus, we re-arrange the templates accordingly. */
					if (IE) {
						for (rootProperty in CSS.Hooks.templates) {
							hookTemplate = CSS.Hooks.templates[rootProperty];
							hookNames = hookTemplate[0].split(" ");

							var defaultValues = hookTemplate[1].match(CSS.RegEx.valueSplit);

							if (hookNames[0] === "Color") {
								/* Reposition both the hook's name and its default value to the end of their respective strings. */
								hookNames.push(hookNames.shift());
								defaultValues.push(defaultValues.shift());

								/* Replace the existing template for the hook's root property. */
								CSS.Hooks.templates[rootProperty] = [ hookNames.join(" "), defaultValues.join(" ") ];
							}
						}
					}

					/* Hook registration. */
					for (rootProperty in CSS.Hooks.templates) {
						hookTemplate = CSS.Hooks.templates[rootProperty];
						hookNames = hookTemplate[0].split(" ");

						for (var i in hookNames) {
							var fullHookName = rootProperty + hookNames[i],
								hookPosition = i;

							/* For each hook, register its full name (e.g. textShadowBlur) with its root property (e.g. textShadow)
							 and the hook's position in its template's default value string. */
							CSS.Hooks.registered[fullHookName] = [ rootProperty, hookPosition ];
						}
					}
				},

				/*****************************
				 Injection and Extraction
				 *****************************/

				/* Look up the root property associated with the hook (e.g. return "textShadow" for "textShadowBlur"). */
				/* Since a hook cannot be set directly (the browser won't recognize it), style updating for hooks is routed through the hook's root property. */
				getRoot: function (property) {
					var hookData = CSS.Hooks.registered[property];

					if (hookData) {
						return hookData[0];
					} else {
						/* If there was no hook match, return the property name untouched. */
						return property;
					}
				},
				/* Convert any rootPropertyValue, null or otherwise, into a space-delimited list of hook values so that
				 the targeted hook can be injected or extracted at its standard position. */
				cleanRootPropertyValue: function(rootProperty, rootPropertyValue) {
					/* If the rootPropertyValue is wrapped with "rgb()", "clip()", etc., remove the wrapping to normalize the value before manipulation. */
					if (CSS.RegEx.valueUnwrap.test(rootPropertyValue)) {
						rootPropertyValue = rootPropertyValue.match(CSS.RegEx.valueUnwrap)[1];
					}

					/* If rootPropertyValue is a CSS null-value (from which there's inherently no hook value to extract),
					 default to the root's default value as defined in CSS.Hooks.templates. */
					/* Note: CSS null-values include "none", "auto", and "transparent". They must be converted into their
					 zero-values (e.g. textShadow: "none" ==> textShadow: "0px 0px 0px black") for hook manipulation to proceed. */
					if (CSS.Values.isCSSNullValue(rootPropertyValue)) {
						rootPropertyValue = CSS.Hooks.templates[rootProperty][1];
					}

					return rootPropertyValue;
				},
				/* Extracted the hook's value from its root property's value. This is used to get the starting value of an animating hook. */
				extractValue: function (fullHookName, rootPropertyValue) {
					var hookData = CSS.Hooks.registered[fullHookName];

					if (hookData) {
						var hookRoot = hookData[0],
							hookPosition = hookData[1];

						rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue);

						/* Split rootPropertyValue into its constituent hook values then grab the desired hook at its standard position. */
						return rootPropertyValue.toString().match(CSS.RegEx.valueSplit)[hookPosition];
					} else {
						/* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */
						return rootPropertyValue;
					}
				},
				/* Inject the hook's value into its root property's value. This is used to piece back together the root property
				 once Velocity has updated one of its individually hooked values through tweening. */
				injectValue: function (fullHookName, hookValue, rootPropertyValue) {
					var hookData = CSS.Hooks.registered[fullHookName];

					if (hookData) {
						var hookRoot = hookData[0],
							hookPosition = hookData[1],
							rootPropertyValueParts,
							rootPropertyValueUpdated;

						rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue);

						/* Split rootPropertyValue into its individual hook values, replace the targeted value with hookValue,
						 then reconstruct the rootPropertyValue string. */
						rootPropertyValueParts = rootPropertyValue.toString().match(CSS.RegEx.valueSplit);
						rootPropertyValueParts[hookPosition] = hookValue;
						rootPropertyValueUpdated = rootPropertyValueParts.join(" ");

						return rootPropertyValueUpdated;
					} else {
						/* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */
						return rootPropertyValue;
					}
				}
			},

			/*******************
			 Normalizations
			 *******************/

			/* Normalizations standardize CSS property manipulation by pollyfilling browser-specific implementations (e.g. opacity)
			 and reformatting special properties (e.g. clip, rgba) to look like standard ones. */
			Normalizations: {
				/* Normalizations are passed a normalization target (either the property's name, its extracted value, or its injected value),
				 the targeted element (which may need to be queried), and the targeted property value. */
				registered: {
					clip: function (type, element, propertyValue) {
						switch (type) {
							case "name":
								return "clip";
							/* Clip needs to be unwrapped and stripped of its commas during extraction. */
							case "extract":
								var extracted;

								/* If Velocity also extracted this value, skip extraction. */
								if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
									extracted = propertyValue;
								} else {
									/* Remove the "rect()" wrapper. */
									extracted = propertyValue.toString().match(CSS.RegEx.valueUnwrap);

									/* Strip off commas. */
									extracted = extracted ? extracted[1].replace(/,(\s+)?/g, " ") : propertyValue;
								}

								return extracted;
							/* Clip needs to be re-wrapped during injection. */
							case "inject":
								return "rect(" + propertyValue + ")";
						}
					},

					blur: function(type, element, propertyValue) {
						switch (type) {
							case "name":
								return Velocity.State.isFirefox ? "filter" : "-webkit-filter";
							case "extract":
								var extracted = parseFloat(propertyValue);

								/* If extracted is NaN, meaning the value isn't already extracted. */
								if (!(extracted || extracted === 0)) {
									var blurComponent = propertyValue.toString().match(/blur\(([0-9]+[A-z]+)\)/i);

									/* If the filter string had a blur component, return just the blur value and unit type. */
									if (blurComponent) {
										extracted = blurComponent[1];
										/* If the component doesn't exist, default blur to 0. */
									} else {
										extracted = 0;
									}
								}

								return extracted;
							/* Blur needs to be re-wrapped during injection. */
							case "inject":
								/* For the blur effect to be fully de-applied, it needs to be set to "none" instead of 0. */
								if (!parseFloat(propertyValue)) {
									return "none";
								} else {
									return "blur(" + propertyValue + ")";
								}
						}
					},

					/* <=IE8 do not support the standard opacity property. They use filter:alpha(opacity=INT) instead. */
					opacity: function (type, element, propertyValue) {
						if (IE <= 8) {
							switch (type) {
								case "name":
									return "filter";
								case "extract":
									/* <=IE8 return a "filter" value of "alpha(opacity=\d{1,3})".
									 Extract the value and convert it to a decimal value to match the standard CSS opacity property's formatting. */
									var extracted = propertyValue.toString().match(/alpha\(opacity=(.*)\)/i);

									if (extracted) {
										/* Convert to decimal value. */
										propertyValue = extracted[1] / 100;
									} else {
										/* When extracting opacity, default to 1 since a null value means opacity hasn't been set. */
										propertyValue = 1;
									}

									return propertyValue;
								case "inject":
									/* Opacified elements are required to have their zoom property set to a non-zero value. */
									element.style.zoom = 1;

									/* Setting the filter property on elements with certain font property combinations can result in a
									 highly unappealing ultra-bolding effect. There's no way to remedy this throughout a tween, but dropping the
									 value altogether (when opacity hits 1) at leasts ensures that the glitch is gone post-tweening. */
									if (parseFloat(propertyValue) >= 1) {
										return "";
									} else {
										/* As per the filter property's spec, convert the decimal value to a whole number and wrap the value. */
										return "alpha(opacity=" + parseInt(parseFloat(propertyValue) * 100, 10) + ")";
									}
							}
							/* With all other browsers, normalization is not required; return the same values that were passed in. */
						} else {
							switch (type) {
								case "name":
									return "opacity";
								case "extract":
									return propertyValue;
								case "inject":
									return propertyValue;
							}
						}
					}
				},

				/*****************************
				 Batched Registrations
				 *****************************/

				/* Note: Batched normalizations extend the CSS.Normalizations.registered object. */
				register: function () {

					/*****************
					 Transforms
					 *****************/

					/* Transforms are the subproperties contained by the CSS "transform" property. Transforms must undergo normalization
					 so that they can be referenced in a properties map by their individual names. */
					/* Note: When transforms are "set", they are actually assigned to a per-element transformCache. When all transform
					 setting is complete complete, CSS.flushTransformCache() must be manually called to flush the values to the DOM.
					 Transform setting is batched in this way to improve performance: the transform style only needs to be updated
					 once when multiple transform subproperties are being animated simultaneously. */
					/* Note: IE9 and Android Gingerbread have support for 2D -- but not 3D -- transforms. Since animating unsupported
					 transform properties results in the browser ignoring the *entire* transform string, we prevent these 3D values
					 from being normalized for these browsers so that tweening skips these properties altogether
					 (since it will ignore them as being unsupported by the browser.) */
					if (!(IE <= 9) && !Velocity.State.isGingerbread) {
						/* Note: Since the standalone CSS "perspective" property and the CSS transform "perspective" subproperty
						 share the same name, the latter is given a unique token within Velocity: "transformPerspective". */
						CSS.Lists.transformsBase = CSS.Lists.transformsBase.concat(CSS.Lists.transforms3D);
					}

					for (var i = 0; i < CSS.Lists.transformsBase.length; i++) {
						/* Wrap the dynamically generated normalization function in a new scope so that transformName's value is
						 paired with its respective function. (Otherwise, all functions would take the final for loop's transformName.) */
						(function() {
							var transformName = CSS.Lists.transformsBase[i];

							CSS.Normalizations.registered[transformName] = function (type, element, propertyValue) {
								switch (type) {
									/* The normalized property name is the parent "transform" property -- the property that is actually set in CSS. */
									case "name":
										return "transform";
									/* Transform values are cached onto a per-element transformCache object. */
									case "extract":
										/* If this transform has yet to be assigned a value, return its null value. */
										if (Data(element) === undefined || Data(element).transformCache[transformName] === undefined) {
											/* Scale CSS.Lists.transformsBase default to 1 whereas all other transform properties default to 0. */
											return /^scale/i.test(transformName) ? 1 : 0;
											/* When transform values are set, they are wrapped in parentheses as per the CSS spec.
											 Thus, when extracting their values (for tween calculations), we strip off the parentheses. */
										} else {
											return Data(element).transformCache[transformName].replace(/[()]/g, "");
										}
									case "inject":
										var invalid = false;

										/* If an individual transform property contains an unsupported unit type, the browser ignores the *entire* transform property.
										 Thus, protect users from themselves by skipping setting for transform values supplied with invalid unit types. */
										/* Switch on the base transform type; ignore the axis by removing the last letter from the transform's name. */
										switch (transformName.substr(0, transformName.length - 1)) {
											/* Whitelist unit types for each transform. */
											case "translate":
												invalid = !/(%|px|em|rem|vw|vh|\d)$/i.test(propertyValue);
												break;
											/* Since an axis-free "scale" property is supported as well, a little hack is used here to detect it by chopping off its last letter. */
											case "scal":
											case "scale":
												/* Chrome on Android has a bug in which scaled elements blur if their initial scale
												 value is below 1 (which can happen with forcefeeding). Thus, we detect a yet-unset scale property
												 and ensure that its first value is always 1. More info: http://stackoverflow.com/questions/10417890/css3-animations-with-transform-causes-blurred-elements-on-webkit/10417962#10417962 */
												if (Velocity.State.isAndroid && Data(element).transformCache[transformName] === undefined && propertyValue < 1) {
													propertyValue = 1;
												}

												invalid = !/(\d)$/i.test(propertyValue);
												break;
											case "skew":
												invalid = !/(deg|\d)$/i.test(propertyValue);
												break;
											case "rotate":
												invalid = !/(deg|\d)$/i.test(propertyValue);
												break;
										}

										if (!invalid) {
											/* As per the CSS spec, wrap the value in parentheses. */
											Data(element).transformCache[transformName] = "(" + propertyValue + ")";
										}

										/* Although the value is set on the transformCache object, return the newly-updated value for the calling code to process as normal. */
										return Data(element).transformCache[transformName];
								}
							};
						})();
					}

					/*************
					 Colors
					 *************/

					/* Since Velocity only animates a single numeric value per property, color animation is achieved by hooking the individual RGBA components of CSS color properties.
					 Accordingly, color values must be normalized (e.g. "#ff0000", "red", and "rgb(255, 0, 0)" ==> "255 0 0 1") so that their components can be injected/extracted by CSS.Hooks logic. */
					for (var i = 0; i < CSS.Lists.colors.length; i++) {
						/* Wrap the dynamically generated normalization function in a new scope so that colorName's value is paired with its respective function.
						 (Otherwise, all functions would take the final for loop's colorName.) */
						(function () {
							var colorName = CSS.Lists.colors[i];

							/* Note: In IE<=8, which support rgb but not rgba, color properties are reverted to rgb by stripping off the alpha component. */
							CSS.Normalizations.registered[colorName] = function(type, element, propertyValue) {
								switch (type) {
									case "name":
										return colorName;
									/* Convert all color values into the rgb format. (Old IE can return hex values and color names instead of rgb/rgba.) */
									case "extract":
										var extracted;

										/* If the color is already in its hookable form (e.g. "255 255 255 1") due to having been previously extracted, skip extraction. */
										if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
											extracted = propertyValue;
										} else {
											var converted,
												colorNames = {
													black: "rgb(0, 0, 0)",
													blue: "rgb(0, 0, 255)",
													gray: "rgb(128, 128, 128)",
													green: "rgb(0, 128, 0)",
													red: "rgb(255, 0, 0)",
													white: "rgb(255, 255, 255)"
												};

											/* Convert color names to rgb. */
											if (/^[A-z]+$/i.test(propertyValue)) {
												if (colorNames[propertyValue] !== undefined) {
													converted = colorNames[propertyValue]
												} else {
													/* If an unmatched color name is provided, default to black. */
													converted = colorNames.black;
												}
												/* Convert hex values to rgb. */
											} else if (CSS.RegEx.isHex.test(propertyValue)) {
												converted = "rgb(" + CSS.Values.hexToRgb(propertyValue).join(" ") + ")";
												/* If the provided color doesn't match any of the accepted color formats, default to black. */
											} else if (!(/^rgba?\(/i.test(propertyValue))) {
												converted = colorNames.black;
											}

											/* Remove the surrounding "rgb/rgba()" string then replace commas with spaces and strip
											 repeated spaces (in case the value included spaces to begin with). */
											extracted = (converted || propertyValue).toString().match(CSS.RegEx.valueUnwrap)[1].replace(/,(\s+)?/g, " ");
										}

										/* So long as this isn't <=IE8, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
										if (!(IE <= 8) && extracted.split(" ").length === 3) {
											extracted += " 1";
										}

										return extracted;
									case "inject":
										/* If this is IE<=8 and an alpha component exists, strip it off. */
										if (IE <= 8) {
											if (propertyValue.split(" ").length === 4) {
												propertyValue = propertyValue.split(/\s+/).slice(0, 3).join(" ");
											}
											/* Otherwise, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
										} else if (propertyValue.split(" ").length === 3) {
											propertyValue += " 1";
										}

										/* Re-insert the browser-appropriate wrapper("rgb/rgba()"), insert commas, and strip off decimal units
										 on all values but the fourth (R, G, and B only accept whole numbers). */
										return (IE <= 8 ? "rgb" : "rgba") + "(" + propertyValue.replace(/\s+/g, ",").replace(/\.(\d)+(?=,)/g, "") + ")";
								}
							};
						})();
					}
				}
			},

			/************************
			 CSS Property Names
			 ************************/

			Names: {
				/* Camelcase a property name into its JavaScript notation (e.g. "background-color" ==> "backgroundColor").
				 Camelcasing is used to normalize property names between and across calls. */
				camelCase: function (property) {
					return property.replace(/-(\w)/g, function (match, subMatch) {
						return subMatch.toUpperCase();
					});
				},

				/* For SVG elements, some properties (namely, dimensional ones) are GET/SET via the element's HTML attributes (instead of via CSS styles). */
				SVGAttribute: function (property) {
					var SVGAttributes = "width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";

					/* Certain browsers require an SVG transform to be applied as an attribute. (Otherwise, application via CSS is preferable due to 3D support.) */
					if (IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) {
						SVGAttributes += "|transform";
					}

					return new RegExp("^(" + SVGAttributes + ")$", "i").test(property);
				},

				/* Determine whether a property should be set with a vendor prefix. */
				/* If a prefixed version of the property exists, return it. Otherwise, return the original property name.
				 If the property is not at all supported by the browser, return a false flag. */
				prefixCheck: function (property) {
					/* If this property has already been checked, return the cached value. */
					if (Velocity.State.prefixMatches[property]) {
						return [ Velocity.State.prefixMatches[property], true ];
					} else {
						var vendors = [ "", "Webkit", "Moz", "ms", "O" ];

						for (var i = 0, vendorsLength = vendors.length; i < vendorsLength; i++) {
							var propertyPrefixed;

							if (i === 0) {
								propertyPrefixed = property;
							} else {
								/* Capitalize the first letter of the property to conform to JavaScript vendor prefix notation (e.g. webkitFilter). */
								propertyPrefixed = vendors[i] + property.replace(/^\w/, function(match) { return match.toUpperCase(); });
							}

							/* Check if the browser supports this property as prefixed. */
							if (Type.isString(Velocity.State.prefixElement.style[propertyPrefixed])) {
								/* Cache the match. */
								Velocity.State.prefixMatches[property] = propertyPrefixed;

								return [ propertyPrefixed, true ];
							}
						}

						/* If the browser doesn't support this property in any form, include a false flag so that the caller can decide how to proceed. */
						return [ property, false ];
					}
				}
			},

			/************************
			 CSS Property Values
			 ************************/

			Values: {
				/* Hex to RGB conversion. Copyright Tim Down: http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb */
				hexToRgb: function (hex) {
					var shortformRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i,
						longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
						rgbParts;

					hex = hex.replace(shortformRegex, function (m, r, g, b) {
						return r + r + g + g + b + b;
					});

					rgbParts = longformRegex.exec(hex);

					return rgbParts ? [ parseInt(rgbParts[1], 16), parseInt(rgbParts[2], 16), parseInt(rgbParts[3], 16) ] : [ 0, 0, 0 ];
				},

				isCSSNullValue: function (value) {
					/* The browser defaults CSS values that have not been set to either 0 or one of several possible null-value strings.
					 Thus, we check for both falsiness and these special strings. */
					/* Null-value checking is performed to default the special strings to 0 (for the sake of tweening) or their hook
					 templates as defined as CSS.Hooks (for the sake of hook injection/extraction). */
					/* Note: Chrome returns "rgba(0, 0, 0, 0)" for an undefined color whereas IE returns "transparent". */
					return (value == 0 || /^(none|auto|transparent|(rgba\(0, ?0, ?0, ?0\)))$/i.test(value));
				},

				/* Retrieve a property's default unit type. Used for assigning a unit type when one is not supplied by the user. */
				getUnitType: function (property) {
					if (/^(rotate|skew)/i.test(property)) {
						return "deg";
					} else if (/(^(scale|scaleX|scaleY|scaleZ|alpha|flexGrow|flexHeight|zIndex|fontWeight)$)|((opacity|red|green|blue|alpha)$)/i.test(property)) {
						/* The above properties are unitless. */
						return "";
					} else {
						/* Default to px for all other properties. */
						return "px";
					}
				},

				/* HTML elements default to an associated display type when they're not set to display:none. */
				/* Note: This function is used for correctly setting the non-"none" display value in certain Velocity redirects, such as fadeIn/Out. */
				getDisplayType: function (element) {
					var tagName = element && element.tagName.toString().toLowerCase();

					if (/^(b|big|i|small|tt|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var|a|bdo|br|img|map|object|q|script|span|sub|sup|button|input|label|select|textarea)$/i.test(tagName)) {
						return "inline";
					} else if (/^(li)$/i.test(tagName)) {
						return "list-item";
					} else if (/^(tr)$/i.test(tagName)) {
						return "table-row";
					} else if (/^(table)$/i.test(tagName)) {
						return "table";
					} else if (/^(tbody)$/i.test(tagName)) {
						return "table-row-group";
						/* Default to "block" when no match is found. */
					} else {
						return "block";
					}
				},

				/* The class add/remove functions are used to temporarily apply a "velocity-animating" class to elements while they're animating. */
				addClass: function (element, className) {
					if (element.classList) {
						element.classList.add(className);
					} else {
						element.className += (element.className.length ? " " : "") + className;
					}
				},

				removeClass: function (element, className) {
					if (element.classList) {
						element.classList.remove(className);
					} else {
						element.className = element.className.toString().replace(new RegExp("(^|\\s)" + className.split(" ").join("|") + "(\\s|$)", "gi"), " ");
					}
				}
			},

			/****************************
			 Style Getting & Setting
			 ****************************/

			/* The singular getPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */
			getPropertyValue: function (element, property, rootPropertyValue, forceStyleLookup) {
				/* Get an element's computed property value. */
				/* Note: Retrieving the value of a CSS property cannot simply be performed by checking an element's
				 style attribute (which only reflects user-defined values). Instead, the browser must be queried for a property's
				 *computed* value. You can read more about getComputedStyle here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */
				function computePropertyValue (element, property) {
					/* When box-sizing isn't set to border-box, height and width style values are incorrectly computed when an
					 element's scrollbars are visible (which expands the element's dimensions). Thus, we defer to the more accurate
					 offsetHeight/Width property, which includes the total dimensions for interior, border, padding, and scrollbar.
					 We subtract border and padding to get the sum of interior + scrollbar. */
					var computedValue = 0;

					/* IE<=8 doesn't support window.getComputedStyle, thus we defer to jQuery, which has an extensive array
					 of hacks to accurately retrieve IE8 property values. Re-implementing that logic here is not worth bloating the
					 codebase for a dying browser. The performance repercussions of using jQuery here are minimal since
					 Velocity is optimized to rarely (and sometimes never) query the DOM. Further, the $.css() codepath isn't that slow. */
					if (IE <= 8) {
						computedValue = $.css(element, property); /* GET */
						/* All other browsers support getComputedStyle. The returned live object reference is cached onto its
						 associated element so that it does not need to be refetched upon every GET. */
					} else {
						/* Browsers do not return height and width values for elements that are set to display:"none". Thus, we temporarily
						 toggle display to the element type's default value. */
						var toggleDisplay = false;

						if (/^(width|height)$/.test(property) && CSS.getPropertyValue(element, "display") === 0) {
							toggleDisplay = true;
							CSS.setPropertyValue(element, "display", CSS.Values.getDisplayType(element));
						}

						function revertDisplay () {
							if (toggleDisplay) {
								CSS.setPropertyValue(element, "display", "none");
							}
						}

						if (!forceStyleLookup) {
							if (property === "height" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") {
								var contentBoxHeight = element.offsetHeight - (parseFloat(CSS.getPropertyValue(element, "borderTopWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "borderBottomWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingTop")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingBottom")) || 0);
								revertDisplay();

								return contentBoxHeight;
							} else if (property === "width" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") {
								var contentBoxWidth = element.offsetWidth - (parseFloat(CSS.getPropertyValue(element, "borderLeftWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "borderRightWidth")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingLeft")) || 0) - (parseFloat(CSS.getPropertyValue(element, "paddingRight")) || 0);
								revertDisplay();

								return contentBoxWidth;
							}
						}

						var computedStyle;

						/* For elements that Velocity hasn't been called on directly (e.g. when Velocity queries the DOM on behalf
						 of a parent of an element its animating), perform a direct getComputedStyle lookup since the object isn't cached. */
						if (Data(element) === undefined) {
							computedStyle = window.getComputedStyle(element, null); /* GET */
							/* If the computedStyle object has yet to be cached, do so now. */
						} else if (!Data(element).computedStyle) {
							computedStyle = Data(element).computedStyle = window.getComputedStyle(element, null); /* GET */
							/* If computedStyle is cached, use it. */
						} else {
							computedStyle = Data(element).computedStyle;
						}

						/* IE and Firefox do not return a value for the generic borderColor -- they only return individual values for each border side's color.
						 Also, in all browsers, when border colors aren't all the same, a compound value is returned that Velocity isn't setup to parse.
						 So, as a polyfill for querying individual border side colors, we just return the top border's color and animate all borders from that value. */
						if (property === "borderColor") {
							property = "borderTopColor";
						}

						/* IE9 has a bug in which the "filter" property must be accessed from computedStyle using the getPropertyValue method
						 instead of a direct property lookup. The getPropertyValue method is slower than a direct lookup, which is why we avoid it by default. */
						if (IE === 9 && property === "filter") {
							computedValue = computedStyle.getPropertyValue(property); /* GET */
						} else {
							computedValue = computedStyle[property];
						}

						/* Fall back to the property's style value (if defined) when computedValue returns nothing,
						 which can happen when the element hasn't been painted. */
						if (computedValue === "" || computedValue === null) {
							computedValue = element.style[property];
						}

						revertDisplay();
					}

					/* For top, right, bottom, and left (TRBL) values that are set to "auto" on elements of "fixed" or "absolute" position,
					 defer to jQuery for converting "auto" to a numeric value. (For elements with a "static" or "relative" position, "auto" has the same
					 effect as being set to 0, so no conversion is necessary.) */
					/* An example of why numeric conversion is necessary: When an element with "position:absolute" has an untouched "left"
					 property, which reverts to "auto", left's value is 0 relative to its parent element, but is often non-zero relative
					 to its *containing* (not parent) element, which is the nearest "position:relative" ancestor or the viewport (and always the viewport in the case of "position:fixed"). */
					if (computedValue === "auto" && /^(top|right|bottom|left)$/i.test(property)) {
						var position = computePropertyValue(element, "position"); /* GET */

						/* For absolute positioning, jQuery's $.position() only returns values for top and left;
						 right and bottom will have their "auto" value reverted to 0. */
						/* Note: A jQuery object must be created here since jQuery doesn't have a low-level alias for $.position().
						 Not a big deal since we're currently in a GET batch anyway. */
						if (position === "fixed" || (position === "absolute" && /top|left/i.test(property))) {
							/* Note: jQuery strips the pixel unit from its returned values; we re-add it here to conform with computePropertyValue's behavior. */
							computedValue = $(element).position()[property] + "px"; /* GET */
						}
					}

					return computedValue;
				}

				var propertyValue;

				/* If this is a hooked property (e.g. "clipLeft" instead of the root property of "clip"),
				 extract the hook's value from a normalized rootPropertyValue using CSS.Hooks.extractValue(). */
				if (CSS.Hooks.registered[property]) {
					var hook = property,
						hookRoot = CSS.Hooks.getRoot(hook);

					/* If a cached rootPropertyValue wasn't passed in (which Velocity always attempts to do in order to avoid requerying the DOM),
					 query the DOM for the root property's value. */
					if (rootPropertyValue === undefined) {
						/* Since the browser is now being directly queried, use the official post-prefixing property name for this lookup. */
						rootPropertyValue = CSS.getPropertyValue(element, CSS.Names.prefixCheck(hookRoot)[0]); /* GET */
					}

					/* If this root has a normalization registered, peform the associated normalization extraction. */
					if (CSS.Normalizations.registered[hookRoot]) {
						rootPropertyValue = CSS.Normalizations.registered[hookRoot]("extract", element, rootPropertyValue);
					}

					/* Extract the hook's value. */
					propertyValue = CSS.Hooks.extractValue(hook, rootPropertyValue);

					/* If this is a normalized property (e.g. "opacity" becomes "filter" in <=IE8) or "translateX" becomes "transform"),
					 normalize the property's name and value, and handle the special case of transforms. */
					/* Note: Normalizing a property is mutually exclusive from hooking a property since hook-extracted values are strictly
					 numerical and therefore do not require normalization extraction. */
				} else if (CSS.Normalizations.registered[property]) {
					var normalizedPropertyName,
						normalizedPropertyValue;

					normalizedPropertyName = CSS.Normalizations.registered[property]("name", element);

					/* Transform values are calculated via normalization extraction (see below), which checks against the element's transformCache.
					 At no point do transform GETs ever actually query the DOM; initial stylesheet values are never processed.
					 This is because parsing 3D transform matrices is not always accurate and would bloat our codebase;
					 thus, normalization extraction defaults initial transform values to their zero-values (e.g. 1 for scaleX and 0 for translateX). */
					if (normalizedPropertyName !== "transform") {
						normalizedPropertyValue = computePropertyValue(element, CSS.Names.prefixCheck(normalizedPropertyName)[0]); /* GET */

						/* If the value is a CSS null-value and this property has a hook template, use that zero-value template so that hooks can be extracted from it. */
						if (CSS.Values.isCSSNullValue(normalizedPropertyValue) && CSS.Hooks.templates[property]) {
							normalizedPropertyValue = CSS.Hooks.templates[property][1];
						}
					}

					propertyValue = CSS.Normalizations.registered[property]("extract", element, normalizedPropertyValue);
				}

				/* If a (numeric) value wasn't produced via hook extraction or normalization, query the DOM. */
				if (!/^[\d-]/.test(propertyValue)) {
					/* For SVG elements, dimensional properties (which SVGAttribute() detects) are tweened via
					 their HTML attribute values instead of their CSS style values. */
					if (Data(element) && Data(element).isSVG && CSS.Names.SVGAttribute(property)) {
						/* Since the height/width attribute values must be set manually, they don't reflect computed values.
						 Thus, we use use getBBox() to ensure we always get values for elements with undefined height/width attributes. */
						if (/^(height|width)$/i.test(property)) {
							/* Firefox throws an error if .getBBox() is called on an SVG that isn't attached to the DOM. */
							try {
								propertyValue = element.getBBox()[property];
							} catch (error) {
								propertyValue = 0;
							}
							/* Otherwise, access the attribute value directly. */
						} else {
							propertyValue = element.getAttribute(property);
						}
					} else {
						propertyValue = computePropertyValue(element, CSS.Names.prefixCheck(property)[0]); /* GET */
					}
				}

				/* Since property lookups are for animation purposes (which entails computing the numeric delta between start and end values),
				 convert CSS null-values to an integer of value 0. */
				if (CSS.Values.isCSSNullValue(propertyValue)) {
					propertyValue = 0;
				}

				if (Velocity.debug >= 2) console.log("Get " + property + ": " + propertyValue);

				return propertyValue;
			},

			/* The singular setPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */
			setPropertyValue: function(element, property, propertyValue, rootPropertyValue, scrollData) {
				var propertyName = property;

				/* In order to be subjected to call options and element queueing, scroll animation is routed through Velocity as if it were a standard CSS property. */
				if (property === "scroll") {
					/* If a container option is present, scroll the container instead of the browser window. */
					if (scrollData.container) {
						scrollData.container["scroll" + scrollData.direction] = propertyValue;
						/* Otherwise, Velocity defaults to scrolling the browser window. */
					} else {
						if (scrollData.direction === "Left") {
							window.scrollTo(propertyValue, scrollData.alternateValue);
						} else {
							window.scrollTo(scrollData.alternateValue, propertyValue);
						}
					}
				} else {
					/* Transforms (translateX, rotateZ, etc.) are applied to a per-element transformCache object, which is manually flushed via flushTransformCache().
					 Thus, for now, we merely cache transforms being SET. */
					if (CSS.Normalizations.registered[property] && CSS.Normalizations.registered[property]("name", element) === "transform") {
						/* Perform a normalization injection. */
						/* Note: The normalization logic handles the transformCache updating. */
						CSS.Normalizations.registered[property]("inject", element, propertyValue);

						propertyName = "transform";
						propertyValue = Data(element).transformCache[property];
					} else {
						/* Inject hooks. */
						if (CSS.Hooks.registered[property]) {
							var hookName = property,
								hookRoot = CSS.Hooks.getRoot(property);

							/* If a cached rootPropertyValue was not provided, query the DOM for the hookRoot's current value. */
							rootPropertyValue = rootPropertyValue || CSS.getPropertyValue(element, hookRoot); /* GET */

							propertyValue = CSS.Hooks.injectValue(hookName, propertyValue, rootPropertyValue);
							property = hookRoot;
						}

						/* Normalize names and values. */
						if (CSS.Normalizations.registered[property]) {
							propertyValue = CSS.Normalizations.registered[property]("inject", element, propertyValue);
							property = CSS.Normalizations.registered[property]("name", element);
						}

						/* Assign the appropriate vendor prefix before performing an official style update. */
						propertyName = CSS.Names.prefixCheck(property)[0];

						/* A try/catch is used for IE<=8, which throws an error when "invalid" CSS values are set, e.g. a negative width.
						 Try/catch is avoided for other browsers since it incurs a performance overhead. */
						if (IE <= 8) {
							try {
								element.style[propertyName] = propertyValue;
							} catch (error) { if (Velocity.debug) console.log("Browser does not support [" + propertyValue + "] for [" + propertyName + "]"); }
							/* SVG elements have their dimensional properties (width, height, x, y, cx, etc.) applied directly as attributes instead of as styles. */
							/* Note: IE8 does not support SVG elements, so it's okay that we skip it for SVG animation. */
						} else if (Data(element) && Data(element).isSVG && CSS.Names.SVGAttribute(property)) {
							/* Note: For SVG attributes, vendor-prefixed property names are never used. */
							/* Note: Not all CSS properties can be animated via attributes, but the browser won't throw an error for unsupported properties. */
							element.setAttribute(property, propertyValue);
						} else {
							element.style[propertyName] = propertyValue;
						}

						if (Velocity.debug >= 2) console.log("Set " + property + " (" + propertyName + "): " + propertyValue);
					}
				}

				/* Return the normalized property name and value in case the caller wants to know how these values were modified before being applied to the DOM. */
				return [ propertyName, propertyValue ];
			},

			/* To increase performance by batching transform updates into a single SET, transforms are not directly applied to an element until flushTransformCache() is called. */
			/* Note: Velocity applies transform properties in the same order that they are chronogically introduced to the element's CSS styles. */
			flushTransformCache: function(element) {
				var transformString = "";

				/* Certain browsers require that SVG transforms be applied as an attribute. However, the SVG transform attribute takes a modified version of CSS's transform string
				 (units are dropped and, except for skewX/Y, subproperties are merged into their master property -- e.g. scaleX and scaleY are merged into scale(X Y). */
				if ((IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) && Data(element).isSVG) {
					/* Since transform values are stored in their parentheses-wrapped form, we use a helper function to strip out their numeric values.
					 Further, SVG transform properties only take unitless (representing pixels) values, so it's okay that parseFloat() strips the unit suffixed to the float value. */
					function getTransformFloat (transformProperty) {
						return parseFloat(CSS.getPropertyValue(element, transformProperty));
					}

					/* Create an object to organize all the transforms that we'll apply to the SVG element. To keep the logic simple,
					 we process *all* transform properties -- even those that may not be explicitly applied (since they default to their zero-values anyway). */
					var SVGTransforms = {
						translate: [ getTransformFloat("translateX"), getTransformFloat("translateY") ],
						skewX: [ getTransformFloat("skewX") ], skewY: [ getTransformFloat("skewY") ],
						/* If the scale property is set (non-1), use that value for the scaleX and scaleY values
						 (this behavior mimics the result of animating all these properties at once on HTML elements). */
						scale: getTransformFloat("scale") !== 1 ? [ getTransformFloat("scale"), getTransformFloat("scale") ] : [ getTransformFloat("scaleX"), getTransformFloat("scaleY") ],
						/* Note: SVG's rotate transform takes three values: rotation degrees followed by the X and Y values
						 defining the rotation's origin point. We ignore the origin values (default them to 0). */
						rotate: [ getTransformFloat("rotateZ"), 0, 0 ]
					};

					/* Iterate through the transform properties in the user-defined property map order.
					 (This mimics the behavior of non-SVG transform animation.) */
					$.each(Data(element).transformCache, function(transformName) {
						/* Except for with skewX/Y, revert the axis-specific transform subproperties to their axis-free master
						 properties so that they match up with SVG's accepted transform properties. */
						if (/^translate/i.test(transformName)) {
							transformName = "translate";
						} else if (/^scale/i.test(transformName)) {
							transformName = "scale";
						} else if (/^rotate/i.test(transformName)) {
							transformName = "rotate";
						}

						/* Check that we haven't yet deleted the property from the SVGTransforms container. */
						if (SVGTransforms[transformName]) {
							/* Append the transform property in the SVG-supported transform format. As per the spec, surround the space-delimited values in parentheses. */
							transformString += transformName + "(" + SVGTransforms[transformName].join(" ") + ")" + " ";

							/* After processing an SVG transform property, delete it from the SVGTransforms container so we don't
							 re-insert the same master property if we encounter another one of its axis-specific properties. */
							delete SVGTransforms[transformName];
						}
					});
				} else {
					var transformValue,
						perspective;

					/* Transform properties are stored as members of the transformCache object. Concatenate all the members into a string. */
					$.each(Data(element).transformCache, function(transformName) {
						transformValue = Data(element).transformCache[transformName];

						/* Transform's perspective subproperty must be set first in order to take effect. Store it temporarily. */
						if (transformName === "transformPerspective") {
							perspective = transformValue;
							return true;
						}

						/* IE9 only supports one rotation type, rotateZ, which it refers to as "rotate". */
						if (IE === 9 && transformName === "rotateZ") {
							transformName = "rotate";
						}

						transformString += transformName + transformValue + " ";
					});

					/* If present, set the perspective subproperty first. */
					if (perspective) {
						transformString = "perspective" + perspective + " " + transformString;
					}
				}

				CSS.setPropertyValue(element, "transform", transformString);
			}
		};

		/* Register hooks and normalizations. */
		CSS.Hooks.register();
		CSS.Normalizations.register();

		/* Allow hook setting in the same fashion as jQuery's $.css(). */
		Velocity.hook = function (elements, arg2, arg3) {
			var value = undefined;

			elements = sanitizeElements(elements);

			$.each(elements, function(i, element) {
				/* Initialize Velocity's per-element data cache if this element hasn't previously been animated. */
				if (Data(element) === undefined) {
					Velocity.init(element);
				}

				/* Get property value. If an element set was passed in, only return the value for the first element. */
				if (arg3 === undefined) {
					if (value === undefined) {
						value = Velocity.CSS.getPropertyValue(element, arg2);
					}
					/* Set property value. */
				} else {
					/* sPV returns an array of the normalized propertyName/propertyValue pair used to update the DOM. */
					var adjustedSet = Velocity.CSS.setPropertyValue(element, arg2, arg3);

					/* Transform properties don't automatically set. They have to be flushed to the DOM. */
					if (adjustedSet[0] === "transform") {
						Velocity.CSS.flushTransformCache(element);
					}

					value = adjustedSet;
				}
			});

			return value;
		};

		/*****************
		 Animation
		 *****************/

		var animate = function() {

			/******************
			 Call Chain
			 ******************/

			/* Logic for determining what to return to the call stack when exiting out of Velocity. */
			function getChain () {
				/* If we are using the utility function, attempt to return this call's promise. If no promise library was detected,
				 default to null instead of returning the targeted elements so that utility function's return value is standardized. */
				if (isUtility) {
					return promiseData.promise || null;
					/* Otherwise, if we're using $.fn, return the jQuery-/Zepto-wrapped element set. */
				} else {
					return elementsWrapped;
				}
			}

			/*************************
			 Arguments Assignment
			 *************************/

			/* To allow for expressive CoffeeScript code, Velocity supports an alternative syntax in which "elements" (or "e"), "properties" (or "p"), and "options" (or "o")
			 objects are defined on a container object that's passed in as Velocity's sole argument. */
			/* Note: Some browsers automatically populate arguments with a "properties" object. We detect it by checking for its default "names" property. */
			var syntacticSugar = (arguments[0] && (arguments[0].p || (($.isPlainObject(arguments[0].properties) && !arguments[0].properties.names) || Type.isString(arguments[0].properties)))),
			/* Whether Velocity was called via the utility function (as opposed to on a jQuery/Zepto object). */
				isUtility,
			/* When Velocity is called via the utility function ($.Velocity()/Velocity()), elements are explicitly
			 passed in as the first parameter. Thus, argument positioning varies. We normalize them here. */
				elementsWrapped,
				argumentIndex;

			var elements,
				propertiesMap,
				options;

			/* Detect jQuery/Zepto elements being animated via the $.fn method. */
			if (Type.isWrapped(this)) {
				isUtility = false;

				argumentIndex = 0;
				elements = this;
				elementsWrapped = this;
				/* Otherwise, raw elements are being animated via the utility function. */
			} else {
				isUtility = true;

				argumentIndex = 1;
				elements = syntacticSugar ? (arguments[0].elements || arguments[0].e) : arguments[0];
			}

			elements = sanitizeElements(elements);

			if (!elements) {
				return;
			}

			if (syntacticSugar) {
				propertiesMap = arguments[0].properties || arguments[0].p;
				options = arguments[0].options || arguments[0].o;
			} else {
				propertiesMap = arguments[argumentIndex];
				options = arguments[argumentIndex + 1];
			}

			/* The length of the element set (in the form of a nodeList or an array of elements) is defaulted to 1 in case a
			 single raw DOM element is passed in (which doesn't contain a length property). */
			var elementsLength = elements.length,
				elementsIndex = 0;

			/***************************
			 Argument Overloading
			 ***************************/

			/* Support is included for jQuery's argument overloading: $.animate(propertyMap [, duration] [, easing] [, complete]).
			 Overloading is detected by checking for the absence of an object being passed into options. */
			/* Note: The stop and finish actions do not accept animation options, and are therefore excluded from this check. */
			if (!/^(stop|finish)$/i.test(propertiesMap) && !$.isPlainObject(options)) {
				/* The utility function shifts all arguments one position to the right, so we adjust for that offset. */
				var startingArgumentPosition = argumentIndex + 1;

				options = {};

				/* Iterate through all options arguments */
				for (var i = startingArgumentPosition; i < arguments.length; i++) {
					/* Treat a number as a duration. Parse it out. */
					/* Note: The following RegEx will return true if passed an array with a number as its first item.
					 Thus, arrays are skipped from this check. */
					if (!Type.isArray(arguments[i]) && (/^(fast|normal|slow)$/i.test(arguments[i]) || /^\d/.test(arguments[i]))) {
						options.duration = arguments[i];
						/* Treat strings and arrays as easings. */
					} else if (Type.isString(arguments[i]) || Type.isArray(arguments[i])) {
						options.easing = arguments[i];
						/* Treat a function as a complete callback. */
					} else if (Type.isFunction(arguments[i])) {
						options.complete = arguments[i];
					}
				}
			}

			/***************
			 Promises
			 ***************/

			var promiseData = {
				promise: null,
				resolver: null,
				rejecter: null
			};

			/* If this call was made via the utility function (which is the default method of invocation when jQuery/Zepto are not being used), and if
			 promise support was detected, create a promise object for this call and store references to its resolver and rejecter methods. The resolve
			 method is used when a call completes naturally or is prematurely stopped by the user. In both cases, completeCall() handles the associated
			 call cleanup and promise resolving logic. The reject method is used when an invalid set of arguments is passed into a Velocity call. */
			/* Note: Velocity employs a call-based queueing architecture, which means that stopping an animating element actually stops the full call that
			 triggered it -- not that one element exclusively. Similarly, there is one promise per call, and all elements targeted by a Velocity call are
			 grouped together for the purposes of resolving and rejecting a promise. */
			if (isUtility && Velocity.Promise) {
				promiseData.promise = new Velocity.Promise(function (resolve, reject) {
					promiseData.resolver = resolve;
					promiseData.rejecter = reject;
				});
			}

			/*********************
			 Action Detection
			 *********************/

			/* Velocity's behavior is categorized into "actions": Elements can either be specially scrolled into view,
			 or they can be started, stopped, or reversed. If a literal or referenced properties map is passed in as Velocity's
			 first argument, the associated action is "start". Alternatively, "scroll", "reverse", or "stop" can be passed in instead of a properties map. */
			var action;

			switch (propertiesMap) {
				case "scroll":
					action = "scroll";
					break;

				case "reverse":
					action = "reverse";
					break;

				case "finish":
				case "stop":
					/*******************
					 Action: Stop
					 *******************/

					/* Clear the currently-active delay on each targeted element. */
					$.each(elements, function(i, element) {
						if (Data(element) && Data(element).delayTimer) {
							/* Stop the timer from triggering its cached next() function. */
							clearTimeout(Data(element).delayTimer.setTimeout);

							/* Manually call the next() function so that the subsequent queue items can progress. */
							if (Data(element).delayTimer.next) {
								Data(element).delayTimer.next();
							}

							delete Data(element).delayTimer;
						}
					});

					var callsToStop = [];

					/* When the stop action is triggered, the elements' currently active call is immediately stopped. The active call might have
					 been applied to multiple elements, in which case all of the call's elements will be stopped. When an element
					 is stopped, the next item in its animation queue is immediately triggered. */
					/* An additional argument may be passed in to clear an element's remaining queued calls. Either true (which defaults to the "fx" queue)
					 or a custom queue string can be passed in. */
					/* Note: The stop command runs prior to Velocity's Queueing phase since its behavior is intended to take effect *immediately*,
					 regardless of the element's current queue state. */

					/* Iterate through every active call. */
					$.each(Velocity.State.calls, function(i, activeCall) {
						/* Inactive calls are set to false by the logic inside completeCall(). Skip them. */
						if (activeCall) {
							/* Iterate through the active call's targeted elements. */
							$.each(activeCall[1], function(k, activeElement) {
								/* If true was passed in as a secondary argument, clear absolutely all calls on this element. Otherwise, only
								 clear calls associated with the relevant queue. */
								/* Call stopping logic works as follows:
								 - options === true --> stop current default queue calls (and queue:false calls), including remaining queued ones.
								 - options === undefined --> stop current queue:"" call and all queue:false calls.
								 - options === false --> stop only queue:false calls.
								 - options === "custom" --> stop current queue:"custom" call, including remaining queued ones (there is no functionality to only clear the currently-running queue:"custom" call). */
								var queueName = (options === undefined) ? "" : options;

								if (queueName !== true && (activeCall[2].queue !== queueName) && !(options === undefined && activeCall[2].queue === false)) {
									return true;
								}

								/* Iterate through the calls targeted by the stop command. */
								$.each(elements, function(l, element) {
									/* Check that this call was applied to the target element. */
									if (element === activeElement) {
										/* Optionally clear the remaining queued calls. */
										if (options === true || Type.isString(options)) {
											/* Iterate through the items in the element's queue. */
											$.each($.queue(element, Type.isString(options) ? options : ""), function(_, item) {
												/* The queue array can contain an "inprogress" string, which we skip. */
												if (Type.isFunction(item)) {
													/* Pass the item's callback a flag indicating that we want to abort from the queue call.
													 (Specifically, the queue will resolve the call's associated promise then abort.)  */
													item(null, true);
												}
											});

											/* Clearing the $.queue() array is achieved by resetting it to []. */
											$.queue(element, Type.isString(options) ? options : "", []);
										}

										if (propertiesMap === "stop") {
											/* Since "reverse" uses cached start values (the previous call's endValues), these values must be
											 changed to reflect the final value that the elements were actually tweened to. */
											/* Note: If only queue:false animations are currently running on an element, it won't have a tweensContainer
											 object. Also, queue:false animations can't be reversed. */
											if (Data(element) && Data(element).tweensContainer && queueName !== false) {
												$.each(Data(element).tweensContainer, function(m, activeTween) {
													activeTween.endValue = activeTween.currentValue;
												});
											}

											callsToStop.push(i);
										} else if (propertiesMap === "finish") {
											/* To get active tweens to finish immediately, we forcefully shorten their durations to 1ms so that
											 they finish upon the next rAf tick then proceed with normal call completion logic. */
											activeCall[2].duration = 1;
										}
									}
								});
							});
						}
					});

					/* Prematurely call completeCall() on each matched active call. Pass an additional flag for "stop" to indicate
					 that the complete callback and display:none setting should be skipped since we're completing prematurely. */
					if (propertiesMap === "stop") {
						$.each(callsToStop, function(i, j) {
							completeCall(j, true);
						});

						if (promiseData.promise) {
							/* Immediately resolve the promise associated with this stop call since stop runs synchronously. */
							promiseData.resolver(elements);
						}
					}

					/* Since we're stopping, and not proceeding with queueing, exit out of Velocity. */
					return getChain();

				default:
					/* Treat a non-empty plain object as a literal properties map. */
					if ($.isPlainObject(propertiesMap) && !Type.isEmptyObject(propertiesMap)) {
						action = "start";

						/****************
						 Redirects
						 ****************/

						/* Check if a string matches a registered redirect (see Redirects above). */
					} else if (Type.isString(propertiesMap) && Velocity.Redirects[propertiesMap]) {
						var opts = $.extend({}, options),
							durationOriginal = opts.duration,
							delayOriginal = opts.delay || 0;

						/* If the backwards option was passed in, reverse the element set so that elements animate from the last to the first. */
						if (opts.backwards === true) {
							elements = $.extend(true, [], elements).reverse();
						}

						/* Individually trigger the redirect for each element in the set to prevent users from having to handle iteration logic in their redirect. */
						$.each(elements, function(elementIndex, element) {
							/* If the stagger option was passed in, successively delay each element by the stagger value (in ms). Retain the original delay value. */
							if (parseFloat(opts.stagger)) {
								opts.delay = delayOriginal + (parseFloat(opts.stagger) * elementIndex);
							} else if (Type.isFunction(opts.stagger)) {
								opts.delay = delayOriginal + opts.stagger.call(element, elementIndex, elementsLength);
							}

							/* If the drag option was passed in, successively increase/decrease (depending on the presense of opts.backwards)
							 the duration of each element's animation, using floors to prevent producing very short durations. */
							if (opts.drag) {
								/* Default the duration of UI pack effects (callouts and transitions) to 1000ms instead of the usual default duration of 400ms. */
								opts.duration = parseFloat(durationOriginal) || (/^(callout|transition)/.test(propertiesMap) ? 1000 : DURATION_DEFAULT);

								/* For each element, take the greater duration of: A) animation completion percentage relative to the original duration,
								 B) 75% of the original duration, or C) a 200ms fallback (in case duration is already set to a low value).
								 The end result is a baseline of 75% of the redirect's duration that increases/decreases as the end of the element set is approached. */
								opts.duration = Math.max(opts.duration * (opts.backwards ? 1 - elementIndex/elementsLength : (elementIndex + 1) / elementsLength), opts.duration * 0.75, 200);
							}

							/* Pass in the call's opts object so that the redirect can optionally extend it. It defaults to an empty object instead of null to
							 reduce the opts checking logic required inside the redirect. */
							Velocity.Redirects[propertiesMap].call(element, element, opts || {}, elementIndex, elementsLength, elements, promiseData.promise ? promiseData : undefined);
						});

						/* Since the animation logic resides within the redirect's own code, abort the remainder of this call.
						 (The performance overhead up to this point is virtually non-existant.) */
						/* Note: The jQuery call chain is kept intact by returning the complete element set. */
						return getChain();
					} else {
						var abortError = "Velocity: First argument (" + propertiesMap + ") was not a property map, a known action, or a registered redirect. Aborting.";

						if (promiseData.promise) {
							promiseData.rejecter(new Error(abortError));
						} else {
							console.log(abortError);
						}

						return getChain();
					}
			}

			/**************************
			 Call-Wide Variables
			 **************************/

			/* A container for CSS unit conversion ratios (e.g. %, rem, and em ==> px) that is used to cache ratios across all elements
			 being animated in a single Velocity call. Calculating unit ratios necessitates DOM querying and updating, and is therefore
			 avoided (via caching) wherever possible. This container is call-wide instead of page-wide to avoid the risk of using stale
			 conversion metrics across Velocity animations that are not immediately consecutively chained. */
			var callUnitConversionData = {
				lastParent: null,
				lastPosition: null,
				lastFontSize: null,
				lastPercentToPxWidth: null,
				lastPercentToPxHeight: null,
				lastEmToPx: null,
				remToPx: null,
				vwToPx: null,
				vhToPx: null
			};

			/* A container for all the ensuing tween data and metadata associated with this call. This container gets pushed to the page-wide
			 Velocity.State.calls array that is processed during animation ticking. */
			var call = [];

			/************************
			 Element Processing
			 ************************/

			/* Element processing consists of three parts -- data processing that cannot go stale and data processing that *can* go stale (i.e. third-party style modifications):
			 1) Pre-Queueing: Element-wide variables, including the element's data storage, are instantiated. Call options are prepared. If triggered, the Stop action is executed.
			 2) Queueing: The logic that runs once this call has reached its point of execution in the element's $.queue() stack. Most logic is placed here to avoid risking it becoming stale.
			 3) Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container.
			 */

			function processElement () {

				/*************************
				 Part I: Pre-Queueing
				 *************************/

				/***************************
				 Element-Wide Variables
				 ***************************/

				var element = this,
				/* The runtime opts object is the extension of the current call's options and Velocity's page-wide option defaults. */
					opts = $.extend({}, Velocity.defaults, options),
				/* A container for the processed data associated with each property in the propertyMap.
				 (Each property in the map produces its own "tween".) */
					tweensContainer = {},
					elementUnitConversionData;

				/******************
				 Element Init
				 ******************/

				if (Data(element) === undefined) {
					Velocity.init(element);
				}

				/******************
				 Option: Delay
				 ******************/

				/* Since queue:false doesn't respect the item's existing queue, we avoid injecting its delay here (it's set later on). */
				/* Note: Velocity rolls its own delay function since jQuery doesn't have a utility alias for $.fn.delay()
				 (and thus requires jQuery element creation, which we avoid since its overhead includes DOM querying). */
				if (parseFloat(opts.delay) && opts.queue !== false) {
					$.queue(element, opts.queue, function(next) {
						/* This is a flag used to indicate to the upcoming completeCall() function that this queue entry was initiated by Velocity. See completeCall() for further details. */
						Velocity.velocityQueueEntryFlag = true;

						/* The ensuing queue item (which is assigned to the "next" argument that $.queue() automatically passes in) will be triggered after a setTimeout delay.
						 The setTimeout is stored so that it can be subjected to clearTimeout() if this animation is prematurely stopped via Velocity's "stop" command. */
						Data(element).delayTimer = {
							setTimeout: setTimeout(next, parseFloat(opts.delay)),
							next: next
						};
					});
				}

				/*********************
				 Option: Duration
				 *********************/

				/* Support for jQuery's named durations. */
				switch (opts.duration.toString().toLowerCase()) {
					case "fast":
						opts.duration = 200;
						break;

					case "normal":
						opts.duration = DURATION_DEFAULT;
						break;

					case "slow":
						opts.duration = 600;
						break;

					default:
						/* Remove the potential "ms" suffix and default to 1 if the user is attempting to set a duration of 0 (in order to produce an immediate style change). */
						opts.duration = parseFloat(opts.duration) || 1;
				}

				/************************
				 Global Option: Mock
				 ************************/

				if (Velocity.mock !== false) {
					/* In mock mode, all animations are forced to 1ms so that they occur immediately upon the next rAF tick.
					 Alternatively, a multiplier can be passed in to time remap all delays and durations. */
					if (Velocity.mock === true) {
						opts.duration = opts.delay = 1;
					} else {
						opts.duration *= parseFloat(Velocity.mock) || 1;
						opts.delay *= parseFloat(Velocity.mock) || 1;
					}
				}

				/*******************
				 Option: Easing
				 *******************/

				opts.easing = getEasing(opts.easing, opts.duration);

				/**********************
				 Option: Callbacks
				 **********************/

				/* Callbacks must functions. Otherwise, default to null. */
				if (opts.begin && !Type.isFunction(opts.begin)) {
					opts.begin = null;
				}

				if (opts.progress && !Type.isFunction(opts.progress)) {
					opts.progress = null;
				}

				if (opts.complete && !Type.isFunction(opts.complete)) {
					opts.complete = null;
				}

				/*********************************
				 Option: Display & Visibility
				 *********************************/

				/* Refer to Velocity's documentation (VelocityJS.org/#displayAndVisibility) for a description of the display and visibility options' behavior. */
				/* Note: We strictly check for undefined instead of falsiness because display accepts an empty string value. */
				if (opts.display !== undefined && opts.display !== null) {
					opts.display = opts.display.toString().toLowerCase();

					/* Users can pass in a special "auto" value to instruct Velocity to set the element to its default display value. */
					if (opts.display === "auto") {
						opts.display = Velocity.CSS.Values.getDisplayType(element);
					}
				}

				if (opts.visibility !== undefined && opts.visibility !== null) {
					opts.visibility = opts.visibility.toString().toLowerCase();
				}

				/**********************
				 Option: mobileHA
				 **********************/

				/* When set to true, and if this is a mobile device, mobileHA automatically enables hardware acceleration (via a null transform hack)
				 on animating elements. HA is removed from the element at the completion of its animation. */
				/* Note: Android Gingerbread doesn't support HA. If a null transform hack (mobileHA) is in fact set, it will prevent other tranform subproperties from taking effect. */
				/* Note: You can read more about the use of mobileHA in Velocity's documentation: VelocityJS.org/#mobileHA. */
				opts.mobileHA = (opts.mobileHA && Velocity.State.isMobile && !Velocity.State.isGingerbread);

				/***********************
				 Part II: Queueing
				 ***********************/

				/* When a set of elements is targeted by a Velocity call, the set is broken up and each element has the current Velocity call individually queued onto it.
				 In this way, each element's existing queue is respected; some elements may already be animating and accordingly should not have this current Velocity call triggered immediately. */
				/* In each queue, tween data is processed for each animating property then pushed onto the call-wide calls array. When the last element in the set has had its tweens processed,
				 the call array is pushed to Velocity.State.calls for live processing by the requestAnimationFrame tick. */
				function buildQueue (next) {

					/*******************
					 Option: Begin
					 *******************/

					/* The begin callback is fired once per call -- not once per elemenet -- and is passed the full raw DOM element set as both its context and its first argument. */
					if (opts.begin && elementsIndex === 0) {
						/* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */
						try {
							opts.begin.call(elements, elements);
						} catch (error) {
							setTimeout(function() { throw error; }, 1);
						}
					}

					/*****************************************
					 Tween Data Construction (for Scroll)
					 *****************************************/

					/* Note: In order to be subjected to chaining and animation options, scroll's tweening is routed through Velocity as if it were a standard CSS property animation. */
					if (action === "scroll") {
						/* The scroll action uniquely takes an optional "offset" option -- specified in pixels -- that offsets the targeted scroll position. */
						var scrollDirection = (/^x$/i.test(opts.axis) ? "Left" : "Top"),
							scrollOffset = parseFloat(opts.offset) || 0,
							scrollPositionCurrent,
							scrollPositionCurrentAlternate,
							scrollPositionEnd;

						/* Scroll also uniquely takes an optional "container" option, which indicates the parent element that should be scrolled --
						 as opposed to the browser window itself. This is useful for scrolling toward an element that's inside an overflowing parent element. */
						if (opts.container) {
							/* Ensure that either a jQuery object or a raw DOM element was passed in. */
							if (Type.isWrapped(opts.container) || Type.isNode(opts.container)) {
								/* Extract the raw DOM element from the jQuery wrapper. */
								opts.container = opts.container[0] || opts.container;
								/* Note: Unlike other properties in Velocity, the browser's scroll position is never cached since it so frequently changes
								 (due to the user's natural interaction with the page). */
								scrollPositionCurrent = opts.container["scroll" + scrollDirection]; /* GET */

								/* $.position() values are relative to the container's currently viewable area (without taking into account the container's true dimensions
								 -- say, for example, if the container was not overflowing). Thus, the scroll end value is the sum of the child element's position *and*
								 the scroll container's current scroll position. */
								scrollPositionEnd = (scrollPositionCurrent + $(element).position()[scrollDirection.toLowerCase()]) + scrollOffset; /* GET */
								/* If a value other than a jQuery object or a raw DOM element was passed in, default to null so that this option is ignored. */
							} else {
								opts.container = null;
							}
						} else {
							/* If the window itself is being scrolled -- not a containing element -- perform a live scroll position lookup using
							 the appropriate cached property names (which differ based on browser type). */
							scrollPositionCurrent = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + scrollDirection]]; /* GET */
							/* When scrolling the browser window, cache the alternate axis's current value since window.scrollTo() doesn't let us change only one value at a time. */
							scrollPositionCurrentAlternate = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + (scrollDirection === "Left" ? "Top" : "Left")]]; /* GET */

							/* Unlike $.position(), $.offset() values are relative to the browser window's true dimensions -- not merely its currently viewable area --
							 and therefore end values do not need to be compounded onto current values. */
							scrollPositionEnd = $(element).offset()[scrollDirection.toLowerCase()] + scrollOffset; /* GET */
						}

						/* Since there's only one format that scroll's associated tweensContainer can take, we create it manually. */
						tweensContainer = {
							scroll: {
								rootPropertyValue: false,
								startValue: scrollPositionCurrent,
								currentValue: scrollPositionCurrent,
								endValue: scrollPositionEnd,
								unitType: "",
								easing: opts.easing,
								scrollData: {
									container: opts.container,
									direction: scrollDirection,
									alternateValue: scrollPositionCurrentAlternate
								}
							},
							element: element
						};

						if (Velocity.debug) console.log("tweensContainer (scroll): ", tweensContainer.scroll, element);

						/******************************************
						 Tween Data Construction (for Reverse)
						 ******************************************/

						/* Reverse acts like a "start" action in that a property map is animated toward. The only difference is
						 that the property map used for reverse is the inverse of the map used in the previous call. Thus, we manipulate
						 the previous call to construct our new map: use the previous map's end values as our new map's start values. Copy over all other data. */
						/* Note: Reverse can be directly called via the "reverse" parameter, or it can be indirectly triggered via the loop option. (Loops are composed of multiple reverses.) */
						/* Note: Reverse calls do not need to be consecutively chained onto a currently-animating element in order to operate on cached values;
						 there is no harm to reverse being called on a potentially stale data cache since reverse's behavior is simply defined
						 as reverting to the element's values as they were prior to the previous *Velocity* call. */
					} else if (action === "reverse") {
						/* Abort if there is no prior animation data to reverse to. */
						if (!Data(element).tweensContainer) {
							/* Dequeue the element so that this queue entry releases itself immediately, allowing subsequent queue entries to run. */
							$.dequeue(element, opts.queue);

							return;
						} else {
							/*********************
							 Options Parsing
							 *********************/

							/* If the element was hidden via the display option in the previous call,
							 revert display to "auto" prior to reversal so that the element is visible again. */
							if (Data(element).opts.display === "none") {
								Data(element).opts.display = "auto";
							}

							if (Data(element).opts.visibility === "hidden") {
								Data(element).opts.visibility = "visible";
							}

							/* If the loop option was set in the previous call, disable it so that "reverse" calls aren't recursively generated.
							 Further, remove the previous call's callback options; typically, users do not want these to be refired. */
							Data(element).opts.loop = false;
							Data(element).opts.begin = null;
							Data(element).opts.complete = null;

							/* Since we're extending an opts object that has already been extended with the defaults options object,
							 we remove non-explicitly-defined properties that are auto-assigned values. */
							if (!options.easing) {
								delete opts.easing;
							}

							if (!options.duration) {
								delete opts.duration;
							}

							/* The opts object used for reversal is an extension of the options object optionally passed into this
							 reverse call plus the options used in the previous Velocity call. */
							opts = $.extend({}, Data(element).opts, opts);

							/*************************************
							 Tweens Container Reconstruction
							 *************************************/

							/* Create a deepy copy (indicated via the true flag) of the previous call's tweensContainer. */
							var lastTweensContainer = $.extend(true, {}, Data(element).tweensContainer);

							/* Manipulate the previous tweensContainer by replacing its end values and currentValues with its start values. */
							for (var lastTween in lastTweensContainer) {
								/* In addition to tween data, tweensContainers contain an element property that we ignore here. */
								if (lastTween !== "element") {
									var lastStartValue = lastTweensContainer[lastTween].startValue;

									lastTweensContainer[lastTween].startValue = lastTweensContainer[lastTween].currentValue = lastTweensContainer[lastTween].endValue;
									lastTweensContainer[lastTween].endValue = lastStartValue;

									/* Easing is the only option that embeds into the individual tween data (since it can be defined on a per-property basis).
									 Accordingly, every property's easing value must be updated when an options object is passed in with a reverse call.
									 The side effect of this extensibility is that all per-property easing values are forcefully reset to the new value. */
									if (!Type.isEmptyObject(options)) {
										lastTweensContainer[lastTween].easing = opts.easing;
									}

									if (Velocity.debug) console.log("reverse tweensContainer (" + lastTween + "): " + JSON.stringify(lastTweensContainer[lastTween]), element);
								}
							}

							tweensContainer = lastTweensContainer;
						}

						/*****************************************
						 Tween Data Construction (for Start)
						 *****************************************/

					} else if (action === "start") {

						/*************************
						 Value Transferring
						 *************************/

						/* If this queue entry follows a previous Velocity-initiated queue entry *and* if this entry was created
						 while the element was in the process of being animated by Velocity, then this current call is safe to use
						 the end values from the prior call as its start values. Velocity attempts to perform this value transfer
						 process whenever possible in order to avoid requerying the DOM. */
						/* If values aren't transferred from a prior call and start values were not forcefed by the user (more on this below),
						 then the DOM is queried for the element's current values as a last resort. */
						/* Note: Conversely, animation reversal (and looping) *always* perform inter-call value transfers; they never requery the DOM. */
						var lastTweensContainer;

						/* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale)
						 to transfer over end values to use as start values. If it's set to true and there is a previous
						 Velocity call to pull values from, do so. */
						if (Data(element).tweensContainer && Data(element).isAnimating === true) {
							lastTweensContainer = Data(element).tweensContainer;
						}

						/***************************
						 Tween Data Calculation
						 ***************************/

						/* This function parses property data and defaults endValue, easing, and startValue as appropriate. */
						/* Property map values can either take the form of 1) a single value representing the end value,
						 or 2) an array in the form of [ endValue, [, easing] [, startValue] ].
						 The optional third parameter is a forcefed startValue to be used instead of querying the DOM for
						 the element's current value. Read Velocity's docmentation to learn more about forcefeeding: VelocityJS.org/#forcefeeding */
						function parsePropertyValue (valueData, skipResolvingEasing) {
							var endValue = undefined,
								easing = undefined,
								startValue = undefined;

							/* Handle the array format, which can be structured as one of three potential overloads:
							 A) [ endValue, easing, startValue ], B) [ endValue, easing ], or C) [ endValue, startValue ] */
							if (Type.isArray(valueData)) {
								/* endValue is always the first item in the array. Don't bother validating endValue's value now
								 since the ensuing property cycling logic does that. */
								endValue = valueData[0];

								/* Two-item array format: If the second item is a number, function, or hex string, treat it as a
								 start value since easings can only be non-hex strings or arrays. */
								if ((!Type.isArray(valueData[1]) && /^[\d-]/.test(valueData[1])) || Type.isFunction(valueData[1]) || CSS.RegEx.isHex.test(valueData[1])) {
									startValue = valueData[1];
									/* Two or three-item array: If the second item is a non-hex string or an array, treat it as an easing. */
								} else if ((Type.isString(valueData[1]) && !CSS.RegEx.isHex.test(valueData[1])) || Type.isArray(valueData[1])) {
									easing = skipResolvingEasing ? valueData[1] : getEasing(valueData[1], opts.duration);

									/* Don't bother validating startValue's value now since the ensuing property cycling logic inherently does that. */
									if (valueData[2] !== undefined) {
										startValue = valueData[2];
									}
								}
								/* Handle the single-value format. */
							} else {
								endValue = valueData;
							}

							/* Default to the call's easing if a per-property easing type was not defined. */
							if (!skipResolvingEasing) {
								easing = easing || opts.easing;
							}

							/* If functions were passed in as values, pass the function the current element as its context,
							 plus the element's index and the element set's size as arguments. Then, assign the returned value. */
							if (Type.isFunction(endValue)) {
								endValue = endValue.call(element, elementsIndex, elementsLength);
							}

							if (Type.isFunction(startValue)) {
								startValue = startValue.call(element, elementsIndex, elementsLength);
							}

							/* Allow startValue to be left as undefined to indicate to the ensuing code that its value was not forcefed. */
							return [ endValue || 0, easing, startValue ];
						}

						/* Cycle through each property in the map, looking for shorthand color properties (e.g. "color" as opposed to "colorRed"). Inject the corresponding
						 colorRed, colorGreen, and colorBlue RGB component tweens into the propertiesMap (which Velocity understands) and remove the shorthand property. */
						$.each(propertiesMap, function(property, value) {
							/* Find shorthand color properties that have been passed a hex string. */
							if (RegExp("^" + CSS.Lists.colors.join("$|^") + "$").test(property)) {
								/* Parse the value data for each shorthand. */
								var valueData = parsePropertyValue(value, true),
									endValue = valueData[0],
									easing = valueData[1],
									startValue = valueData[2];

								if (CSS.RegEx.isHex.test(endValue)) {
									/* Convert the hex strings into their RGB component arrays. */
									var colorComponents = [ "Red", "Green", "Blue" ],
										endValueRGB = CSS.Values.hexToRgb(endValue),
										startValueRGB = startValue ? CSS.Values.hexToRgb(startValue) : undefined;

									/* Inject the RGB component tweens into propertiesMap. */
									for (var i = 0; i < colorComponents.length; i++) {
										var dataArray = [ endValueRGB[i] ];

										if (easing) {
											dataArray.push(easing);
										}

										if (startValueRGB !== undefined) {
											dataArray.push(startValueRGB[i]);
										}

										propertiesMap[property + colorComponents[i]] = dataArray;
									}

									/* Remove the intermediary shorthand property entry now that we've processed it. */
									delete propertiesMap[property];
								}
							}
						});

						/* Create a tween out of each property, and append its associated data to tweensContainer. */
						for (var property in propertiesMap) {

							/**************************
							 Start Value Sourcing
							 **************************/

							/* Parse out endValue, easing, and startValue from the property's data. */
							var valueData = parsePropertyValue(propertiesMap[property]),
								endValue = valueData[0],
								easing = valueData[1],
								startValue = valueData[2];

							/* Now that the original property name's format has been used for the parsePropertyValue() lookup above,
							 we force the property to its camelCase styling to normalize it for manipulation. */
							property = CSS.Names.camelCase(property);

							/* In case this property is a hook, there are circumstances where we will intend to work on the hook's root property and not the hooked subproperty. */
							var rootProperty = CSS.Hooks.getRoot(property),
								rootPropertyValue = false;

							/* Other than for the dummy tween property, properties that are not supported by the browser (and do not have an associated normalization) will
							 inherently produce no style changes when set, so they are skipped in order to decrease animation tick overhead.
							 Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */
							/* Note: Since SVG elements have some of their properties directly applied as HTML attributes,
							 there is no way to check for their explicit browser support, and so we skip skip this check for them. */
							if (!Data(element).isSVG && rootProperty !== "tween" && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) {
								if (Velocity.debug) console.log("Skipping [" + rootProperty + "] due to a lack of browser support.");

								continue;
							}

							/* If the display option is being set to a non-"none" (e.g. "block") and opacity (filter on IE<=8) is being
							 animated to an endValue of non-zero, the user's intention is to fade in from invisible, thus we forcefeed opacity
							 a startValue of 0 if its startValue hasn't already been sourced by value transferring or prior forcefeeding. */
							if (((opts.display !== undefined && opts.display !== null && opts.display !== "none") || (opts.visibility !== undefined && opts.visibility !== "hidden")) && /opacity|filter/.test(property) && !startValue && endValue !== 0) {
								startValue = 0;
							}

							/* If values have been transferred from the previous Velocity call, extract the endValue and rootPropertyValue
							 for all of the current call's properties that were *also* animated in the previous call. */
							/* Note: Value transferring can optionally be disabled by the user via the _cacheValues option. */
							if (opts._cacheValues && lastTweensContainer && lastTweensContainer[property]) {
								if (startValue === undefined) {
									startValue = lastTweensContainer[property].endValue + lastTweensContainer[property].unitType;
								}

								/* The previous call's rootPropertyValue is extracted from the element's data cache since that's the
								 instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue
								 attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */
								rootPropertyValue = Data(element).rootPropertyValueCache[rootProperty];
								/* If values were not transferred from a previous Velocity call, query the DOM as needed. */
							} else {
								/* Handle hooked properties. */
								if (CSS.Hooks.registered[property]) {
									if (startValue === undefined) {
										rootPropertyValue = CSS.getPropertyValue(element, rootProperty); /* GET */
										/* Note: The following getPropertyValue() call does not actually trigger a DOM query;
										 getPropertyValue() will extract the hook from rootPropertyValue. */
										startValue = CSS.getPropertyValue(element, property, rootPropertyValue);
										/* If startValue is already defined via forcefeeding, do not query the DOM for the root property's value;
										 just grab rootProperty's zero-value template from CSS.Hooks. This overwrites the element's actual
										 root property value (if one is set), but this is acceptable since the primary reason users forcefeed is
										 to avoid DOM queries, and thus we likewise avoid querying the DOM for the root property's value. */
									} else {
										/* Grab this hook's zero-value template, e.g. "0px 0px 0px black". */
										rootPropertyValue = CSS.Hooks.templates[rootProperty][1];
									}
									/* Handle non-hooked properties that haven't already been defined via forcefeeding. */
								} else if (startValue === undefined) {
									startValue = CSS.getPropertyValue(element, property); /* GET */
								}
							}

							/**************************
							 Value Data Extraction
							 **************************/

							var separatedValue,
								endValueUnitType,
								startValueUnitType,
								operator = false;

							/* Separates a property value into its numeric value and its unit type. */
							function separateValue (property, value) {
								var unitType,
									numericValue;

								numericValue = (value || "0")
									.toString()
									.toLowerCase()
									/* Match the unit type at the end of the value. */
									.replace(/[%A-z]+$/, function(match) {
										/* Grab the unit type. */
										unitType = match;

										/* Strip the unit type off of value. */
										return "";
									});

								/* If no unit type was supplied, assign one that is appropriate for this property (e.g. "deg" for rotateZ or "px" for width). */
								if (!unitType) {
									unitType = CSS.Values.getUnitType(property);
								}

								return [ numericValue, unitType ];
							}

							/* Separate startValue. */
							separatedValue = separateValue(property, startValue);
							startValue = separatedValue[0];
							startValueUnitType = separatedValue[1];

							/* Separate endValue, and extract a value operator (e.g. "+=", "-=") if one exists. */
							separatedValue = separateValue(property, endValue);
							endValue = separatedValue[0].replace(/^([+-\/*])=/, function(match, subMatch) {
								operator = subMatch;

								/* Strip the operator off of the value. */
								return "";
							});
							endValueUnitType = separatedValue[1];

							/* Parse float values from endValue and startValue. Default to 0 if NaN is returned. */
							startValue = parseFloat(startValue) || 0;
							endValue = parseFloat(endValue) || 0;

							/***************************************
							 Property-Specific Value Conversion
							 ***************************************/

							/* Custom support for properties that don't actually accept the % unit type, but where pollyfilling is trivial and relatively foolproof. */
							if (endValueUnitType === "%") {
								/* A %-value fontSize/lineHeight is relative to the parent's fontSize (as opposed to the parent's dimensions),
								 which is identical to the em unit's behavior, so we piggyback off of that. */
								if (/^(fontSize|lineHeight)$/.test(property)) {
									/* Convert % into an em decimal value. */
									endValue = endValue / 100;
									endValueUnitType = "em";
									/* For scaleX and scaleY, convert the value into its decimal format and strip off the unit type. */
								} else if (/^scale/.test(property)) {
									endValue = endValue / 100;
									endValueUnitType = "";
									/* For RGB components, take the defined percentage of 255 and strip off the unit type. */
								} else if (/(Red|Green|Blue)$/i.test(property)) {
									endValue = (endValue / 100) * 255;
									endValueUnitType = "";
								}
							}

							/***************************
							 Unit Ratio Calculation
							 ***************************/

							/* When queried, the browser returns (most) CSS property values in pixels. Therefore, if an endValue with a unit type of
							 %, em, or rem is animated toward, startValue must be converted from pixels into the same unit type as endValue in order
							 for value manipulation logic (increment/decrement) to proceed. Further, if the startValue was forcefed or transferred
							 from a previous call, startValue may also not be in pixels. Unit conversion logic therefore consists of two steps:
							 1) Calculating the ratio of %/em/rem/vh/vw relative to pixels
							 2) Converting startValue into the same unit of measurement as endValue based on these ratios. */
							/* Unit conversion ratios are calculated by inserting a sibling node next to the target node, copying over its position property,
							 setting values with the target unit type then comparing the returned pixel value. */
							/* Note: Even if only one of these unit types is being animated, all unit ratios are calculated at once since the overhead
							 of batching the SETs and GETs together upfront outweights the potential overhead
							 of layout thrashing caused by re-querying for uncalculated ratios for subsequently-processed properties. */
							/* Todo: Shift this logic into the calls' first tick instance so that it's synced with RAF. */
							function calculateUnitRatios () {

								/************************
								 Same Ratio Checks
								 ************************/

								/* The properties below are used to determine whether the element differs sufficiently from this call's
								 previously iterated element to also differ in its unit conversion ratios. If the properties match up with those
								 of the prior element, the prior element's conversion ratios are used. Like most optimizations in Velocity,
								 this is done to minimize DOM querying. */
								var sameRatioIndicators = {
										myParent: element.parentNode || document.body, /* GET */
										position: CSS.getPropertyValue(element, "position"), /* GET */
										fontSize: CSS.getPropertyValue(element, "fontSize") /* GET */
									},
								/* Determine if the same % ratio can be used. % is based on the element's position value and its parent's width and height dimensions. */
									samePercentRatio = ((sameRatioIndicators.position === callUnitConversionData.lastPosition) && (sameRatioIndicators.myParent === callUnitConversionData.lastParent)),
								/* Determine if the same em ratio can be used. em is relative to the element's fontSize. */
									sameEmRatio = (sameRatioIndicators.fontSize === callUnitConversionData.lastFontSize);

								/* Store these ratio indicators call-wide for the next element to compare against. */
								callUnitConversionData.lastParent = sameRatioIndicators.myParent;
								callUnitConversionData.lastPosition = sameRatioIndicators.position;
								callUnitConversionData.lastFontSize = sameRatioIndicators.fontSize;

								/***************************
								 Element-Specific Units
								 ***************************/

								/* Note: IE8 rounds to the nearest pixel when returning CSS values, thus we perform conversions using a measurement
								 of 100 (instead of 1) to give our ratios a precision of at least 2 decimal values. */
								var measurement = 100,
									unitRatios = {};

								if (!sameEmRatio || !samePercentRatio) {
									var dummy = Data(element).isSVG ? document.createElementNS("http://www.w3.org/2000/svg", "rect") : document.createElement("div");

									Velocity.init(dummy);
									sameRatioIndicators.myParent.appendChild(dummy);

									/* To accurately and consistently calculate conversion ratios, the element's cascaded overflow and box-sizing are stripped.
									 Similarly, since width/height can be artificially constrained by their min-/max- equivalents, these are controlled for as well. */
									/* Note: Overflow must be also be controlled for per-axis since the overflow property overwrites its per-axis values. */
									$.each([ "overflow", "overflowX", "overflowY" ], function(i, property) {
										Velocity.CSS.setPropertyValue(dummy, property, "hidden");
									});
									Velocity.CSS.setPropertyValue(dummy, "position", sameRatioIndicators.position);
									Velocity.CSS.setPropertyValue(dummy, "fontSize", sameRatioIndicators.fontSize);
									Velocity.CSS.setPropertyValue(dummy, "boxSizing", "content-box");

									/* width and height act as our proxy properties for measuring the horizontal and vertical % ratios. */
									$.each([ "minWidth", "maxWidth", "width", "minHeight", "maxHeight", "height" ], function(i, property) {
										Velocity.CSS.setPropertyValue(dummy, property, measurement + "%");
									});
									/* paddingLeft arbitrarily acts as our proxy property for the em ratio. */
									Velocity.CSS.setPropertyValue(dummy, "paddingLeft", measurement + "em");

									/* Divide the returned value by the measurement to get the ratio between 1% and 1px. Default to 1 since working with 0 can produce Infinite. */
									unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth = (parseFloat(CSS.getPropertyValue(dummy, "width", null, true)) || 1) / measurement; /* GET */
									unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight = (parseFloat(CSS.getPropertyValue(dummy, "height", null, true)) || 1) / measurement; /* GET */
									unitRatios.emToPx = callUnitConversionData.lastEmToPx = (parseFloat(CSS.getPropertyValue(dummy, "paddingLeft")) || 1) / measurement; /* GET */

									sameRatioIndicators.myParent.removeChild(dummy);
								} else {
									unitRatios.emToPx = callUnitConversionData.lastEmToPx;
									unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth;
									unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight;
								}

								/***************************
								 Element-Agnostic Units
								 ***************************/

								/* Whereas % and em ratios are determined on a per-element basis, the rem unit only needs to be checked
								 once per call since it's exclusively dependant upon document.body's fontSize. If this is the first time
								 that calculateUnitRatios() is being run during this call, remToPx will still be set to its default value of null,
								 so we calculate it now. */
								if (callUnitConversionData.remToPx === null) {
									/* Default to browsers' default fontSize of 16px in the case of 0. */
									callUnitConversionData.remToPx = parseFloat(CSS.getPropertyValue(document.body, "fontSize")) || 16; /* GET */
								}

								/* Similarly, viewport units are %-relative to the window's inner dimensions. */
								if (callUnitConversionData.vwToPx === null) {
									callUnitConversionData.vwToPx = parseFloat(window.innerWidth) / 100; /* GET */
									callUnitConversionData.vhToPx = parseFloat(window.innerHeight) / 100; /* GET */
								}

								unitRatios.remToPx = callUnitConversionData.remToPx;
								unitRatios.vwToPx = callUnitConversionData.vwToPx;
								unitRatios.vhToPx = callUnitConversionData.vhToPx;

								if (Velocity.debug >= 1) console.log("Unit ratios: " + JSON.stringify(unitRatios), element);

								return unitRatios;
							}

							/********************
							 Unit Conversion
							 ********************/

							/* The * and / operators, which are not passed in with an associated unit, inherently use startValue's unit. Skip value and unit conversion. */
							if (/[\/*]/.test(operator)) {
								endValueUnitType = startValueUnitType;
								/* If startValue and endValue differ in unit type, convert startValue into the same unit type as endValue so that if endValueUnitType
								 is a relative unit (%, em, rem), the values set during tweening will continue to be accurately relative even if the metrics they depend
								 on are dynamically changing during the course of the animation. Conversely, if we always normalized into px and used px for setting values, the px ratio
								 would become stale if the original unit being animated toward was relative and the underlying metrics change during the animation. */
								/* Since 0 is 0 in any unit type, no conversion is necessary when startValue is 0 -- we just start at 0 with endValueUnitType. */
							} else if ((startValueUnitType !== endValueUnitType) && startValue !== 0) {
								/* Unit conversion is also skipped when endValue is 0, but *startValueUnitType* must be used for tween values to remain accurate. */
								/* Note: Skipping unit conversion here means that if endValueUnitType was originally a relative unit, the animation won't relatively
								 match the underlying metrics if they change, but this is acceptable since we're animating toward invisibility instead of toward visibility,
								 which remains past the point of the animation's completion. */
								if (endValue === 0) {
									endValueUnitType = startValueUnitType;
								} else {
									/* By this point, we cannot avoid unit conversion (it's undesirable since it causes layout thrashing).
									 If we haven't already, we trigger calculateUnitRatios(), which runs once per element per call. */
									elementUnitConversionData = elementUnitConversionData || calculateUnitRatios();

									/* The following RegEx matches CSS properties that have their % values measured relative to the x-axis. */
									/* Note: W3C spec mandates that all of margin and padding's properties (even top and bottom) are %-relative to the *width* of the parent element. */
									var axis = (/margin|padding|left|right|width|text|word|letter/i.test(property) || /X$/.test(property) || property === "x") ? "x" : "y";

									/* In order to avoid generating n^2 bespoke conversion functions, unit conversion is a two-step process:
									 1) Convert startValue into pixels. 2) Convert this new pixel value into endValue's unit type. */
									switch (startValueUnitType) {
										case "%":
											/* Note: translateX and translateY are the only properties that are %-relative to an element's own dimensions -- not its parent's dimensions.
											 Velocity does not include a special conversion process to account for this behavior. Therefore, animating translateX/Y from a % value
											 to a non-% value will produce an incorrect start value. Fortunately, this sort of cross-unit conversion is rarely done by users in practice. */
											startValue *= (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight);
											break;

										case "px":
											/* px acts as our midpoint in the unit conversion process; do nothing. */
											break;

										default:
											startValue *= elementUnitConversionData[startValueUnitType + "ToPx"];
									}

									/* Invert the px ratios to convert into to the target unit. */
									switch (endValueUnitType) {
										case "%":
											startValue *= 1 / (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight);
											break;

										case "px":
											/* startValue is already in px, do nothing; we're done. */
											break;

										default:
											startValue *= 1 / elementUnitConversionData[endValueUnitType + "ToPx"];
									}
								}
							}

							/*********************
							 Relative Values
							 *********************/

							/* Operator logic must be performed last since it requires unit-normalized start and end values. */
							/* Note: Relative *percent values* do not behave how most people think; while one would expect "+=50%"
							 to increase the property 1.5x its current value, it in fact increases the percent units in absolute terms:
							 50 points is added on top of the current % value. */
							switch (operator) {
								case "+":
									endValue = startValue + endValue;
									break;

								case "-":
									endValue = startValue - endValue;
									break;

								case "*":
									endValue = startValue * endValue;
									break;

								case "/":
									endValue = startValue / endValue;
									break;
							}

							/**************************
							 tweensContainer Push
							 **************************/

							/* Construct the per-property tween object, and push it to the element's tweensContainer. */
							tweensContainer[property] = {
								rootPropertyValue: rootPropertyValue,
								startValue: startValue,
								currentValue: startValue,
								endValue: endValue,
								unitType: endValueUnitType,
								easing: easing
							};

							if (Velocity.debug) console.log("tweensContainer (" + property + "): " + JSON.stringify(tweensContainer[property]), element);
						}

						/* Along with its property data, store a reference to the element itself onto tweensContainer. */
						tweensContainer.element = element;
					}

					/*****************
					 Call Push
					 *****************/

					/* Note: tweensContainer can be empty if all of the properties in this call's property map were skipped due to not
					 being supported by the browser. The element property is used for checking that the tweensContainer has been appended to. */
					if (tweensContainer.element) {
						/* Apply the "velocity-animating" indicator class. */
						CSS.Values.addClass(element, "velocity-animating");

						/* The call array houses the tweensContainers for each element being animated in the current call. */
						call.push(tweensContainer);

						/* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */
						if (opts.queue === "") {
							Data(element).tweensContainer = tweensContainer;
							Data(element).opts = opts;
						}

						/* Switch on the element's animating flag. */
						Data(element).isAnimating = true;

						/* Once the final element in this call's element set has been processed, push the call array onto
						 Velocity.State.calls for the animation tick to immediately begin processing. */
						if (elementsIndex === elementsLength - 1) {
							/* Add the current call plus its associated metadata (the element set and the call's options) onto the global call container.
							 Anything on this call container is subjected to tick() processing. */
							Velocity.State.calls.push([ call, elements, opts, null, promiseData.resolver ]);

							/* If the animation tick isn't running, start it. (Velocity shuts it off when there are no active calls to process.) */
							if (Velocity.State.isTicking === false) {
								Velocity.State.isTicking = true;

								/* Start the tick loop. */
								tick();
							}
						} else {
							elementsIndex++;
						}
					}
				}

				/* When the queue option is set to false, the call skips the element's queue and fires immediately. */
				if (opts.queue === false) {
					/* Since this buildQueue call doesn't respect the element's existing queue (which is where a delay option would have been appended),
					 we manually inject the delay property here with an explicit setTimeout. */
					if (opts.delay) {
						setTimeout(buildQueue, opts.delay);
					} else {
						buildQueue();
					}
					/* Otherwise, the call undergoes element queueing as normal. */
					/* Note: To interoperate with jQuery, Velocity uses jQuery's own $.queue() stack for queuing logic. */
				} else {
					$.queue(element, opts.queue, function(next, clearQueue) {
						/* If the clearQueue flag was passed in by the stop command, resolve this call's promise. (Promises can only be resolved once,
						 so it's fine if this is repeatedly triggered for each element in the associated call.) */
						if (clearQueue === true) {
							if (promiseData.promise) {
								promiseData.resolver(elements);
							}

							/* Do not continue with animation queueing. */
							return true;
						}

						/* This flag indicates to the upcoming completeCall() function that this queue entry was initiated by Velocity.
						 See completeCall() for further details. */
						Velocity.velocityQueueEntryFlag = true;

						buildQueue(next);
					});
				}

				/*********************
				 Auto-Dequeuing
				 *********************/

				/* As per jQuery's $.queue() behavior, to fire the first non-custom-queue entry on an element, the element
				 must be dequeued if its queue stack consists *solely* of the current call. (This can be determined by checking
				 for the "inprogress" item that jQuery prepends to active queue stack arrays.) Regardless, whenever the element's
				 queue is further appended with additional items -- including $.delay()'s or even $.animate() calls, the queue's
				 first entry is automatically fired. This behavior contrasts that of custom queues, which never auto-fire. */
				/* Note: When an element set is being subjected to a non-parallel Velocity call, the animation will not begin until
				 each one of the elements in the set has reached the end of its individually pre-existing queue chain. */
				/* Note: Unfortunately, most people don't fully grasp jQuery's powerful, yet quirky, $.queue() function.
				 Lean more here: http://stackoverflow.com/questions/1058158/can-somebody-explain-jquery-queue-to-me */
				if ((opts.queue === "" || opts.queue === "fx") && $.queue(element)[0] !== "inprogress") {
					$.dequeue(element);
				}
			}

			/**************************
			 Element Set Iteration
			 **************************/

			/* If the "nodeType" property exists on the elements variable, we're animating a single element.
			 Place it in an array so that $.each() can iterate over it. */
			$.each(elements, function(i, element) {
				/* Ensure each element in a set has a nodeType (is a real element) to avoid throwing errors. */
				if (Type.isNode(element)) {
					processElement.call(element);
				}
			});

			/******************
			 Option: Loop
			 ******************/

			/* The loop option accepts an integer indicating how many times the element should loop between the values in the
			 current call's properties map and the element's property values prior to this call. */
			/* Note: The loop option's logic is performed here -- after element processing -- because the current call needs
			 to undergo its queue insertion prior to the loop option generating its series of constituent "reverse" calls,
			 which chain after the current call. Two reverse calls (two "alternations") constitute one loop. */
			var opts = $.extend({}, Velocity.defaults, options),
				reverseCallsCount;

			opts.loop = parseInt(opts.loop);
			reverseCallsCount = (opts.loop * 2) - 1;

			if (opts.loop) {
				/* Double the loop count to convert it into its appropriate number of "reverse" calls.
				 Subtract 1 from the resulting value since the current call is included in the total alternation count. */
				for (var x = 0; x < reverseCallsCount; x++) {
					/* Since the logic for the reverse action occurs inside Queueing and therefore this call's options object
					 isn't parsed until then as well, the current call's delay option must be explicitly passed into the reverse
					 call so that the delay logic that occurs inside *Pre-Queueing* can process it. */
					var reverseOptions = {
						delay: opts.delay,
						progress: opts.progress
					};

					/* If a complete callback was passed into this call, transfer it to the loop redirect's final "reverse" call
					 so that it's triggered when the entire redirect is complete (and not when the very first animation is complete). */
					if (x === reverseCallsCount - 1) {
						reverseOptions.display = opts.display;
						reverseOptions.visibility = opts.visibility;
						reverseOptions.complete = opts.complete;
					}

					animate(elements, "reverse", reverseOptions);
				}
			}

			/***************
			 Chaining
			 ***************/

			/* Return the elements back to the call chain, with wrapped elements taking precedence in case Velocity was called via the $.fn. extension. */
			return getChain();
		};

		/* Turn Velocity into the animation function, extended with the pre-existing Velocity object. */
		Velocity = $.extend(animate, Velocity);
		/* For legacy support, also expose the literal animate method. */
		Velocity.animate = animate;

		/**************
		 Timing
		 **************/

		/* Ticker function. */
		var ticker = window.requestAnimationFrame || rAFShim;

		/* Inactive browser tabs pause rAF, which results in all active animations immediately sprinting to their completion states when the tab refocuses.
		 To get around this, we dynamically switch rAF to setTimeout (which the browser *doesn't* pause) when the tab loses focus. We skip this for mobile
		 devices to avoid wasting battery power on inactive tabs. */
		/* Note: Tab focus detection doesn't work on older versions of IE, but that's okay since they don't support rAF to begin with. */
		if (!Velocity.State.isMobile && document.hidden !== undefined) {
			document.addEventListener("visibilitychange", function() {
				/* Reassign the rAF function (which the global tick() function uses) based on the tab's focus state. */
				if (document.hidden) {
					ticker = function(callback) {
						/* The tick function needs a truthy first argument in order to pass its internal timestamp check. */
						return setTimeout(function() { callback(true) }, 16);
					};

					/* The rAF loop has been paused by the browser, so we manually restart the tick. */
					tick();
				} else {
					ticker = window.requestAnimationFrame || rAFShim;
				}
			});
		}

		/************
		 Tick
		 ************/

		/* Note: All calls to Velocity are pushed to the Velocity.State.calls array, which is fully iterated through upon each tick. */
		function tick (timestamp) {
			/* An empty timestamp argument indicates that this is the first tick occurence since ticking was turned on.
			 We leverage this metadata to fully ignore the first tick pass since RAF's initial pass is fired whenever
			 the browser's next tick sync time occurs, which results in the first elements subjected to Velocity
			 calls being animated out of sync with any elements animated immediately thereafter. In short, we ignore
			 the first RAF tick pass so that elements being immediately consecutively animated -- instead of simultaneously animated
			 by the same Velocity call -- are properly batched into the same initial RAF tick and consequently remain in sync thereafter. */
			if (timestamp) {
				/* We ignore RAF's high resolution timestamp since it can be significantly offset when the browser is
				 under high stress; we opt for choppiness over allowing the browser to drop huge chunks of frames. */
				var timeCurrent = (new Date).getTime();

				/********************
				 Call Iteration
				 ********************/

				var callsLength = Velocity.State.calls.length;

				/* To speed up iterating over this array, it is compacted (falsey items -- calls that have completed -- are removed)
				 when its length has ballooned to a point that can impact tick performance. This only becomes necessary when animation
				 has been continuous with many elements over a long period of time; whenever all active calls are completed, completeCall() clears Velocity.State.calls. */
				if (callsLength > 10000) {
					Velocity.State.calls = compactSparseArray(Velocity.State.calls);
				}

				/* Iterate through each active call. */
				for (var i = 0; i < callsLength; i++) {
					/* When a Velocity call is completed, its Velocity.State.calls entry is set to false. Continue on to the next call. */
					if (!Velocity.State.calls[i]) {
						continue;
					}

					/************************
					 Call-Wide Variables
					 ************************/

					var callContainer = Velocity.State.calls[i],
						call = callContainer[0],
						opts = callContainer[2],
						timeStart = callContainer[3],
						firstTick = !!timeStart,
						tweenDummyValue = null;

					/* If timeStart is undefined, then this is the first time that this call has been processed by tick().
					 We assign timeStart now so that its value is as close to the real animation start time as possible.
					 (Conversely, had timeStart been defined when this call was added to Velocity.State.calls, the delay
					 between that time and now would cause the first few frames of the tween to be skipped since
					 percentComplete is calculated relative to timeStart.) */
					/* Further, subtract 16ms (the approximate resolution of RAF) from the current time value so that the
					 first tick iteration isn't wasted by animating at 0% tween completion, which would produce the
					 same style value as the element's current value. */
					if (!timeStart) {
						timeStart = Velocity.State.calls[i][3] = timeCurrent - 16;
					}

					/* The tween's completion percentage is relative to the tween's start time, not the tween's start value
					 (which would result in unpredictable tween durations since JavaScript's timers are not particularly accurate).
					 Accordingly, we ensure that percentComplete does not exceed 1. */
					var percentComplete = Math.min((timeCurrent - timeStart) / opts.duration, 1);

					/**********************
					 Element Iteration
					 **********************/

					/* For every call, iterate through each of the elements in its set. */
					for (var j = 0, callLength = call.length; j < callLength; j++) {
						var tweensContainer = call[j],
							element = tweensContainer.element;

						/* Check to see if this element has been deleted midway through the animation by checking for the
						 continued existence of its data cache. If it's gone, skip animating this element. */
						if (!Data(element)) {
							continue;
						}

						var transformPropertyExists = false;

						/**********************************
						 Display & Visibility Toggling
						 **********************************/

						/* If the display option is set to non-"none", set it upfront so that the element can become visible before tweening begins.
						 (Otherwise, display's "none" value is set in completeCall() once the animation has completed.) */
						if (opts.display !== undefined && opts.display !== null && opts.display !== "none") {
							if (opts.display === "flex") {
								var flexValues = [ "-webkit-box", "-moz-box", "-ms-flexbox", "-webkit-flex" ];

								$.each(flexValues, function(i, flexValue) {
									CSS.setPropertyValue(element, "display", flexValue);
								});
							}

							CSS.setPropertyValue(element, "display", opts.display);
						}

						/* Same goes with the visibility option, but its "none" equivalent is "hidden". */
						if (opts.visibility !== undefined && opts.visibility !== "hidden") {
							CSS.setPropertyValue(element, "visibility", opts.visibility);
						}

						/************************
						 Property Iteration
						 ************************/

						/* For every element, iterate through each property. */
						for (var property in tweensContainer) {
							/* Note: In addition to property tween data, tweensContainer contains a reference to its associated element. */
							if (property !== "element") {
								var tween = tweensContainer[property],
									currentValue,
								/* Easing can either be a pre-genereated function or a string that references a pre-registered easing
								 on the Velocity.Easings object. In either case, return the appropriate easing *function*. */
									easing = Type.isString(tween.easing) ? Velocity.Easings[tween.easing] : tween.easing;

								/******************************
								 Current Value Calculation
								 ******************************/

								/* If this is the last tick pass (if we've reached 100% completion for this tween),
								 ensure that currentValue is explicitly set to its target endValue so that it's not subjected to any rounding. */
								if (percentComplete === 1) {
									currentValue = tween.endValue;
									/* Otherwise, calculate currentValue based on the current delta from startValue. */
								} else {
									var tweenDelta = tween.endValue - tween.startValue;
									currentValue = tween.startValue + (tweenDelta * easing(percentComplete, opts, tweenDelta));

									/* If no value change is occurring, don't proceed with DOM updating. */
									if (!firstTick && (currentValue === tween.currentValue)) {
										continue;
									}
								}

								tween.currentValue = currentValue;

								/* If we're tweening a fake 'tween' property in order to log transition values, update the one-per-call variable so that
								 it can be passed into the progress callback. */
								if (property === "tween") {
									tweenDummyValue = currentValue;
								} else {
									/******************
									 Hooks: Part I
									 ******************/

									/* For hooked properties, the newly-updated rootPropertyValueCache is cached onto the element so that it can be used
									 for subsequent hooks in this call that are associated with the same root property. If we didn't cache the updated
									 rootPropertyValue, each subsequent update to the root property in this tick pass would reset the previous hook's
									 updates to rootPropertyValue prior to injection. A nice performance byproduct of rootPropertyValue caching is that
									 subsequently chained animations using the same hookRoot but a different hook can use this cached rootPropertyValue. */
									if (CSS.Hooks.registered[property]) {
										var hookRoot = CSS.Hooks.getRoot(property),
											rootPropertyValueCache = Data(element).rootPropertyValueCache[hookRoot];

										if (rootPropertyValueCache) {
											tween.rootPropertyValue = rootPropertyValueCache;
										}
									}

									/*****************
									 DOM Update
									 *****************/

									/* setPropertyValue() returns an array of the property name and property value post any normalization that may have been performed. */
									/* Note: To solve an IE<=8 positioning bug, the unit type is dropped when setting a property value of 0. */
									var adjustedSetData = CSS.setPropertyValue(element, /* SET */
										property,
										tween.currentValue + (parseFloat(currentValue) === 0 ? "" : tween.unitType),
										tween.rootPropertyValue,
										tween.scrollData);

									/*******************
									 Hooks: Part II
									 *******************/

									/* Now that we have the hook's updated rootPropertyValue (the post-processed value provided by adjustedSetData), cache it onto the element. */
									if (CSS.Hooks.registered[property]) {
										/* Since adjustedSetData contains normalized data ready for DOM updating, the rootPropertyValue needs to be re-extracted from its normalized form. ?? */
										if (CSS.Normalizations.registered[hookRoot]) {
											Data(element).rootPropertyValueCache[hookRoot] = CSS.Normalizations.registered[hookRoot]("extract", null, adjustedSetData[1]);
										} else {
											Data(element).rootPropertyValueCache[hookRoot] = adjustedSetData[1];
										}
									}

									/***************
									 Transforms
									 ***************/

									/* Flag whether a transform property is being animated so that flushTransformCache() can be triggered once this tick pass is complete. */
									if (adjustedSetData[0] === "transform") {
										transformPropertyExists = true;
									}

								}
							}
						}

						/****************
						 mobileHA
						 ****************/

						/* If mobileHA is enabled, set the translate3d transform to null to force hardware acceleration.
						 It's safe to override this property since Velocity doesn't actually support its animation (hooks are used in its place). */
						if (opts.mobileHA) {
							/* Don't set the null transform hack if we've already done so. */
							if (Data(element).transformCache.translate3d === undefined) {
								/* All entries on the transformCache object are later concatenated into a single transform string via flushTransformCache(). */
								Data(element).transformCache.translate3d = "(0px, 0px, 0px)";

								transformPropertyExists = true;
							}
						}

						if (transformPropertyExists) {
							CSS.flushTransformCache(element);
						}
					}

					/* The non-"none" display value is only applied to an element once -- when its associated call is first ticked through.
					 Accordingly, it's set to false so that it isn't re-processed by this call in the next tick. */
					if (opts.display !== undefined && opts.display !== "none") {
						Velocity.State.calls[i][2].display = false;
					}
					if (opts.visibility !== undefined && opts.visibility !== "hidden") {
						Velocity.State.calls[i][2].visibility = false;
					}

					/* Pass the elements and the timing data (percentComplete, msRemaining, timeStart, tweenDummyValue) into the progress callback. */
					if (opts.progress) {
						opts.progress.call(callContainer[1],
							callContainer[1],
							percentComplete,
							Math.max(0, (timeStart + opts.duration) - timeCurrent),
							timeStart,
							tweenDummyValue);
					}

					/* If this call has finished tweening, pass its index to completeCall() to handle call cleanup. */
					if (percentComplete === 1) {
						completeCall(i);
					}
				}
			}

			/* Note: completeCall() sets the isTicking flag to false when the last call on Velocity.State.calls has completed. */
			if (Velocity.State.isTicking) {
				ticker(tick);
			}
		}

		/**********************
		 Call Completion
		 **********************/

		/* Note: Unlike tick(), which processes all active calls at once, call completion is handled on a per-call basis. */
		function completeCall (callIndex, isStopped) {
			/* Ensure the call exists. */
			if (!Velocity.State.calls[callIndex]) {
				return false;
			}

			/* Pull the metadata from the call. */
			var call = Velocity.State.calls[callIndex][0],
				elements = Velocity.State.calls[callIndex][1],
				opts = Velocity.State.calls[callIndex][2],
				resolver = Velocity.State.calls[callIndex][4];

			var remainingCallsExist = false;

			/*************************
			 Element Finalization
			 *************************/

			for (var i = 0, callLength = call.length; i < callLength; i++) {
				var element = call[i].element;

				/* If the user set display to "none" (intending to hide the element), set it now that the animation has completed. */
				/* Note: display:none isn't set when calls are manually stopped (via Velocity("stop"). */
				/* Note: Display gets ignored with "reverse" calls and infinite loops, since this behavior would be undesirable. */
				if (!isStopped && !opts.loop) {
					if (opts.display === "none") {
						CSS.setPropertyValue(element, "display", opts.display);
					}

					if (opts.visibility === "hidden") {
						CSS.setPropertyValue(element, "visibility", opts.visibility);
					}
				}

				/* If the element's queue is empty (if only the "inprogress" item is left at position 0) or if its queue is about to run
				 a non-Velocity-initiated entry, turn off the isAnimating flag. A non-Velocity-initiatied queue entry's logic might alter
				 an element's CSS values and thereby cause Velocity's cached value data to go stale. To detect if a queue entry was initiated by Velocity,
				 we check for the existence of our special Velocity.queueEntryFlag declaration, which minifiers won't rename since the flag
				 is assigned to jQuery's global $ object and thus exists out of Velocity's own scope. */
				if (opts.loop !== true && ($.queue(element)[1] === undefined || !/\.velocityQueueEntryFlag/i.test($.queue(element)[1]))) {
					/* The element may have been deleted. Ensure that its data cache still exists before acting on it. */
					if (Data(element)) {
						Data(element).isAnimating = false;
						/* Clear the element's rootPropertyValueCache, which will become stale. */
						Data(element).rootPropertyValueCache = {};

						var transformHAPropertyExists = false;
						/* If any 3D transform subproperty is at its default value (regardless of unit type), remove it. */
						$.each(CSS.Lists.transforms3D, function(i, transformName) {
							var defaultValue = /^scale/.test(transformName) ? 1 : 0,
								currentValue = Data(element).transformCache[transformName];

							if (Data(element).transformCache[transformName] !== undefined && new RegExp("^\\(" + defaultValue + "[^.]").test(currentValue)) {
								transformHAPropertyExists = true;

								delete Data(element).transformCache[transformName];
							}
						});

						/* Mobile devices have hardware acceleration removed at the end of the animation in order to avoid hogging the GPU's memory. */
						if (opts.mobileHA) {
							transformHAPropertyExists = true;
							delete Data(element).transformCache.translate3d;
						}

						/* Flush the subproperty removals to the DOM. */
						if (transformHAPropertyExists) {
							CSS.flushTransformCache(element);
						}

						/* Remove the "velocity-animating" indicator class. */
						CSS.Values.removeClass(element, "velocity-animating");
					}
				}

				/*********************
				 Option: Complete
				 *********************/

				/* Complete is fired once per call (not once per element) and is passed the full raw DOM element set as both its context and its first argument. */
				/* Note: Callbacks aren't fired when calls are manually stopped (via Velocity("stop"). */
				if (!isStopped && opts.complete && !opts.loop && (i === callLength - 1)) {
					/* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */
					try {
						opts.complete.call(elements, elements);
					} catch (error) {
						setTimeout(function() { throw error; }, 1);
					}
				}

				/**********************
				 Promise Resolving
				 **********************/

				/* Note: Infinite loops don't return promises. */
				if (resolver && opts.loop !== true) {
					resolver(elements);
				}

				/****************************
				 Option: Loop (Infinite)
				 ****************************/

				if (Data(element) && opts.loop === true && !isStopped) {
					/* If a rotateX/Y/Z property is being animated to 360 deg with loop:true, swap tween start/end values to enable
					 continuous iterative rotation looping. (Otherise, the element would just rotate back and forth.) */
					$.each(Data(element).tweensContainer, function(propertyName, tweenContainer) {
						if (/^rotate/.test(propertyName) && parseFloat(tweenContainer.endValue) === 360) {
							tweenContainer.endValue = 0;
							tweenContainer.startValue = 360;
						}

						if (/^backgroundPosition/.test(propertyName) && parseFloat(tweenContainer.endValue) === 100 && tweenContainer.unitType === "%") {
							tweenContainer.endValue = 0;
							tweenContainer.startValue = 100;
						}
					});

					Velocity(element, "reverse", { loop: true, delay: opts.delay });
				}

				/***************
				 Dequeueing
				 ***************/

				/* Fire the next call in the queue so long as this call's queue wasn't set to false (to trigger a parallel animation),
				 which would have already caused the next call to fire. Note: Even if the end of the animation queue has been reached,
				 $.dequeue() must still be called in order to completely clear jQuery's animation queue. */
				if (opts.queue !== false) {
					$.dequeue(element, opts.queue);
				}
			}

			/************************
			 Calls Array Cleanup
			 ************************/

			/* Since this call is complete, set it to false so that the rAF tick skips it. This array is later compacted via compactSparseArray().
			 (For performance reasons, the call is set to false instead of being deleted from the array: http://www.html5rocks.com/en/tutorials/speed/v8/) */
			Velocity.State.calls[callIndex] = false;

			/* Iterate through the calls array to determine if this was the final in-progress animation.
			 If so, set a flag to end ticking and clear the calls array. */
			for (var j = 0, callsLength = Velocity.State.calls.length; j < callsLength; j++) {
				if (Velocity.State.calls[j] !== false) {
					remainingCallsExist = true;

					break;
				}
			}

			if (remainingCallsExist === false) {
				/* tick() will detect this flag upon its next iteration and subsequently turn itself off. */
				Velocity.State.isTicking = false;

				/* Clear the calls array so that its length is reset. */
				delete Velocity.State.calls;
				Velocity.State.calls = [];
			}
		}

		/******************
		 Frameworks
		 ******************/

		/* Both jQuery and Zepto allow their $.fn object to be extended to allow wrapped elements to be subjected to plugin calls.
		 If either framework is loaded, register a "velocity" extension pointing to Velocity's core animate() method.  Velocity
		 also registers itself onto a global container (window.jQuery || window.Zepto || window) so that certain features are
		 accessible beyond just a per-element scope. This master object contains an .animate() method, which is later assigned to $.fn
		 (if jQuery or Zepto are present). Accordingly, Velocity can both act on wrapped DOM elements and stand alone for targeting raw DOM elements. */
		global.Velocity = Velocity;

		if (global !== window) {
			/* Assign the element function to Velocity's core animate() method. */
			global.fn.velocity = animate;
			/* Assign the object function's defaults to Velocity's global defaults object. */
			global.fn.velocity.defaults = Velocity.defaults;
		}

		/***********************
		 Packaged Redirects
		 ***********************/

		/* slideUp, slideDown */
		$.each([ "Down", "Up" ], function(i, direction) {
			Velocity.Redirects["slide" + direction] = function (element, options, elementsIndex, elementsSize, elements, promiseData) {
				var opts = $.extend({}, options),
					begin = opts.begin,
					complete = opts.complete,
					computedValues = { height: "", marginTop: "", marginBottom: "", paddingTop: "", paddingBottom: "" },
					inlineValues = {};

				if (opts.display === undefined) {
					/* Show the element before slideDown begins and hide the element after slideUp completes. */
					/* Note: Inline elements cannot have dimensions animated, so they're reverted to inline-block. */
					opts.display = (direction === "Down" ? (Velocity.CSS.Values.getDisplayType(element) === "inline" ? "inline-block" : "block") : "none");
				}

				opts.begin = function() {
					/* If the user passed in a begin callback, fire it now. */
					begin && begin.call(elements, elements);

					/* Cache the elements' original vertical dimensional property values so that we can animate back to them. */
					for (var property in computedValues) {
						inlineValues[property] = element.style[property];

						/* For slideDown, use forcefeeding to animate all vertical properties from 0. For slideUp,
						 use forcefeeding to start from computed values and animate down to 0. */
						var propertyValue = Velocity.CSS.getPropertyValue(element, property);
						computedValues[property] = (direction === "Down") ? [ propertyValue, 0 ] : [ 0, propertyValue ];
					}

					/* Force vertical overflow content to clip so that sliding works as expected. */
					inlineValues.overflow = element.style.overflow;
					element.style.overflow = "hidden";
				}

				opts.complete = function() {
					/* Reset element to its pre-slide inline values once its slide animation is complete. */
					for (var property in inlineValues) {
						element.style[property] = inlineValues[property];
					}

					/* If the user passed in a complete callback, fire it now. */
					complete && complete.call(elements, elements);
					promiseData && promiseData.resolver(elements);
				};

				Velocity(element, computedValues, opts);
			};
		});

		/* fadeIn, fadeOut */
		$.each([ "In", "Out" ], function(i, direction) {
			Velocity.Redirects["fade" + direction] = function (element, options, elementsIndex, elementsSize, elements, promiseData) {
				var opts = $.extend({}, options),
					propertiesMap = { opacity: (direction === "In") ? 1 : 0 },
					originalComplete = opts.complete;

				/* Since redirects are triggered individually for each element in the animated set, avoid repeatedly triggering
				 callbacks by firing them only when the final element has been reached. */
				if (elementsIndex !== elementsSize - 1) {
					opts.complete = opts.begin = null;
				} else {
					opts.complete = function() {
						if (originalComplete) {
							originalComplete.call(elements, elements);
						}

						promiseData && promiseData.resolver(elements);
					}
				}

				/* If a display was passed in, use it. Otherwise, default to "none" for fadeOut or the element-specific default for fadeIn. */
				/* Note: We allow users to pass in "null" to skip display setting altogether. */
				if (opts.display === undefined) {
					opts.display = (direction === "In" ? "auto" : "none");
				}

				Velocity(this, propertiesMap, opts);
			};
		});

		return Velocity;
	}((window.jQuery || window.Zepto || window), window, document);
}));

/******************
 Known Issues
 ******************/

/* The CSS spec mandates that the translateX/Y/Z transforms are %-relative to the element itself -- not its parent.
 Velocity, however, doesn't make this distinction. Thus, converting to or from the % unit with these subproperties
 will produce an inaccurate conversion value. The same issue exists with the cx/cy attributes of SVG circles and ellipses. */
/*! http://mths.be/placeholder v2.1.1 by @mathias */
(function(factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD
		define(['jquery'], factory);
	} else if (typeof module === 'object' && module.exports) {
		factory(require('jquery'));
	} else {
		// Browser globals
		factory(jQuery);
	}
}(function($) {

	// Opera Mini v7 doesn't support placeholder although its DOM seems to indicate so
	var isOperaMini = Object.prototype.toString.call(window.operamini) == '[object OperaMini]';
	var isInputSupported = 'placeholder' in document.createElement('input') && !isOperaMini;
	var isTextareaSupported = 'placeholder' in document.createElement('textarea') && !isOperaMini;
	var valHooks = $.valHooks;
	var propHooks = $.propHooks;
	var hooks;
	var placeholder;

	if (isInputSupported && isTextareaSupported) {

		placeholder = $.fn.placeholder = function() {
			return this;
		};

		placeholder.input = placeholder.textarea = true;

	} else {

		var settings = {};

		placeholder = $.fn.placeholder = function(options) {

			var defaults = {customClass: 'placeholder'};
			settings = $.extend({}, defaults, options);

			var $this = this;
			$this
				.filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
				.not('.'+settings.customClass)
				.bind({
					'focus.placeholder': clearPlaceholder,
					'blur.placeholder': setPlaceholder
				})
				.data('placeholder-enabled', true)
				.trigger('blur.placeholder');
			return $this;
		};

		placeholder.input = isInputSupported;
		placeholder.textarea = isTextareaSupported;

		hooks = {
			'get': function(element) {
				var $element = $(element);

				var $passwordInput = $element.data('placeholder-password');
				if ($passwordInput) {
					return $passwordInput[0].value;
				}

				return $element.data('placeholder-enabled') && $element.hasClass(settings.customClass) ? '' : element.value;
			},
			'set': function(element, value) {
				var $element = $(element);

				var $passwordInput = $element.data('placeholder-password');
				if ($passwordInput) {
					return $passwordInput[0].value = value;
				}

				if (!$element.data('placeholder-enabled')) {
					return element.value = value;
				}
				if (value === '') {
					element.value = value;
					// Issue #56: Setting the placeholder causes problems if the element continues to have focus.
					if (element != safeActiveElement()) {
						// We can't use `triggerHandler` here because of dummy text/password inputs :(
						setPlaceholder.call(element);
					}
				} else if ($element.hasClass(settings.customClass)) {
					clearPlaceholder.call(element, true, value) || (element.value = value);
				} else {
					element.value = value;
				}
				// `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
				return $element;
			}
		};

		if (!isInputSupported) {
			valHooks.input = hooks;
			propHooks.value = hooks;
		}
		if (!isTextareaSupported) {
			valHooks.textarea = hooks;
			propHooks.value = hooks;
		}

		$(function() {
			// Look for forms
			$(document).delegate('form', 'submit.placeholder', function() {
				// Clear the placeholder values so they don't get submitted
				var $inputs = $('.'+settings.customClass, this).each(clearPlaceholder);
				setTimeout(function() {
					$inputs.each(setPlaceholder);
				}, 10);
			});
		});

		// Clear placeholder values upon page reload
		$(window).bind('beforeunload.placeholder', function() {
			$('.'+settings.customClass).each(function() {
				this.value = '';
			});
		});

	}

	function args(elem) {
		// Return an object of element attributes
		var newAttrs = {};
		var rinlinejQuery = /^jQuery\d+$/;
		$.each(elem.attributes, function(i, attr) {
			if (attr.specified && !rinlinejQuery.test(attr.name)) {
				newAttrs[attr.name] = attr.value;
			}
		});
		return newAttrs;
	}

	function clearPlaceholder(event, value) {
		var input = this;
		var $input = $(input);
		if (input.value == $input.attr('placeholder') && $input.hasClass(settings.customClass)) {
			if ($input.data('placeholder-password')) {
				$input = $input.hide().nextAll('input[type="password"]:first').show().attr('id', $input.removeAttr('id').data('placeholder-id'));
				// If `clearPlaceholder` was called from `$.valHooks.input.set`
				if (event === true) {
					return $input[0].value = value;
				}
				$input.focus();
			} else {
				input.value = '';
				$input.removeClass(settings.customClass);
				input == safeActiveElement() && input.select();
			}
		}
	}

	function setPlaceholder() {
		var $replacement;
		var input = this;
		var $input = $(input);
		var id = this.id;
		if (input.value === '') {
			if (input.type === 'password') {
				if (!$input.data('placeholder-textinput')) {
					try {
						$replacement = $input.clone().attr({ 'type': 'text' });
					} catch(e) {
						$replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
					}
					$replacement
						.removeAttr('name')
						.data({
							'placeholder-password': $input,
							'placeholder-id': id
						})
						.bind('focus.placeholder', clearPlaceholder);
					$input
						.data({
							'placeholder-textinput': $replacement,
							'placeholder-id': id
						})
						.before($replacement);
				}
				$input = $input.removeAttr('id').hide().prevAll('input[type="text"]:first').attr('id', id).show();
				// Note: `$input[0] != input` now!
			}
			$input.addClass(settings.customClass);
			$input[0].value = $input.attr('placeholder');
		} else {
			$input.removeClass(settings.customClass);
		}
	}

	function safeActiveElement() {
		// Avoid IE9 `document.activeElement` of death
		// https://github.com/mathiasbynens/jquery-placeholder/pull/99
		try {
			return document.activeElement;
		} catch (exception) {}
	}

}));
// v1.0.1
(function ($, window, document, undefined) {
	var pluginName = "bbFormat",
		defaults = {
			changeEventName: 'bbFormatChangeEvent',
			noDefault: false,
			defaultValue: 0,
			enableEmpty: false,
			minValue: 0,
			maxValue: 1000000000,
			thousendSep: ',',
			decimalSep: '.',
			decimal: 0,
			symbolLeft: true,
			symbol: '',
			numberOnly: true,
			animateValue: {
				active: true,
				duration: 300
			}
		};

	function Plugin(element, options) {
		this.element = element;
		this.$element = $(element);
		this.options = $.extend({}, defaults, options);
		this._defaults = defaults;
		this.changeEvent = $.Event(this.options.changeEventName);
		this.init();
	}

	Plugin.prototype = {

		init: function () {
			var initVal;
			if (this.$element.is(':input')) {
				initVal = this.$element.val();
				initVal = parseFloat(initVal);
				initVal = !isNaN( initVal ) ? initVal : this.options.defaultValue;
				if (!this.options.noDefault) {
					this.$element.val(this._numberToCurrency(initVal, this.options.decimal));
				}

				this.addEvents();

			} else {
				initVal = this.$element.text();
				initVal = parseFloat(initVal);
				initVal = !isNaN( initVal ) ? initVal : this.options.defaultValue;
				this.$element.text(this._numberToCurrency(initVal, this.options.decimal));
			}
		},

		addEvents: function() {
			this.$element
				.on('blur.' + pluginName, $.proxy(this._setFieldFormatNum, this))
				.on('focus.' + pluginName, $.proxy(this._unsetFieldFormatNum, this))
				.on('change.' + pluginName, $.proxy(this._onChange, this));

			if (this.options.numberOnly) {
				this.$element.on('keydown.' + pluginName, $.proxy(this._filterNum, this));
			}
		},

		_onChange: function(e) {
			var inp = $(e.currentTarget),
				v = inp.val();

			this.changeEvent.bbValue = this._getMinMax(v);
			this.$element.trigger(this.changeEvent);
		},

		_setFieldFormatNum: function (e) {
			var inp = $(e.currentTarget),
				v = this._getNumber(inp.val());


			if (this.options.enableEmpty) {
				if (v !== '') {
					v = this._getMinMax(v);
					v = this._numberToCurrency(v, this.options.decimal);
				}
			} else {
				v = this._getMinMax(v);
				v = this._numberToCurrency(v, this.options.decimal);
			}

			inp.val(v);
			inp.trigger('bbFormatBlurEvent');
		},

		_getMinMax: function(v) {

			var min = parseInt(this.options.minValue, 10),
				max = parseInt(this.options.maxValue, 10);
			v = parseFloat(v) || 0;

			if (!isNaN(min)) {
				v = Math.max(min, v);
			}
			if (!isNaN(max)) {
				v = Math.min(max, v);
			}

			return v;
		},

		_unsetFieldFormatNum: function(e) {
			var inp = $(e.currentTarget),
				v = inp.val(),
				newV = String(v).split(this.options.thousendSep).join('').split(this.options.symbol).join('');

			inp.val(newV);
			inp.trigger('bbFormatFocusEvent');
		},

		_getNumber: function (s) {
			if (typeof s === 'number') {
				return s;
			}

			s = s && s.toString() || '';
			s = s.split(this.options.thousendSep).join('');
			s = s.split(this.options.symbol).join('');
			s = s.split(this.options.decimalSep).join('.');

			return parseFloat(s);
		},

		_numberToCurrency: function (n, decimal, nan, noCur) {
			var v;

			if (decimal === 0) {
				n = Math.floor(n);
			}

			v = this._numberFormat(n, this.options.decimalSep, this.options.thousendSep, decimal, nan);

			if (!noCur) {
				if (this.options.symbolLeft) {
					v = this.options.symbol + v;
				} else {
					v += this.options.symbol;
				}
			}
			return v;
		},

		_numberFormat: function (n, decSep, tSep, prec, nan) {
			n = parseFloat(n);
			if (isNaN(n)) {
				return typeof nan !== 'undefined' ? nan : '';
			}
			var sign = '';
			if (n < 0) {
				n = -n;
				sign = '-';
			}

			n = isNaN(prec) || prec<0 ? n.toString(10) : n.toFixed(prec);
			var nParts = n.split('.');
			for (var i=nParts[0].length-3; i>0; i-=3) {
				nParts[0] = nParts[0].substr(0,i) + tSep + nParts[0].substr(i);
			}
			return sign + nParts.join(decSep);
		},

		_filterNum: function(e) {

			if (this.options.decimal) {
				if (this.options.decimalSep === ',') {
					if ( $.inArray(e.keyCode,[188, 110]) !== -1) {
						return;
					}
				} else if (this.options.decimalSep === '.') {
					if (e.keyCode === 190 ) {
						return;
					}
				}
			}


			// Allow: backspace, delete, tab, escape, enter
			if ( $.inArray(e.keyCode,[46,8,9,27]) !== -1 ||
					// Allow: Ctrl+A
				(e.keyCode === 65 && e.ctrlKey === true) ||
					// Allow: Ctrl+V
				(e.keyCode === 86 && e.ctrlKey === true) ||
					// Allow: Ctrl+C
				(e.keyCode === 67 && e.ctrlKey === true) ||
					// Allow: home, end, left, right
				(e.keyCode >= 35 && e.keyCode <= 39)) {
				// let it happen, don't do anything
				return;
			} else {
				// Ensure that it is a number and stop the keypress
				if (e.shiftKey || (e.keyCode < 48 || e.keyCode > 57) && (e.keyCode < 96 || e.keyCode > 105 )) {
					e.preventDefault();
				}

				if (e.keyCode === 13) {
					this.$element.trigger('blur');
				}
			}
		},

		_animateValue: function(newVal) {
			var t = this;

			this.$element.each(function(){
				this._animatedNumVal = this._animatedNumVal || 0;
			});

			this.$element.stop();

			this.$element.animate({
				_animatedNumVal: newVal
			},{
				duration: t.options.animateValue.duration,
				step: function () {
					$(this).text(t._numberToCurrency(this._animatedNumVal, t.options.decimal));
				},
				complete: function () {
					$(this).text(t._numberToCurrency(newVal, t.options.decimal));
				}
			});
		},

		val: function() {
			var v = this.$element.is(':input') ? this.$element.val() : this.$element.text();
			return this._getNumber(this.options.symbol ? v.split(this.options.symbol).join('') : v);
		},

		setValue: function (v) {
			if (this.$element.is(':input')) {
				this.$element.val(this._numberToCurrency(this._getNumber(v), this.options.decimal));
			} else {
				if (this.options.animateValue.active) {
					this._animateValue(v);
				} else {
					this.$element.text(this._numberToCurrency(this._getNumber(v), this.options.decimal));
				}
			}
		}
	};

	$.fn[pluginName] = function (options) {
		if (this.length === 0) { return; }

		var val;

		this.each(function () {
			var pluginInstance = $.data(this, "plugin_" + pluginName);
			if (!pluginInstance) {
				$.data(this, "plugin_" + pluginName, new Plugin(this, options));
				return this;
			} else {
				if (options && options.value !== undefined ) {
					pluginInstance.setValue(options.value);
				}
				val = pluginInstance.val();
			}
		});

		return val === undefined ? this : val;
	};


})(jQuery, window, document);
/*
 *  jQuery Boilerplate - v3.3.4
 *  A jump-start for jQuery plugins development.
 *  http://jqueryboilerplate.com
 *
 *  Made by Zeno Rocha
 *  Under MIT License
 */
// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ( $, window, document, undefined ) {

	// undefined is used here as the undefined global variable in ECMAScript 3 is
	// mutable (ie. it can be changed by someone else). undefined isn't really being
	// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
	// can no longer be modified.

	// window and document are passed through as local variable rather than global
	// as this (slightly) quickens the resolution process and can be more efficiently
	// minified (especially when both are regularly referenced in your plugin).

	// Create the defaults once
	var pluginName = "bbAccordion",
		defaults = {
			slideUpTime: 300,
			slideDownTime: 300,
			selectorHead: '.fHead',
			selectorContent: '.fContent',
			classOpen: pluginName + '-open',
			eClick: 'click',
			allClosed: true, //  Am Anfang werden alle Einträge geschlossen, außer ein Eintrag hat die Klasse settings.classOpen
			singleOpened: true, // Höchstens ein Eintrag darf Gleichzeitig geöffnet sein
			oneOpened: false, // Mindestens ein Eintrag muss geöffnet sein
			eventOpened: pluginName + '-opened'
		};

	// The actual plugin constructor
	function Plugin ( element, options ) {
		this.element = element;
		this.$el = $(this.element);

		// jQuery has an extend method which merges the contents of two or
		// more objects, storing the result in the first object. The first object
		// is generally empty as we don't want to alter the default options for
		// future instances of the plugin
		this.settings = $.extend( {}, defaults, options );
		this._defaults = defaults;
		this._name = pluginName;
		this.init();
	}

	// Avoid Plugin.prototype conflicts
	$.extend(Plugin.prototype, {
		init: function () {
			// Place initialization logic here
			// You already have access to the DOM element and
			// the options via the instance, e.g. this.element
			// and this.settings
			// you can add more functions like the one below and
			// call them like so: this.yourOtherFunction(this.element, this.settings).
			this.$heads = this.$el.find(this.settings.selectorHead);
			this.$contents = this.$el.find(this.settings.selectorContent);
			if (this.settings.allClosed) this._closeAll( false, true );
			if (this.settings.oneOpened && this.$heads.filter('.'+this.settings.classOpen).length === 0) this.$contents.first().slideDown(0);
			this.$heads.on(this.settings.eClick, $.proxy(this._toggleFold, this));
		},

		_toggleFold: function ( e ) {
			var btn = $(e.currentTarget),
				content = btn.next(this.settings.selectorContent),
				doClose = btn.hasClass(this.settings.classOpen);

			if(!btn.hasClass('run')){
				btn.addClass('run');
				if (doClose) {
					if ( !(this.settings.oneOpened && this.$heads.filter('.'+this.settings.classOpen).length <= 1) ) {
						content.slideUp(this.settings.slideUpTime, function(){
							btn.removeClass('run');
						});
						btn.toggleClass(this.settings.classOpen, !doClose);
					}
				} else {
					if ( this.settings.singleOpened ) {
						this._closeAll( true );
						//this.$heads
						//	.filter('.'+this.settings.classOpen)
						//	.trigger(this.settings.eClick);
					}

					var t = this;


					content.slideDown(this.settings.slideDownTime, function(){
						$(t.element).trigger('open');
						btn.removeClass('run');

					});
					btn.trigger(this.settings.eventOpened);
					btn.toggleClass(this.settings.classOpen, !doClose);
				}
			}
		},

		_closeAll: function( animated, keepInitial ) {
			var initialOpenedHeads = this.$heads.filter('.' + this.settings.classOpen);
			var initialOpenedContents = initialOpenedHeads.next();

			this.$heads.removeClass(this.settings.classOpen);
			this.$contents.slideUp( animated ? this.settings.slideDownTime : 0);

			if ( keepInitial ) {
				initialOpenedHeads.addClass(this.settings.classOpen);
				initialOpenedContents.slideDown(0);
			}
		}

	});

	// A really lightweight plugin wrapper around the constructor,
	// preventing against multiple instantiations
	$.fn[ pluginName ] = function ( options ) {
		var plugin;
		this.each(function() {
			plugin = $.data( this, "plugin_" + pluginName );
			if ( !plugin ) {
				$.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
			} else if ( options ) {
				plugin.settings =  $.extend( plugin.settings, options );
			}
		});

		// chain jQuery functions
		return this;
	};

})( jQuery, window, document );
/*
 * jQuery FlexSlider v2.7.0
 * Copyright 2012 WooThemes
 * Contributing Author: Tyler Smith
 */
;
(function ($) {

	var focused = true;

	//FlexSlider: Object Instance
	$.flexslider = function(el, options) {
		var slider = $(el);

		// making variables public

		//if rtl value was not passed and html is in rtl..enable it by default.
		if(typeof options.rtl=='undefined' && $('html').attr('dir')=='rtl'){
			options.rtl=true;
		}
		slider.vars = $.extend({}, $.flexslider.defaults, options);

		var namespace = slider.vars.namespace,
			msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
			touch = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch,
			// deprecating this idea, as devices are being released with both of these events
			eventType = "click touchend MSPointerUp keyup",
			watchedEvent = "",
			watchedEventClearTimer,
			vertical = slider.vars.direction === "vertical",
			reverse = slider.vars.reverse,
			carousel = (slider.vars.itemWidth > 0),
			fade = slider.vars.animation === "fade",
			asNav = slider.vars.asNavFor !== "",
			methods = {};

		// Store a reference to the slider object
		$.data(el, "flexslider", slider);

		// Private slider methods
		methods = {
			init: function() {
				slider.animating = false;
				// Get current slide and make sure it is a number
				slider.currentSlide = parseInt( ( slider.vars.startAt ? slider.vars.startAt : 0), 10 );
				if ( isNaN( slider.currentSlide ) ) { slider.currentSlide = 0; }
				slider.animatingTo = slider.currentSlide;
				slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);
				slider.containerSelector = slider.vars.selector.substr(0,slider.vars.selector.search(' '));
				slider.slides = $(slider.vars.selector, slider);
				slider.container = $(slider.containerSelector, slider);
				slider.count = slider.slides.length;
				// SYNC:
				slider.syncExists = $(slider.vars.sync).length > 0;
				// SLIDE:
				if (slider.vars.animation === "slide") { slider.vars.animation = "swing"; }
				slider.prop = (vertical) ? "top" : ( slider.vars.rtl ? "marginRight" : "marginLeft" );
				slider.args = {};
				// SLIDESHOW:
				slider.manualPause = false;
				slider.stopped = false;
				//PAUSE WHEN INVISIBLE
				slider.started = false;
				slider.startTimeout = null;
				// TOUCH/USECSS:
				slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function() {
					var obj = document.createElement('div'),
						props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
					for (var i in props) {
						if ( obj.style[ props[i] ] !== undefined ) {
							slider.pfx = props[i].replace('Perspective','').toLowerCase();
							slider.prop = "-" + slider.pfx + "-transform";
							return true;
						}
					}
					return false;
				}());
				slider.ensureAnimationEnd = '';
				// CONTROLSCONTAINER:
				if (slider.vars.controlsContainer !== "") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer);
				// MANUAL:
				if (slider.vars.manualControls !== "") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls);

				// CUSTOM DIRECTION NAV:
				if (slider.vars.customDirectionNav !== "") slider.customDirectionNav = $(slider.vars.customDirectionNav).length === 2 && $(slider.vars.customDirectionNav);

				// RANDOMIZE:
				if (slider.vars.randomize) {
					slider.slides.sort(function() { return (Math.round(Math.random())-0.5); });
					slider.container.empty().append(slider.slides);
				}

				slider.doMath();

				// INIT
				slider.setup("init");

				// CONTROLNAV:
				if (slider.vars.controlNav) { methods.controlNav.setup(); }

				// DIRECTIONNAV:
				if (slider.vars.directionNav) { methods.directionNav.setup(); }

				// KEYBOARD:
				if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) {
					$(document).bind('keyup', function(event) {
						var keycode = event.keyCode;
						if (!slider.animating && (keycode === 39 || keycode === 37)) {
							var target = (slider.vars.rtl?
									((keycode === 37) ? slider.getTarget('next') :
										(keycode === 39) ? slider.getTarget('prev') : false)
									:
									((keycode === 39) ? slider.getTarget('next') :
										(keycode === 37) ? slider.getTarget('prev') : false)
								)
							;
							slider.flexAnimate(target, slider.vars.pauseOnAction);
						}
					});
				}
				// MOUSEWHEEL:
				if (slider.vars.mousewheel) {
					slider.bind('mousewheel', function(event, delta, deltaX, deltaY) {
						event.preventDefault();
						var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');
						slider.flexAnimate(target, slider.vars.pauseOnAction);
					});
				}

				// PAUSEPLAY
				if (slider.vars.pausePlay) { methods.pausePlay.setup(); }

				//PAUSE WHEN INVISIBLE
				if (slider.vars.slideshow && slider.vars.pauseInvisible) { methods.pauseInvisible.init(); }

				// SLIDSESHOW
				if (slider.vars.slideshow) {
					if (slider.vars.pauseOnHover) {
						slider.hover(function() {
							if (!slider.manualPlay && !slider.manualPause) { slider.pause(); }
						}, function() {
							if (!slider.manualPause && !slider.manualPlay && !slider.stopped) { slider.play(); }
						});
					}
					// initialize animation
					//If we're visible, or we don't use PageVisibility API
					if(!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) {
						(slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play();
					}
				}

				// ASNAV:
				if (asNav) { methods.asNav.setup(); }

				// TOUCH
				if (touch && slider.vars.touch) { methods.touch(); }

				// FADE&&SMOOTHHEIGHT || SLIDE:
				if (!fade || (fade && slider.vars.smoothHeight)) { $(window).bind("resize orientationchange focus", methods.resize); }

				slider.find("img").attr("draggable", "false");

				// API: start() Callback
				setTimeout(function(){
					slider.vars.start(slider);
				}, 200);
			},
			asNav: {
				setup: function() {
					slider.asNav = true;
					slider.animatingTo = Math.floor(slider.currentSlide/slider.move);
					slider.currentItem = slider.currentSlide;
					slider.slides.removeClass(namespace + "active-slide").eq(slider.currentItem).addClass(namespace + "active-slide");
					if(!msGesture){
						slider.slides.on(eventType, function(e){
							e.preventDefault();
							var $slide = $(this),
								target = $slide.index();
							var posFromX;
							if(slider.vars.rtl){
								posFromX = -1*($slide.offset().right - $(slider).scrollLeft()); // Find position of slide relative to right of slider container
							}
							else
							{
								posFromX = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container
							}
							if( posFromX <= 0 && $slide.hasClass( namespace + 'active-slide' ) ) {
								slider.flexAnimate(slider.getTarget("prev"), true);
							} else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + "active-slide")) {
								slider.direction = (slider.currentItem < target) ? "next" : "prev";
								slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
							}
						});
					}else{
						el._slider = slider;
						slider.slides.each(function (){
							var that = this;
							that._gesture = new MSGesture();
							that._gesture.target = that;
							that.addEventListener("MSPointerDown", function (e){
								e.preventDefault();
								if(e.currentTarget._gesture) {
									e.currentTarget._gesture.addPointer(e.pointerId);
								}
							}, false);
							that.addEventListener("MSGestureTap", function (e){
								e.preventDefault();
								var $slide = $(this),
									target = $slide.index();
								if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {
									slider.direction = (slider.currentItem < target) ? "next" : "prev";
									slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
								}
							});
						});
					}
				}
			},
			controlNav: {
				setup: function() {
					if (!slider.manualControls) {
						methods.controlNav.setupPaging();
					} else { // MANUALCONTROLS:
						methods.controlNav.setupManual();
					}
				},
				setupPaging: function() {
					var type = (slider.vars.controlNav === "thumbnails") ? 'control-thumbs' : 'control-paging',
						j = 1,
						item,
						slide;

					slider.controlNavScaffold = $('<ol class="'+ namespace + 'control-nav ' + namespace + type + '"></ol>');

					if (slider.pagingCount > 1) {
						for (var i = 0; i < slider.pagingCount; i++) {
							slide = slider.slides.eq(i);
							if ( undefined === slide.attr( 'data-thumb-alt' ) ) { slide.attr( 'data-thumb-alt', '' ); }
							var altText = ( '' !== slide.attr( 'data-thumb-alt' ) ) ? altText = ' alt="' + slide.attr( 'data-thumb-alt' ) + '"' : '';
							item = (slider.vars.controlNav === "thumbnails") ? '<img src="' + slide.attr( 'data-thumb' ) + '"' + altText + '/>' : '<a href="#">' + j + '</a>';
							if ( 'thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions ) {
								var captn = slide.attr( 'data-thumbcaption' );
								if ( '' !== captn && undefined !== captn ) { item += '<span class="' + namespace + 'caption">' + captn + '</span>'; }
							}
							slider.controlNavScaffold.append('<li>' + item + '</li>');
							j++;
						}
					}

					// CONTROLSCONTAINER:
					(slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);
					methods.controlNav.set();

					methods.controlNav.active();

					slider.controlNavScaffold.delegate('a, img', eventType, function(event) {
						event.preventDefault();

						if (watchedEvent === "" || watchedEvent === event.type) {
							var $this = $(this),
								target = slider.controlNav.index($this);

							if (!$this.hasClass(namespace + 'active')) {
								slider.direction = (target > slider.currentSlide) ? "next" : "prev";
								slider.flexAnimate(target, slider.vars.pauseOnAction);
							}
						}

						// setup flags to prevent event duplication
						if (watchedEvent === "") {
							watchedEvent = event.type;
						}
						methods.setToClearWatchedEvent();

					});
				},
				setupManual: function() {
					slider.controlNav = slider.manualControls;
					methods.controlNav.active();

					slider.controlNav.bind(eventType, function(event) {
						event.preventDefault();

						if (watchedEvent === "" || watchedEvent === event.type) {
							var $this = $(this),
								target = slider.controlNav.index($this);

							if (!$this.hasClass(namespace + 'active')) {
								(target > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev";
								slider.flexAnimate(target, slider.vars.pauseOnAction);
							}
						}

						// setup flags to prevent event duplication
						if (watchedEvent === "") {
							watchedEvent = event.type;
						}
						methods.setToClearWatchedEvent();
					});
				},
				set: function() {
					var selector = (slider.vars.controlNav === "thumbnails") ? 'img' : 'a';
					slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);
				},
				active: function() {
					slider.controlNav.removeClass(namespace + "active").eq(slider.animatingTo).addClass(namespace + "active");
				},
				update: function(action, pos) {
					if (slider.pagingCount > 1 && action === "add") {
						slider.controlNavScaffold.append($('<li><a href="#">' + slider.count + '</a></li>'));
					} else if (slider.pagingCount === 1) {
						slider.controlNavScaffold.find('li').remove();
					} else {
						slider.controlNav.eq(pos).closest('li').remove();
					}
					methods.controlNav.set();
					(slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();
				}
			},
			directionNav: {
				setup: function() {
					var directionNavScaffold = $('<ul class="' + namespace + 'direction-nav"><li class="' + namespace + 'nav-prev"><a class="' + namespace + 'prev" href="#">' + slider.vars.prevText + '</a></li><li class="' + namespace + 'nav-next"><a class="' + namespace + 'next" href="#">' + slider.vars.nextText + '</a></li></ul>');

					// CUSTOM DIRECTION NAV:
					if (slider.customDirectionNav) {
						slider.directionNav = slider.customDirectionNav;
						// CONTROLSCONTAINER:
					} else if (slider.controlsContainer) {
						$(slider.controlsContainer).append(directionNavScaffold);
						slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);
					} else {
						slider.append(directionNavScaffold);
						slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);
					}

					methods.directionNav.update();

					slider.directionNav.bind(eventType, function(event) {
						event.preventDefault();
						var target;

						if (watchedEvent === "" || watchedEvent === event.type) {
							target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');
							slider.flexAnimate(target, slider.vars.pauseOnAction);
						}

						// setup flags to prevent event duplication
						if (watchedEvent === "") {
							watchedEvent = event.type;
						}
						methods.setToClearWatchedEvent();
					});
				},
				update: function() {
					var disabledClass = namespace + 'disabled';
					if (slider.pagingCount === 1) {
						slider.directionNav.addClass(disabledClass).attr('tabindex', '-1');
					} else if (!slider.vars.animationLoop) {
						if (slider.animatingTo === 0) {
							slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "prev").addClass(disabledClass).attr('tabindex', '-1');
						} else if (slider.animatingTo === slider.last) {
							slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "next").addClass(disabledClass).attr('tabindex', '-1');
						} else {
							slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
						}
					} else {
						slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
					}
				}
			},
			pausePlay: {
				setup: function() {
					var pausePlayScaffold = $('<div class="' + namespace + 'pauseplay"><a href="#"></a></div>');

					// CONTROLSCONTAINER:
					if (slider.controlsContainer) {
						slider.controlsContainer.append(pausePlayScaffold);
						slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);
					} else {
						slider.append(pausePlayScaffold);
						slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);
					}

					methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');

					slider.pausePlay.bind(eventType, function(event) {
						event.preventDefault();

						if (watchedEvent === "" || watchedEvent === event.type) {
							if ($(this).hasClass(namespace + 'pause')) {
								slider.manualPause = true;
								slider.manualPlay = false;
								slider.pause();
							} else {
								slider.manualPause = false;
								slider.manualPlay = true;
								slider.play();
							}
						}

						// setup flags to prevent event duplication
						if (watchedEvent === "") {
							watchedEvent = event.type;
						}
						methods.setToClearWatchedEvent();
					});
				},
				update: function(state) {
					(state === "play") ? slider.pausePlay.removeClass(namespace + 'pause').addClass(namespace + 'play').html(slider.vars.playText) : slider.pausePlay.removeClass(namespace + 'play').addClass(namespace + 'pause').html(slider.vars.pauseText);
				}
			},
			touch: function() {
				var startX,
					startY,
					offset,
					cwidth,
					dx,
					startT,
					onTouchStart,
					onTouchMove,
					onTouchEnd,
					scrolling = false,
					localX = 0,
					localY = 0,
					accDx = 0;

				if(!msGesture){
					onTouchStart = function(e) {
						if (slider.animating) {
							e.preventDefault();
						} else if ( ( window.navigator.msPointerEnabled ) || e.touches.length === 1 ) {
							slider.pause();
							// CAROUSEL:
							cwidth = (vertical) ? slider.h : slider. w;
							startT = Number(new Date());
							// CAROUSEL:

							// Local vars for X and Y points.
							localX = e.touches[0].pageX;
							localY = e.touches[0].pageY;

							offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
								(carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
									(carousel && slider.currentSlide === slider.last) ? slider.limit :
										(carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
											(reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
							startX = (vertical) ? localY : localX;
							startY = (vertical) ? localX : localY;
							el.addEventListener('touchmove', onTouchMove, false);
							el.addEventListener('touchend', onTouchEnd, false);
						}
					};

					onTouchMove = function(e) {
						// Local vars for X and Y points.

						localX = e.touches[0].pageX;
						localY = e.touches[0].pageY;

						dx = (vertical) ? startX - localY : (slider.vars.rtl?-1:1)*(startX - localX);
						scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY));
						var fxms = 500;

						if ( ! scrolling || Number( new Date() ) - startT > fxms ) {
							e.preventDefault();
							if (!fade && slider.transitions) {
								if (!slider.vars.animationLoop) {
									dx = dx/((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx)/cwidth+2) : 1);
								}
								slider.setProps(offset + dx, "setTouch");
							}
						}
					};

					onTouchEnd = function(e) {
						// finish the touch by undoing the touch session
						el.removeEventListener('touchmove', onTouchMove, false);

						if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
							var updateDx = (reverse) ? -dx : dx,
								target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');

							if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) {
								slider.flexAnimate(target, slider.vars.pauseOnAction);
							} else {
								if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); }
							}
						}
						el.removeEventListener('touchend', onTouchEnd, false);

						startX = null;
						startY = null;
						dx = null;
						offset = null;
					};

					el.addEventListener('touchstart', onTouchStart, false);
				}else{
					el.style.msTouchAction = "none";
					el._gesture = new MSGesture();
					el._gesture.target = el;
					el.addEventListener("MSPointerDown", onMSPointerDown, false);
					el._slider = slider;
					el.addEventListener("MSGestureChange", onMSGestureChange, false);
					el.addEventListener("MSGestureEnd", onMSGestureEnd, false);

					function onMSPointerDown(e){
						e.stopPropagation();
						if (slider.animating) {
							e.preventDefault();
						}else{
							slider.pause();
							el._gesture.addPointer(e.pointerId);
							accDx = 0;
							cwidth = (vertical) ? slider.h : slider. w;
							startT = Number(new Date());
							// CAROUSEL:

							offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
								(carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
									(carousel && slider.currentSlide === slider.last) ? slider.limit :
										(carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
											(reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
						}
					}

					function onMSGestureChange(e) {
						e.stopPropagation();
						var slider = e.target._slider;
						if(!slider){
							return;
						}
						var transX = -e.translationX,
							transY = -e.translationY;

						//Accumulate translations.
						accDx = accDx + ((vertical) ? transY : transX);
						dx = (slider.vars.rtl?-1:1)*accDx;
						scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY));

						if(e.detail === e.MSGESTURE_FLAG_INERTIA){
							setImmediate(function (){
								el._gesture.stop();
							});

							return;
						}

						if (!scrolling || Number(new Date()) - startT > 500) {
							e.preventDefault();
							if (!fade && slider.transitions) {
								if (!slider.vars.animationLoop) {
									dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1);
								}
								slider.setProps(offset + dx, "setTouch");
							}
						}
					}

					function onMSGestureEnd(e) {
						e.stopPropagation();
						var slider = e.target._slider;
						if(!slider){
							return;
						}
						if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
							var updateDx = (reverse) ? -dx : dx,
								target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');

							if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) {
								slider.flexAnimate(target, slider.vars.pauseOnAction);
							} else {
								if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); }
							}
						}

						startX = null;
						startY = null;
						dx = null;
						offset = null;
						accDx = 0;
					}
				}
			},
			resize: function() {
				if (!slider.animating && slider.is(':visible')) {
					if (!carousel) { slider.doMath(); }

					if (fade) {
						// SMOOTH HEIGHT:
						methods.smoothHeight();
					} else if (carousel) { //CAROUSEL:
						slider.slides.width(slider.computedW);
						slider.update(slider.pagingCount);
						slider.setProps();
					}
					else if (vertical) { //VERTICAL:
						slider.viewport.height(slider.h);
						slider.setProps(slider.h, "setTotal");
					} else {
						// SMOOTH HEIGHT:
						if (slider.vars.smoothHeight) { methods.smoothHeight(); }
						slider.newSlides.width(slider.computedW);
						slider.setProps(slider.computedW, "setTotal");
					}
				}
			},
			smoothHeight: function(dur) {
				if (!vertical || fade) {
					var $obj = (fade) ? slider : slider.viewport;
					(dur) ? $obj.animate({"height": slider.slides.eq(slider.animatingTo).innerHeight()}, dur) : $obj.innerHeight(slider.slides.eq(slider.animatingTo).innerHeight());
				}
			},
			sync: function(action) {
				var $obj = $(slider.vars.sync).data("flexslider"),
					target = slider.animatingTo;

				switch (action) {
					case "animate": $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true); break;
					case "play": if (!$obj.playing && !$obj.asNav) { $obj.play(); } break;
					case "pause": $obj.pause(); break;
				}
			},
			uniqueID: function($clone) {
				// Append _clone to current level and children elements with id attributes
				$clone.filter( '[id]' ).add($clone.find( '[id]' )).each(function() {
					var $this = $(this);
					$this.attr( 'id', $this.attr( 'id' ) + '_clone' );
				});
				return $clone;
			},
			pauseInvisible: {
				visProp: null,
				init: function() {
					var visProp = methods.pauseInvisible.getHiddenProp();
					if (visProp) {
						var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';
						document.addEventListener(evtname, function() {
							if (methods.pauseInvisible.isHidden()) {
								if(slider.startTimeout) {
									clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible
								} else {
									slider.pause(); //Or just pause
								}
							}
							else {
								if(slider.started) {
									slider.play(); //Initiated before, just play
								} else {
									if (slider.vars.initDelay > 0) {
										setTimeout(slider.play, slider.vars.initDelay);
									} else {
										slider.play(); //Didn't init before: simply init or wait for it
									}
								}
							}
						});
					}
				},
				isHidden: function() {
					var prop = methods.pauseInvisible.getHiddenProp();
					if (!prop) {
						return false;
					}
					return document[prop];
				},
				getHiddenProp: function() {
					var prefixes = ['webkit','moz','ms','o'];
					// if 'hidden' is natively supported just return it
					if ('hidden' in document) {
						return 'hidden';
					}
					// otherwise loop over all the known prefixes until we find one
					for ( var i = 0; i < prefixes.length; i++ ) {
						if ((prefixes[i] + 'Hidden') in document) {
							return prefixes[i] + 'Hidden';
						}
					}
					// otherwise it's not supported
					return null;
				}
			},
			setToClearWatchedEvent: function() {
				clearTimeout(watchedEventClearTimer);
				watchedEventClearTimer = setTimeout(function() {
					watchedEvent = "";
				}, 3000);
			}
		};

		// public methods
		slider.flexAnimate = function(target, pause, override, withSync, fromNav) {
			if (!slider.vars.animationLoop && target !== slider.currentSlide) {
				slider.direction = (target > slider.currentSlide) ? "next" : "prev";
			}

			if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? "next" : "prev";

			if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(":visible")) {
				if (asNav && withSync) {
					var master = $(slider.vars.asNavFor).data('flexslider');
					slider.atEnd = target === 0 || target === slider.count - 1;
					master.flexAnimate(target, true, false, true, fromNav);
					slider.direction = (slider.currentItem < target) ? "next" : "prev";
					master.direction = slider.direction;

					if (Math.ceil((target + 1)/slider.visible) - 1 !== slider.currentSlide && target !== 0) {
						slider.currentItem = target;
						slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
						target = Math.floor(target/slider.visible);
					} else {
						slider.currentItem = target;
						slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
						return false;
					}
				}

				slider.animating = true;
				slider.animatingTo = target;

				// SLIDESHOW:
				if (pause) { slider.pause(); }

				// API: before() animation Callback
				slider.vars.before(slider);

				// SYNC:
				if (slider.syncExists && !fromNav) { methods.sync("animate"); }

				// CONTROLNAV
				if (slider.vars.controlNav) { methods.controlNav.active(); }

				// !CAROUSEL:
				// CANDIDATE: slide active class (for add/remove slide)
				if (!carousel) { slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide'); }

				// INFINITE LOOP:
				// CANDIDATE: atEnd
				slider.atEnd = target === 0 || target === slider.last;

				// DIRECTIONNAV:
				if (slider.vars.directionNav) { methods.directionNav.update(); }

				if (target === slider.last) {
					// API: end() of cycle Callback
					slider.vars.end(slider);
					// SLIDESHOW && !INFINITE LOOP:
					if (!slider.vars.animationLoop) { slider.pause(); }
				}

				// SLIDE:
				if (!fade) {
					var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,
						margin, slideString, calcNext;

					// INFINITE LOOP / REVERSE:
					if (carousel) {
						margin = slider.vars.itemMargin;
						calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;
						slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;
					} else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== "next") {
						slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;
					} else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== "prev") {
						slideString = (reverse) ? 0 : (slider.count + 1) * dimension;
					} else {
						slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;
					}
					slider.setProps(slideString, "", slider.vars.animationSpeed);
					if (slider.transitions) {
						if (!slider.vars.animationLoop || !slider.atEnd) {
							slider.animating = false;
							slider.currentSlide = slider.animatingTo;
						}

						// Unbind previous transitionEnd events and re-bind new transitionEnd event
						slider.container.unbind("webkitTransitionEnd transitionend");
						slider.container.bind("webkitTransitionEnd transitionend", function() {
							clearTimeout(slider.ensureAnimationEnd);
							slider.wrapup(dimension);
						});

						// Insurance for the ever-so-fickle transitionEnd event
						clearTimeout(slider.ensureAnimationEnd);
						slider.ensureAnimationEnd = setTimeout(function() {
							slider.wrapup(dimension);
						}, slider.vars.animationSpeed + 100);

					} else {
						slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function(){
							slider.wrapup(dimension);
						});
					}
				} else { // FADE:
					if (!touch) {
						slider.slides.eq(slider.currentSlide).css({"zIndex": 1}).animate({"opacity": 0}, slider.vars.animationSpeed, slider.vars.easing);
						slider.slides.eq(target).css({"zIndex": 2}).animate({"opacity": 1}, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
					} else {
						slider.slides.eq(slider.currentSlide).css({ "opacity": 0, "zIndex": 1 });
						slider.slides.eq(target).css({ "opacity": 1, "zIndex": 2 });
						slider.wrapup(dimension);
					}
				}
				// SMOOTH HEIGHT:
				if (slider.vars.smoothHeight) { methods.smoothHeight(slider.vars.animationSpeed); }
			}
		};
		slider.wrapup = function(dimension) {
			// SLIDE:
			if (!fade && !carousel) {
				if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) {
					slider.setProps(dimension, "jumpEnd");
				} else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) {
					slider.setProps(dimension, "jumpStart");
				}
			}
			slider.animating = false;
			slider.currentSlide = slider.animatingTo;
			// API: after() animation Callback
			slider.vars.after(slider);
		};

		// SLIDESHOW:
		slider.animateSlides = function() {
			if (!slider.animating && focused ) { slider.flexAnimate(slider.getTarget("next")); }
		};
		// SLIDESHOW:
		slider.pause = function() {
			clearInterval(slider.animatedSlides);
			slider.animatedSlides = null;
			slider.playing = false;
			// PAUSEPLAY:
			if (slider.vars.pausePlay) { methods.pausePlay.update("play"); }
			// SYNC:
			if (slider.syncExists) { methods.sync("pause"); }
		};
		// SLIDESHOW:
		slider.play = function() {
			if (slider.playing) { clearInterval(slider.animatedSlides); }
			slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed);
			slider.started = slider.playing = true;
			// PAUSEPLAY:
			if (slider.vars.pausePlay) { methods.pausePlay.update("pause"); }
			// SYNC:
			if (slider.syncExists) { methods.sync("play"); }
		};
		// STOP:
		slider.stop = function () {
			slider.pause();
			slider.stopped = true;
		};
		slider.canAdvance = function(target, fromNav) {
			// ASNAV:
			var last = (asNav) ? slider.pagingCount - 1 : slider.last;
			return (fromNav) ? true :
				(asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === "prev") ? true :
					(asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== "next") ? false :
						(target === slider.currentSlide && !asNav) ? false :
							(slider.vars.animationLoop) ? true :
								(slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== "next") ? false :
									(slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === "next") ? false :
										true;
		};
		slider.getTarget = function(dir) {
			slider.direction = dir;
			if (dir === "next") {
				return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;
			} else {
				return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;
			}
		};

		// SLIDE:
		slider.setProps = function(pos, special, dur) {
			var target = (function() {
				var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo,
					posCalc = (function() {
						if (carousel) {
							return (special === "setTouch") ? pos :
								(reverse && slider.animatingTo === slider.last) ? 0 :
									(reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
										(slider.animatingTo === slider.last) ? slider.limit : posCheck;
						} else {
							switch (special) {
								case "setTotal": return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;
								case "setTouch": return (reverse) ? pos : pos;
								case "jumpEnd": return (reverse) ? pos : slider.count * pos;
								case "jumpStart": return (reverse) ? slider.count * pos : pos;
								default: return pos;
							}
						}
					}());

				return (posCalc * ((slider.vars.rtl)?1:-1)) + "px";
			}());

			if (slider.transitions) {
				target = (vertical) ? "translate3d(0," + target + ",0)" : "translate3d(" + ((slider.vars.rtl?-1:1)*parseInt(target)+'px') + ",0,0)";
				dur = (dur !== undefined) ? (dur/1000) + "s" : "0s";
				slider.container.css("-" + slider.pfx + "-transition-duration", dur);
				slider.container.css("transition-duration", dur);
			}

			slider.args[slider.prop] = target;
			if (slider.transitions || dur === undefined) { slider.container.css(slider.args); }

			slider.container.css('transform',target);
		};

		slider.setup = function(type) {
			// SLIDE:
			if (!fade) {
				var sliderOffset, arr;

				if (type === "init") {
					slider.viewport = $('<div class="' + namespace + 'viewport"></div>').css({"overflow": "hidden", "position": "relative"}).appendTo(slider).append(slider.container);
					// INFINITE LOOP:
					slider.cloneCount = 0;
					slider.cloneOffset = 0;
					// REVERSE:
					if (reverse) {
						arr = $.makeArray(slider.slides).reverse();
						slider.slides = $(arr);
						slider.container.empty().append(slider.slides);
					}
				}
				// INFINITE LOOP && !CAROUSEL:
				if (slider.vars.animationLoop && !carousel) {
					slider.cloneCount = 2;
					slider.cloneOffset = 1;
					// clear out old clones
					if (type !== "init") { slider.container.find('.clone').remove(); }
					slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true'))
						.prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true'));
				}
				slider.newSlides = $(slider.vars.selector, slider);

				sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;
				// VERTICAL:
				if (vertical && !carousel) {
					slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%");
					setTimeout(function(){
						slider.newSlides.css({"display": "block"});
						slider.doMath();
						slider.viewport.height(slider.h);
						slider.setProps(sliderOffset * slider.h, "init");
					}, (type === "init") ? 100 : 0);
				} else {
					slider.container.width((slider.count + slider.cloneCount) * 200 + "%");
					slider.setProps(sliderOffset * slider.computedW, "init");
					setTimeout(function(){
						slider.doMath();
						if(slider.vars.rtl){
							slider.newSlides.css({"width": slider.computedW, "marginRight" : slider.computedM, "float": "left", "display": "block"});
						}
						else{
							slider.newSlides.css({"width": slider.computedW, "marginRight" : slider.computedM, "float": "left", "display": "block"});
						}
						// SMOOTH HEIGHT:
						if (slider.vars.smoothHeight) { methods.smoothHeight(); }
					}, (type === "init") ? 100 : 0);
				}
			} else { // FADE:
				if(slider.vars.rtl){
					slider.slides.css({"width": "100%", "float": 'right', "marginLeft": "-100%", "position": "relative"});
				}
				else{
					slider.slides.css({"width": "100%", "float": 'left', "marginRight": "-100%", "position": "relative"});
				}
				if (type === "init") {
					if (!touch) {
						//slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing);
						if (slider.vars.fadeFirstSlide == false) {
							slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).css({"opacity": 1});
						} else {
							slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).animate({"opacity": 1},slider.vars.animationSpeed,slider.vars.easing);
						}
					} else {
						slider.slides.css({ "opacity": 0, "display": "block", "webkitTransition": "opacity " + slider.vars.animationSpeed / 1000 + "s ease", "zIndex": 1 }).eq(slider.currentSlide).css({ "opacity": 1, "zIndex": 2});
					}
				}
				// SMOOTH HEIGHT:
				if (slider.vars.smoothHeight) { methods.smoothHeight(); }
			}
			// !CAROUSEL:
			// CANDIDATE: active slide
			if (!carousel) { slider.slides.removeClass(namespace + "active-slide").eq(slider.currentSlide).addClass(namespace + "active-slide"); }

			//FlexSlider: init() Callback
			slider.vars.init(slider);
		};

		slider.doMath = function() {
			var slide = slider.slides.first(),
				slideMargin = slider.vars.itemMargin,
				minItems = slider.vars.minItems,
				maxItems = slider.vars.maxItems;

			slider.w = (slider.viewport===undefined) ? slider.width() : slider.viewport.width();
			slider.h = slide.height();
			slider.boxPadding = slide.outerWidth() - slide.width();

			// CAROUSEL:
			if (carousel) {
				slider.itemT = slider.vars.itemWidth + slideMargin;
				slider.itemM = slideMargin;
				slider.minW = (minItems) ? minItems * slider.itemT : slider.w;
				slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w;
				slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1)))/minItems :
					(slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1)))/maxItems :
						(slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth;

				slider.visible = Math.floor(slider.w/(slider.itemW));
				slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible ) ? slider.vars.move : slider.visible;
				slider.pagingCount = Math.ceil(((slider.count - slider.visible)/slider.move) + 1);
				slider.last =  slider.pagingCount - 1;
				slider.limit = (slider.pagingCount === 1) ? 0 :
					(slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;
			} else {
				slider.itemW = slider.w;
				slider.itemM = slideMargin;
				slider.pagingCount = slider.count;
				slider.last = slider.count - 1;
			}
			slider.computedW = slider.itemW - slider.boxPadding;
			slider.computedM = slider.itemM;
		};

		slider.update = function(pos, action) {
			slider.doMath();

			// update currentSlide and slider.animatingTo if necessary
			if (!carousel) {
				if (pos < slider.currentSlide) {
					slider.currentSlide += 1;
				} else if (pos <= slider.currentSlide && pos !== 0) {
					slider.currentSlide -= 1;
				}
				slider.animatingTo = slider.currentSlide;
			}

			// update controlNav
			if (slider.vars.controlNav && !slider.manualControls) {
				if ((action === "add" && !carousel) || slider.pagingCount > slider.controlNav.length) {
					methods.controlNav.update("add");
				} else if ((action === "remove" && !carousel) || slider.pagingCount < slider.controlNav.length) {
					if (carousel && slider.currentSlide > slider.last) {
						slider.currentSlide -= 1;
						slider.animatingTo -= 1;
					}
					methods.controlNav.update("remove", slider.last);
				}
			}
			// update directionNav
			if (slider.vars.directionNav) { methods.directionNav.update(); }

		};

		slider.addSlide = function(obj, pos) {
			var $obj = $(obj);

			slider.count += 1;
			slider.last = slider.count - 1;

			// append new slide
			if (vertical && reverse) {
				(pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);
			} else {
				(pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);
			}

			// update currentSlide, animatingTo, controlNav, and directionNav
			slider.update(pos, "add");

			// update slider.slides
			slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
			// re-setup the slider to accomdate new slide
			slider.setup();

			//FlexSlider: added() Callback
			slider.vars.added(slider);
		};
		slider.removeSlide = function(obj) {
			var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;

			// update count
			slider.count -= 1;
			slider.last = slider.count - 1;

			// remove slide
			if (isNaN(obj)) {
				$(obj, slider.slides).remove();
			} else {
				(vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();
			}

			// update currentSlide, animatingTo, controlNav, and directionNav
			slider.doMath();
			slider.update(pos, "remove");

			// update slider.slides
			slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
			// re-setup the slider to accomdate new slide
			slider.setup();

			// FlexSlider: removed() Callback
			slider.vars.removed(slider);
		};

		//FlexSlider: Initialize
		methods.init();
	};

	// Ensure the slider isn't focussed if the window loses focus.
	$( window ).blur( function ( e ) {
		focused = false;
	}).focus( function ( e ) {
		focused = true;
	});

	//FlexSlider: Default Settings
	$.flexslider.defaults = {
		namespace: "flex-",             //{NEW} String: Prefix string attached to the class of every element generated by the plugin
		selector: ".slides > li",       //{NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril
		animation: "fade",              //String: Select your animation type, "fade" or "slide"
		easing: "swing",                //{NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!
		direction: "horizontal",        //String: Select the sliding direction, "horizontal" or "vertical"
		reverse: false,                 //{NEW} Boolean: Reverse the animation direction
		animationLoop: true,            //Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end
		smoothHeight: false,            //{NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode
		startAt: 0,                     //Integer: The slide that the slider should start on. Array notation (0 = first slide)
		slideshow: true,                //Boolean: Animate slider automatically
		slideshowSpeed: 7000,           //Integer: Set the speed of the slideshow cycling, in milliseconds
		animationSpeed: 600,            //Integer: Set the speed of animations, in milliseconds
		initDelay: 0,                   //{NEW} Integer: Set an initialization delay, in milliseconds
		randomize: false,               //Boolean: Randomize slide order
		fadeFirstSlide: true,           //Boolean: Fade in the first slide when animation type is "fade"
		thumbCaptions: false,           //Boolean: Whether or not to put captions on thumbnails when using the "thumbnails" controlNav.

		// Usability features
		pauseOnAction: true,            //Boolean: Pause the slideshow when interacting with control elements, highly recommended.
		pauseOnHover: false,            //Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering
		pauseInvisible: true,   		//{NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage.
		useCSS: true,                   //{NEW} Boolean: Slider will use CSS3 transitions if available
		touch: true,                    //{NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices
		video: false,                   //{NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches

		// Primary Controls
		controlNav: true,               //Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage
		directionNav: true,             //Boolean: Create navigation for previous/next navigation? (true/false)
		prevText: "Previous",           //String: Set the text for the "previous" directionNav item
		nextText: "Next",               //String: Set the text for the "next" directionNav item

		// Secondary Navigation
		keyboard: true,                 //Boolean: Allow slider navigating via keyboard left/right keys
		multipleKeyboard: false,        //{NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.
		mousewheel: false,              //{UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel
		pausePlay: false,               //Boolean: Create pause/play dynamic element
		pauseText: "Pause",             //String: Set the text for the "pause" pausePlay item
		playText: "Play",               //String: Set the text for the "play" pausePlay item

		// Special properties
		controlsContainer: "",          //{UPDATED} jQuery Object/Selector: Declare which container the navigation elements should be appended too. Default container is the FlexSlider element. Example use would be $(".flexslider-container"). Property is ignored if given element is not found.
		manualControls: "",             //{UPDATED} jQuery Object/Selector: Declare custom control navigation. Examples would be $(".flex-control-nav li") or "#tabs-nav li img", etc. The number of elements in your controlNav should match the number of slides/tabs.
		customDirectionNav: "",         //{NEW} jQuery Object/Selector: Custom prev / next button. Must be two jQuery elements. In order to make the events work they have to have the classes "prev" and "next" (plus namespace)
		sync: "",                       //{NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.
		asNavFor: "",                   //{NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider

		// Carousel Options
		itemWidth: 0,                   //{NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.
		itemMargin: 0,                  //{NEW} Integer: Margin between carousel items.
		minItems: 1,                    //{NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.
		maxItems: 0,                    //{NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.
		move: 0,                        //{NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.
		allowOneSlide: true,           //{NEW} Boolean: Whether or not to allow a slider comprised of a single slide

		// Callback API
		start: function(){},            //Callback: function(slider) - Fires when the slider loads the first slide
		before: function(){},           //Callback: function(slider) - Fires asynchronously with each slider animation
		after: function(){},            //Callback: function(slider) - Fires after each slider animation completes
		end: function(){},              //Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)
		added: function(){},            //{NEW} Callback: function(slider) - Fires after a slide is added
		removed: function(){},           //{NEW} Callback: function(slider) - Fires after a slide is removed
		init: function() {},             //{NEW} Callback: function(slider) - Fires after the slider is initially setup
		rtl: false             //{NEW} Boolean: Whether or not to enable RTL mode
	};

	//FlexSlider: Plugin Function
	$.fn.flexslider = function(options) {
		if (options === undefined) { options = {}; }

		if (typeof options === "object") {
			return this.each(function() {
				var $this = $(this),
					selector = (options.selector) ? options.selector : ".slides > li",
					$slides = $this.find(selector);

				if ( ( $slides.length === 1 && options.allowOneSlide === false ) || $slides.length === 0 ) {
					$slides.fadeIn(400);
					if (options.start) { options.start($this); }
				} else if ($this.data('flexslider') === undefined) {
					new $.flexslider(this, options);
				}
			});
		} else {
			// Helper strings to quickly perform functions on the slider
			var $slider = $(this).data('flexslider');
			switch (options) {
				case "play": $slider.play(); break;
				case "pause": $slider.pause(); break;
				case "stop": $slider.stop(); break;
				case "next": $slider.flexAnimate($slider.getTarget("next"), true); break;
				case "prev":
				case "previous": $slider.flexAnimate($slider.getTarget("prev"), true); break;
				default: if (typeof options === "number") { $slider.flexAnimate(options, true); }
			}
		}
	};
})(jQuery);

/*! iScroll v5.0.4 ~ (c) 2008-2013 Matteo Spinelli ~ http://cubiq.org/license */

// IMPORTANT!!! This has been patched as per https://github.com/cubiq/iscroll/pull/436
// Ideally update to use separate IE8 patch once released

var IScroll = (function (window, document, Math) {

	// Obligatory browser/device sniff hack
	var nua = navigator.userAgent;
	var is_android = ((nua.indexOf('Mozilla/5.0') > -1 && nua.indexOf('Android ') > -1 && nua.indexOf('AppleWebKit') > -1) && !(nua.indexOf('Chrome') > -1));
	if (is_android) {
		document.getElementsByTagName('body')[0].className+=' is-android-browser'; // Add body class helper
	}

	var rAF = window.requestAnimationFrame	||
		window.webkitRequestAnimationFrame	||
		window.mozRequestAnimationFrame		||
		window.oRequestAnimationFrame		||
		window.msRequestAnimationFrame		||
		function (callback) { window.setTimeout(callback, 1000 / 60); };

	var utils = (function () {
		var me = {};

		var _elementStyle = document.createElement('div').style;
		var _vendor = (function () {
			var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
				transform,
				i = 0,
				l = vendors.length;

			for ( ; i < l; i++ ) {
				transform = vendors[i] + 'ransform';
				if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
			}

			return false;
		})();

		function _prefixStyle (style) {
			if ( _vendor === false ) return false;
			if ( _vendor === '' ) return style;
			return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
		}

		me.getTime = Date.now || function getTime () { return new Date().getTime(); };

		me.extend = function (target, obj) {
			for ( var i in obj ) {
				target[i] = obj[i];
			}
		};

		me.extendEvent = function(e, _this) {
			if (!e.currentTarget) e.currentTarget = _this;
			if (!e.target) e.target = e.srcElement;

			if (!e.relatedTarget) {
				if (e.type == 'mouseover') e.relatedTarget = e.fromElement;
				if (e.type == 'mouseout') e.relatedTarget = e.toElement;
			}

			if (e.pageX == null && e.clientX != null ) {
				var html = document.documentElement;
				var body = document.body;

				e.pageX = e.clientX + (html.scrollLeft || body && body.scrollLeft || 0);
				e.pageX -= html.clientLeft || 0;

				e.pageY = e.clientY + (html.scrollTop || body && body.scrollTop || 0);
				e.pageY -= html.clientTop || 0;
			}
			if (!e.which && e.button) {
				if (e.button == 1) {
					e.button2 = 0;
				} else if (e.button == 4) {
					e.button2 = 1;
				} else if (e.button == 2) {
					e.button2 = 2;
				} else {
					e.button2 = 0;
				}
				e.which = e.button & 1 ? 1 : ( e.button & 2 ? 3 : (e.button & 4 ? 2 : 0) );
			}
			return e;
		};

		// fn arg can be an object or a function, thanks to handleEvent
		me.addEvent = function(el, type, fn, capture) {
			if("addEventListener" in el) {
				// BBOS6 doesn't support handleEvent, catch and polyfill
				try {
					el.addEventListener(type, fn, !!capture);
				} catch(e) {
					if(typeof fn == "object" && fn.handleEvent) {
						el.addEventListener(type, function(e){
							// Bind fn as this and set first arg as event object
							fn.handleEvent.call(fn,e);
						}, !!capture);
					} else {
						throw e;
					}
				}
			} else if("attachEvent" in el) {
				// check if the callback is an object and contains handleEvent
				if (el == window) el = document;
				if(typeof fn == "object" && fn.handleEvent) {
					el.attachEvent("on" + type, function(e){
						// Bind fn as this
						e = me.extendEvent(e, el);
						fn.handleEvent.call(fn, e);
					});
				} else {
					el.attachEvent("on" + type, fn);
				}
			}
		};

		me.removeEvent = function (el, type, fn, capture) {
			el.removeEventListener(type, fn, !!capture);

			if (typeof el.addEventListener != undefined) {
				el.removeEventListener(type, fn, !!capture);
			}
			else if (typeof el.attachEvent != undefined) {
				el.detachEvent("on" + type, el[type + fn]);
				el[type + fn] = null;
				el["e" + type + fn] = null;
			}

		};

		me.momentum = function (current, start, time, lowerMargin, wrapperSize) {
			var distance = current - start,
				speed = Math.abs(distance) / time,
				destination,
				duration,
				deceleration = 0.0006;

			destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
			duration = speed / deceleration;

			if ( destination < lowerMargin ) {
				destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
				distance = Math.abs(destination - current);
				duration = distance / speed;
			} else if ( destination > 0 ) {
				destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
				distance = Math.abs(current) + destination;
				duration = distance / speed;
			}

			return {
				destination: Math.round(destination),
				duration: duration
			};
		};

		var _transform = _prefixStyle('transform');

		me.extend(me, {
			hasTransform: _transform !== false,
			hasPerspective: _prefixStyle('perspective') in _elementStyle,
			hasTouch: 'ontouchstart' in window,
			hasPointer: navigator.msPointerEnabled,
			hasTransition: _prefixStyle('transition') in _elementStyle
		});

		me.isAndroidBrowser = /Android/.test(window.navigator.appVersion) && /Version\/\d/.test(window.navigator.appVersion);

		me.extend(me.style = {}, {
			transform: _transform,
			transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
			transitionDuration: _prefixStyle('transitionDuration'),
			transformOrigin: _prefixStyle('transformOrigin')
		});

		me.hasClass = function (e, c) {
			var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
			return re.test(e.className);
		};

		me.addClass = function (e, c) {
			if ( me.hasClass(e, c) ) {
				return;
			}

			var newclass = e.className.split(' ');
			newclass.push(c);
			e.className = newclass.join(' ');
		};

		me.removeClass = function (e, c) {
			if ( !me.hasClass(e, c) ) {
				return;
			}

			var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
			e.className = e.className.replace(re, '');
		};

		me.offset = function (el) {
			var left = -el.offsetLeft,
				top = -el.offsetTop;

			// jshint -W084
			while (el = el.offsetParent) {
				left -= el.offsetLeft;
				top -= el.offsetTop;
			}
			// jshint +W084

			return {
				left: left,
				top: top
			};
		};

		me.extend(me.eventType = {}, {
			touchstart: 1,
			touchmove: 1,
			touchend: 1,

			mousedown: 2,
			mousemove: 2,
			mouseup: 2,

			MSPointerDown: 3,
			MSPointerMove: 3,
			MSPointerUp: 3
		});

		me.extend(me.ease = {}, {
			quadratic: {
				style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
				fn: function (k) {
					return k * ( 2 - k );
				}
			},
			circular: {
				style: 'cubic-bezier(0.1, 0.57, 0.1, 1)',	// Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
				fn: function (k) {
					return Math.sqrt( 1 - ( --k * k ) );
				}
			},
			back: {
				style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
				fn: function (k) {
					var b = 4;
					return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
				}
			},
			bounce: {
				style: '',
				fn: function (k) {
					if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
						return 7.5625 * k * k;
					} else if ( k < ( 2 / 2.75 ) ) {
						return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
					} else if ( k < ( 2.5 / 2.75 ) ) {
						return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
					} else {
						return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
					}
				}
			},
			elastic: {
				style: '',
				fn: function (k) {
					var f = 0.22,
						e = 0.4;

					if ( k === 0 ) { return 0; }
					if ( k == 1 ) { return 1; }

					return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
				}
			}
		});

		me.tap = function (e, eventName) {
			var ev = document.createEvent('Event');
			ev.initEvent(eventName, true, true);
			ev.pageX = e.pageX;
			ev.pageY = e.pageY;
			e.target.dispatchEvent(ev);
		};

		me.click = function (e) {
			var target = e.target,
				ev;

			if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
				ev = document.createEvent('MouseEvents');
				ev.initMouseEvent('click', true, true, e.view, 1,
					target.screenX, target.screenY, target.clientX, target.clientY,
					e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
					0, null);

				ev._constructed = true;
				target.dispatchEvent(ev);
			}
		};

		return me;
	})();

	function IScroll (el, options) {
		this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
		this.scroller = this.wrapper.children[0];
		this.scrollerStyle = this.scroller.style;		// cache style for better performance

		this.options = {

			resizeIndicator: true,

			mouseWheelSpeed: 20,

			snapThreshold: 0.334,

// INSERT POINT: OPTIONS

			startX: 0,
			startY: 0,
			scrollY: true,
			directionLockThreshold: 5,
			momentum: true,

			bounce: true,
			bounceTime: 600,
			bounceEasing: '',

			preventDefault: true,

			HWCompositing: true,
			useTransition: true,
			useTransform: true
		};

		for ( var i in options ) {
			this.options[i] = options[i];
		}

		// Normalize options
		this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';

		this.options.useTransition = utils.hasTransition && this.options.useTransition;
		this.options.useTransform = utils.hasTransform && this.options.useTransform;

		this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
		this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;

		// If you want eventPassthrough I have to lock one of the axes
		this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
		this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;

		// With eventPassthrough we also need lockDirection mechanism
		this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
		this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;

		this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;

		this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;

		if ( this.options.tap === true ) {
			this.options.tap = 'tap';
		}

		this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;

// INSERT POINT: NORMALIZATION

		// Some defaults
		this.x = 0;
		this.y = 0;
		this.directionX = 0;
		this.directionY = 0;
		this._events = {};

// INSERT POINT: DEFAULTS

		this._init();
		this.refresh();

		this.scrollTo(this.options.startX, this.options.startY);
		this.enable();
	}

	IScroll.prototype = {
		version: '5.0.4',

		_init: function () {
			this._initEvents();

			if ( this.options.scrollbars || this.options.indicators ) {
				this._initIndicators();
			}

			if ( this.options.mouseWheel ) {
				this._initWheel();
			}

			if ( this.options.snap ) {
				this._initSnap();
			}

			if ( this.options.keyBindings ) {
				this._initKeys();
			}

// INSERT POINT: _init

		},

		destroy: function () {
			this._initEvents(true);

			this._execEvent('destroy');
		},

		_transitionEnd: function (e) {
			if ( e.target != this.scroller ) {
				return;
			}

			this._transitionTime(0);
			if ( !this.resetPosition(this.options.bounceTime) ) {
				this._execEvent('scrollEnd');
			}
		},

		_start: function (e) {
			// React to left mouse button only
			var _button = e.button2 != undefined ? e.button2 : e.button;
			if ( utils.eventType[e.type] != 1 ) {
				if ( _button !== 0 ) {
					return;
				}
			}
			if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
				return;
			}

			if ( this.options.preventDefault && !utils.isAndroidBrowser ) {
				(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
			}

			var point = e.touches ? e.touches[0] : e,
				pos;

			this.initiated	= utils.eventType[e.type];
			this.moved		= false;
			this.distX		= 0;
			this.distY		= 0;
			this.directionX = 0;
			this.directionY = 0;
			this.directionLocked = 0;

			this._transitionTime();

			this.isAnimating = false;
			this.startTime = utils.getTime();

			if ( this.options.useTransition && this.isInTransition ) {
				pos = this.getComputedPosition();

				if (is_android) { this._transitionTime(0.001); } // Scroll fix hack for Android
				this._translate(Math.round(pos.x), Math.round(pos.y));
				this.isInTransition = false;
			}

			this.startX    = this.x;
			this.startY    = this.y;
			this.absStartX = this.x;
			this.absStartY = this.y;
			this.pointX    = point.pageX;
			this.pointY    = point.pageY;

			this._execEvent('scrollStart');
		},

		_move: function (e) {
			if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
				return;
			}

			if ( this.options.preventDefault ) {	// increases performance on Android? TODO: check!
				(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
			}

			var point		= e.touches ? e.touches[0] : e,
				deltaX		= this.hasHorizontalScroll ? point.pageX - this.pointX : 0,
				deltaY		= this.hasVerticalScroll   ? point.pageY - this.pointY : 0,
				timestamp	= utils.getTime(),
				newX, newY,
				absDistX, absDistY;

			this.pointX		= point.pageX;
			this.pointY		= point.pageY;

			this.distX		+= deltaX;
			this.distY		+= deltaY;
			absDistX		= Math.abs(this.distX);
			absDistY		= Math.abs(this.distY);

			// We need to move at least 10 pixels for the scrolling to initiate
			if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
				return;
			}

			// If you are scrolling in one direction lock the other
			if ( !this.directionLocked && !this.options.freeScroll ) {
				if ( absDistX > absDistY + this.options.directionLockThreshold ) {
					this.directionLocked = 'h';		// lock horizontally
				} else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
					this.directionLocked = 'v';		// lock vertically
				} else {
					this.directionLocked = 'n';		// no lock
				}
			}

			if ( this.directionLocked == 'h' ) {
				if ( this.options.eventPassthrough == 'vertical' ) {
					(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
				} else if ( this.options.eventPassthrough == 'horizontal' ) {
					this.initiated = false;
					return;
				}

				deltaY = 0;
			} else if ( this.directionLocked == 'v' ) {
				if ( this.options.eventPassthrough == 'horizontal' ) {
					(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
				} else if ( this.options.eventPassthrough == 'vertical' ) {
					this.initiated = false;
					return;
				}

				deltaX = 0;
			}

			newX = this.x + deltaX;
			newY = this.y + deltaY;

			// Slow down if outside of the boundaries
			if ( newX > 0 || newX < this.maxScrollX ) {
				newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
			}
			if ( newY > 0 || newY < this.maxScrollY ) {
				newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
			}

			this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
			this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;

			this.moved = true;

			this._translate(newX, newY);

			/* REPLACE START: _move */

			if ( timestamp - this.startTime > 300 ) {
				this.startTime = timestamp;
				this.startX = this.x;
				this.startY = this.y;
			}

			/* REPLACE END: _move */

		},

		_end: function (e) {
			if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
				return;
			}

			if ( this.options.preventDefault ) {
				(e.preventDefault) ? e.preventDefault() : e.returnValue = false;		// TODO: check if needed
			}

			var point = e.changedTouches ? e.changedTouches[0] : e,
				momentumX,
				momentumY,
				duration = utils.getTime() - this.startTime,
				newX = Math.round(this.x),
				newY = Math.round(this.y),
				distanceX = Math.abs(newX - this.startX),
				distanceY = Math.abs(newY - this.startY),
				time = 0,
				easing = '';

			this.scrollTo(newX, newY);	// ensures that the last position is rounded

			this.isInTransition = 0;
			this.initiated = 0;
			this.endTime = utils.getTime();

			// reset if we are outside of the boundaries
			if ( this.resetPosition(this.options.bounceTime) ) {
				return;
			}

			// we scrolled less than 10 pixels
			if ( !this.moved ) {
				if ( this.options.tap ) {
					utils.tap(e, this.options.tap);
				}

				if ( this.options.click ) {
					utils.click(e);
				}

				return;
			}

			if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
				this._execEvent('flick');
				return;
			}

			// start momentum animation if needed
			if ( this.options.momentum && duration < 300 ) {
				momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0) : { destination: newX, duration: 0 };
				momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0) : { destination: newY, duration: 0 };
				newX = momentumX.destination;
				newY = momentumY.destination;
				time = Math.max(momentumX.duration, momentumY.duration);
				this.isInTransition = 1;
			}

			if ( this.options.snap ) {
				var snap = this._nearestSnap(newX, newY);
				this.currentPage = snap;
				newX = snap.x;
				newY = snap.y;
				time = this.options.snapSpeed || Math.max(
					Math.max(
						Math.min(distanceX, 1000),
						Math.min(distanceX, 1000)
					), 300);

				this.directionX = 0;
				this.directionY = 0;
				easing = this.options.bounceEasing;
			}

			if ( newX != this.x || newY != this.y ) {
				// change easing function when scroller goes out of the boundaries
				if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
					easing = utils.ease.quadratic;
				}

				this.scrollTo(newX, newY, time, easing);
				return;
			}

			this._execEvent('scrollEnd');
		},

		_resize: function () {
			var that = this;

			clearTimeout(this.resizeTimeout);

			this.resizeTimeout = setTimeout(function () {
				that.refresh();
			}, this.options.resizePolling);
		},

		resetPosition: function (time) {
			var x = this.x,
				y = this.y;

			time = time || 0;

			if ( !this.hasHorizontalScroll || this.x > 0 ) {
				x = 0;
			} else if ( this.x < this.maxScrollX ) {
				x = this.maxScrollX;
			}

			if ( !this.hasVerticalScroll || this.y > 0 ) {
				y = 0;
			} else if ( this.y < this.maxScrollY ) {
				y = this.maxScrollY;
			}

			if ( x == this.x && y == this.y ) {
				return false;
			}

			this.scrollTo(x, y, time, this.options.bounceEasing);

			return true;
		},

		disable: function () {
			this.enabled = false;
		},

		enable: function () {
			this.enabled = true;
		},

		refresh: function () {
			var rf = this.wrapper.offsetHeight;		// Force reflow

			this.wrapperWidth	= this.wrapper.clientWidth;
			this.wrapperHeight	= this.wrapper.clientHeight;

			/* REPLACE START: refresh */

			this.scrollerWidth	= this.scroller.offsetWidth;
			this.scrollerHeight	= this.scroller.offsetHeight;

			/* REPLACE END: refresh */

			this.maxScrollX		= this.wrapperWidth - this.scrollerWidth;
			this.maxScrollY		= this.wrapperHeight - this.scrollerHeight;

			this.hasHorizontalScroll	= this.options.scrollX && this.maxScrollX < 0;
			this.hasVerticalScroll		= this.options.scrollY && this.maxScrollY < 0;

			if ( !this.hasHorizontalScroll ) {
				this.maxScrollX = 0;
				this.scrollerWidth = this.wrapperWidth;
			}

			if ( !this.hasVerticalScroll ) {
				this.maxScrollY = 0;
				this.scrollerHeight = this.wrapperHeight;
			}

			this.endTime = 0;
			this.directionX = 0;
			this.directionY = 0;

			this.wrapperOffset = utils.offset(this.wrapper);

			this._execEvent('refresh');

			this.resetPosition();

			if ( this.options.snap ) {
				var snap = this._nearestSnap(this.x, this.y);
				if ( this.x == snap.x && this.y == snap.y ) {
					return;
				}

				this.currentPage = snap;
				this.scrollTo(snap.x, snap.y);
			}
		},

		on: function (type, fn) {
			if ( !this._events[type] ) {
				this._events[type] = [];
			}

			this._events[type].push(fn);
		},

		_execEvent: function (type) {
			if ( !this._events[type] ) {
				return;
			}

			var i = 0,
				l = this._events[type].length;

			if ( !l ) {
				return;
			}

			for ( ; i < l; i++ ) {
				this._events[type][i].call(this);
			}
		},

		scrollBy: function (x, y, time, easing) {
			x = this.x + x;
			y = this.y + y;
			time = time || 0;

			this.scrollTo(x, y, time, easing);
		},

		scrollTo: function (x, y, time, easing) {
			easing = easing || utils.ease.circular;

			if ( !time || (this.options.useTransition && easing.style) ) {
				this._transitionTimingFunction(easing.style);
				this._transitionTime(time);
				this._translate(x, y);
			} else {
				this._animate(x, y, time, easing.fn);
			}
		},

		scrollToElement: function (el, time, offsetX, offsetY, easing) {
			el = el.nodeType ? el : this.scroller.querySelector(el);

			if ( !el ) {
				return;
			}

			var pos = utils.offset(el);

			pos.left -= this.wrapperOffset.left;
			pos.top  -= this.wrapperOffset.top;

			// if offsetX/Y are true we center the element to the screen
			if ( offsetX === true ) {
				offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
			}
			if ( offsetY === true ) {
				offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
			}

			pos.left -= offsetX || 0;
			pos.top  -= offsetY || 0;

			pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
			pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;

			time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(pos.left)*2, Math.abs(pos.top)*2) : time;

			this.scrollTo(pos.left, pos.top, time, easing);
		},

		_transitionTime: function (time) {
			time = time || 0;
			this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';


			if ( this.indicator1 ) {
				this.indicator1.transitionTime(time);
			}

			if ( this.indicator2 ) {
				this.indicator2.transitionTime(time);
			}

// INSERT POINT: _transitionTime

		},

		_transitionTimingFunction: function (easing) {
			this.scrollerStyle[utils.style.transitionTimingFunction] = easing;


			if ( this.indicator1 ) {
				this.indicator1.transitionTimingFunction(easing);
			}

			if ( this.indicator2 ) {
				this.indicator2.transitionTimingFunction(easing);
			}


// INSERT POINT: _transitionTimingFunction

		},

		_translate: function (x, y) {
			if ( this.options.useTransform ) {

				/* REPLACE START: _translate */

				this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;

				/* REPLACE END: _translate */

			} else {
				x = Math.round(x);
				y = Math.round(y);
				this.scrollerStyle.left = x + 'px';
				this.scrollerStyle.top = y + 'px';
			}

			this.x = x;
			this.y = y;


			if ( this.indicator1 ) {	// usually the vertical
				this.indicator1.updatePosition();
			}

			if ( this.indicator2 ) {
				this.indicator2.updatePosition();
			}

// INSERT POINT: _translate

		},

		_initEvents: function (remove) {
			var eventType = remove ? utils.removeEvent : utils.addEvent,
				target = this.options.bindToWrapper ? this.wrapper : window;

			eventType(window, 'orientationchange', this);
			eventType(window, 'resize', this);

			eventType(this.wrapper, 'mousedown', this);
			eventType(target, 'mousemove', this);
			eventType(target, 'mousecancel', this);
			eventType(target, 'mouseup', this);

			if ( utils.hasPointer ) {
				eventType(this.wrapper, 'MSPointerDown', this);
				eventType(target, 'MSPointerMove', this);
				eventType(target, 'MSPointerCancel', this);
				eventType(target, 'MSPointerUp', this);
			}

			if ( utils.hasTouch ) {
				eventType(this.wrapper, 'touchstart', this);
				eventType(target, 'touchmove', this);
				eventType(target, 'touchcancel', this);
				eventType(target, 'touchend', this);
			}

			eventType(this.scroller, 'transitionend', this);
			eventType(this.scroller, 'webkitTransitionEnd', this);
			eventType(this.scroller, 'oTransitionEnd', this);
			eventType(this.scroller, 'MSTransitionEnd', this);
		},

		getComputedPosition: function () {
			var matrix = window.getComputedStyle(this.scroller, null),
				x, y;

			if ( this.options.useTransform ) {
				matrix = matrix[utils.style.transform].split(')')[0].split(', ');
				x = +(matrix[12] || matrix[4]);
				y = +(matrix[13] || matrix[5]);
			} else {
				x = +matrix.left.replace(/[^-\d]/g, '');
				y = +matrix.top.replace(/[^-\d]/g, '');
			}

			return { x: x, y: y };
		},

		_initIndicators: function () {
			var interactive = this.options.interactiveScrollbars,
				defaultScrollbars = typeof this.options.scrollbars != 'object',
				customStyle = typeof this.options.scrollbars != 'string',
				indicator1,
				indicator2;

			if ( this.options.scrollbars ) {
				// Vertical scrollbar
				if ( this.options.scrollY ) {
					indicator1 = {
						el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
						interactive: interactive,
						defaultScrollbars: true,
						customStyle: customStyle,
						resize: this.options.resizeIndicator,
						listenX: false
					};

					this.wrapper.appendChild(indicator1.el);
				}

				// Horizontal scrollbar
				if ( this.options.scrollX ) {
					indicator2 = {
						el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
						interactive: interactive,
						defaultScrollbars: true,
						customStyle: customStyle,
						resize: this.options.resizeIndicator,
						listenY: false
					};

					this.wrapper.appendChild(indicator2.el);
				}
			} else {
				indicator1 = this.options.indicators.length ? this.options.indicators[0] : this.options.indicators;
				indicator2 = this.options.indicators[1] && this.options.indicators[1];
			}

			if ( indicator1 ) {
				this.indicator1 = new Indicator(this, indicator1);
			}

			if ( indicator2 ) {
				this.indicator2 = new Indicator(this, indicator2);
			}

			this.on('refresh', function () {
				if ( this.indicator1 ) {
					this.indicator1.refresh();
				}

				if ( this.indicator2 ) {
					this.indicator2.refresh();
				}
			});

			this.on('destroy', function () {
				if ( this.indicator1 ) {
					this.indicator1.destroy();
					this.indicator1 = null;
				}

				if ( this.indicator2 ) {
					this.indicator2.destroy();
					this.indicator2 = null;
				}
			});
		},

		_initWheel: function () {
			utils.addEvent(this.wrapper, 'mousewheel', this);
			utils.addEvent(this.wrapper, 'DOMMouseScroll', this);

			this.on('destroy', function () {
				utils.removeEvent(this.wrapper, 'mousewheel', this);
				utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
			});
		},

		_wheel: function (e) {
			if ( !this.enabled ) {
				return;
			}

			var wheelDeltaX, wheelDeltaY,
				newX, newY,
				that = this;

			// Execute the scrollEnd event after 400ms the wheel stopped scrolling
			clearTimeout(this.wheelTimeout);
			this.wheelTimeout = setTimeout(function () {
				that._execEvent('scrollEnd');
			}, 400);

			(e.preventDefault) ? e.preventDefault() : e.returnValue = false;

			if ( 'wheelDeltaX' in e ) {
				wheelDeltaX = e.wheelDeltaX / 120;
				wheelDeltaY = e.wheelDeltaY / 120;
			} else if ( 'wheelDelta' in e ) {
				wheelDeltaX = wheelDeltaY = e.wheelDelta / 120;
			} else if ( 'detail' in e ) {
				wheelDeltaX = wheelDeltaY = -e.detail / 3;
			} else {
				return;
			}

			wheelDeltaX *= this.options.mouseWheelSpeed;
			wheelDeltaY *= this.options.mouseWheelSpeed;

			if ( !this.hasVerticalScroll ) {
				wheelDeltaX = wheelDeltaY;
			}

			newX = this.x + (this.hasHorizontalScroll ? wheelDeltaX * this.options.invertWheelDirection : 0);
			newY = this.y + (this.hasVerticalScroll ? wheelDeltaY * this.options.invertWheelDirection : 0);

			if ( newX > 0 ) {
				newX = 0;
			} else if ( newX < this.maxScrollX ) {
				newX = this.maxScrollX;
			}

			if ( newY > 0 ) {
				newY = 0;
			} else if ( newY < this.maxScrollY ) {
				newY = this.maxScrollY;
			}

			this.scrollTo(newX, newY, 0);

// INSERT POINT: _wheel
		},

		_initSnap: function () {
			this.currentPage = {};

			if ( typeof this.options.snap == 'string' ) {
				this.options.snap = this.scroller.querySelectorAll(this.options.snap);
			}

			this.on('refresh', function () {
				var i = 0, l,
					m = 0, n,
					cx, cy,
					x = 0, y,
					stepX = this.options.snapStepX || this.wrapperWidth,
					stepY = this.options.snapStepY || this.wrapperHeight,
					el;

				this.pages = [];

				if ( this.options.snap === true ) {
					cx = Math.round( stepX / 2 );
					cy = Math.round( stepY / 2 );

					while ( x > -this.scrollerWidth ) {
						this.pages[i] = [];
						l = 0;
						y = 0;

						while ( y > -this.scrollerHeight ) {
							this.pages[i][l] = {
								x: Math.max(x, this.maxScrollX),
								y: Math.max(y, this.maxScrollY),
								width: stepX,
								height: stepY,
								cx: x - cx,
								cy: y - cy
							};

							y -= stepY;
							l++;
						}

						x -= stepX;
						i++;
					}
				} else {
					el = this.options.snap;
					l = el.length;
					n = -1;

					for ( ; i < l; i++ ) {
						if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
							m = 0;
							n++;
						}

						if ( !this.pages[m] ) {
							this.pages[m] = [];
						}

						x = Math.max(-el[i].offsetLeft, this.maxScrollX);
						y = Math.max(-el[i].offsetTop, this.maxScrollY);
						cx = x - Math.round(el[i].offsetWidth / 2);
						cy = y - Math.round(el[i].offsetHeight / 2);

						this.pages[m][n] = {
							x: x,
							y: y,
							width: el[i].offsetWidth,
							height: el[i].offsetHeight,
							cx: cx,
							cy: cy
						};

						if ( x > this.maxScrollX ) {
							m++;
						}
					}
				}

				this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);

				// Update snap threshold if needed
				if ( this.options.snapThreshold % 1 === 0 ) {
					this.snapThresholdX = this.options.snapThreshold;
					this.snapThresholdY = this.options.snapThreshold;
				} else {
					this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
					this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
				}
			});

			this.on('flick', function () {
				var time = this.options.snapSpeed || Math.max(
						Math.max(
							Math.min(Math.abs(this.x - this.startX), 1000),
							Math.min(Math.abs(this.y - this.startY), 1000)
						), 300);

				this.goToPage(
					this.currentPage.pageX + this.directionX,
					this.currentPage.pageY + this.directionY,
					time
				);
			});
		},

		_nearestSnap: function (x, y) {
			var i = 0,
				l = this.pages.length,
				m = 0;

			// Check if we exceeded the snap threshold
			if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
				Math.abs(y - this.absStartY) < this.snapThresholdY ) {
				return this.currentPage;
			}

			if ( x > 0 ) {
				x = 0;
			} else if ( x < this.maxScrollX ) {
				x = this.maxScrollX;
			}

			if ( y > 0 ) {
				y = 0;
			} else if ( y < this.maxScrollY ) {
				y = this.maxScrollY;
			}

			for ( ; i < l; i++ ) {
				if ( x >= this.pages[i][0].cx ) {
					x = this.pages[i][0].x;
					break;
				}
			}

			l = this.pages[i].length;

			for ( ; m < l; m++ ) {
				if ( y >= this.pages[0][m].cy ) {
					y = this.pages[0][m].y;
					break;
				}
			}

			if ( i == this.currentPage.pageX ) {
				i += this.directionX;

				if ( i < 0 ) {
					i = 0;
				} else if ( i >= this.pages.length ) {
					i = this.pages.length - 1;
				}

				x = this.pages[i][0].x;
			}

			if ( m == this.currentPage.pageY ) {
				m += this.directionY;

				if ( m < 0 ) {
					m = 0;
				} else if ( m >= this.pages[0].length ) {
					m = this.pages[0].length - 1;
				}

				y = this.pages[0][m].y;
			}

			return {
				x: x,
				y: y,
				pageX: i,
				pageY: m
			};
		},

		goToPage: function (x, y, time, easing) {
			easing = easing || this.options.bounceEasing;

			if ( x >= this.pages.length ) {
				x = this.pages.length - 1;
			} else if ( x < 0 ) {
				x = 0;
			}

			if ( y >= this.pages[0].length ) {
				y = this.pages[0].length - 1;
			} else if ( y < 0 ) {
				y = 0;
			}

			var posX = this.pages[x][y].x,
				posY = this.pages[x][y].y;

			time = time === undefined ? this.options.snapSpeed || Math.max(
				Math.max(
					Math.min(Math.abs(posX - this.x), 1000),
					Math.min(Math.abs(posY - this.y), 1000)
				), 300) : time;

			this.currentPage = {
				x: posX,
				y: posY,
				pageX: x,
				pageY: y
			};

			this.scrollTo(posX, posY, time, easing);
		},

		next: function (time, easing) {
			var x = this.currentPage.pageX,
				y = this.currentPage.pageY;

			x++;

			if ( x >= this.pages.length && this.hasVerticalScroll ) {
				x = 0;
				y++;
			}

			this.goToPage(x, y, time, easing);
		},

		prev: function (time, easing) {
			var x = this.currentPage.pageX,
				y = this.currentPage.pageY;

			x--;

			if ( x < 0 && this.hasVerticalScroll ) {
				x = 0;
				y--;
			}

			this.goToPage(x, y, time, easing);
		},

		_initKeys: function (e) {
			// default key bindings
			var keys = {
				pageUp: 33,
				pageDown: 34,
				end: 35,
				home: 36,
				left: 37,
				up: 38,
				right: 39,
				down: 40
			};
			var i;

			// if you give me characters I give you keycode
			if ( typeof this.options.keyBindings == 'object' ) {
				for ( i in this.options.keyBindings ) {
					if ( typeof this.options.keyBindings[i] == 'string' ) {
						this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);
					}
				}
			} else {
				this.options.keyBindings = {};
			}

			for ( i in keys ) {
				this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
			}

			utils.addEvent(window, 'keydown', this);

			this.on('destroy', function () {
				utils.removeEvent(window, 'keydown', this);
			});
		},

		_key: function (e) {
			if ( !this.enabled ) {
				return;
			}

			var snap = this.options.snap,	// we are using this alot, better to cache it
				newX = snap ? this.currentPage.pageX : this.x,
				newY = snap ? this.currentPage.pageY : this.y,
				now = utils.getTime(),
				prevTime = this.keyTime || 0,
				acceleration = 0.250,
				pos;

			if ( this.options.useTransition && this.isInTransition ) {
				pos = this.getComputedPosition();

				if (is_android) { this._transitionTime(0.001); } // Scroll fix hack for Android
				this._translate(Math.round(pos.x), Math.round(pos.y));
				this.isInTransition = false;
			}

			this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;

			switch ( e.keyCode ) {
				case this.options.keyBindings.pageUp:
					if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
						newX += snap ? 1 : this.wrapperWidth;
					} else {
						newY += snap ? 1 : this.wrapperHeight;
					}
					break;
				case this.options.keyBindings.pageDown:
					if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
						newX -= snap ? 1 : this.wrapperWidth;
					} else {
						newY -= snap ? 1 : this.wrapperHeight;
					}
					break;
				case this.options.keyBindings.end:
					newX = snap ? this.pages.length-1 : this.maxScrollX;
					newY = snap ? this.pages[0].length-1 : this.maxScrollY;
					break;
				case this.options.keyBindings.home:
					newX = 0;
					newY = 0;
					break;
				case this.options.keyBindings.left:
					newX += snap ? -1 : 5 + this.keyAcceleration>>0;
					break;
				case this.options.keyBindings.up:
					newY += snap ? 1 : 5 + this.keyAcceleration>>0;
					break;
				case this.options.keyBindings.right:
					newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
					break;
				case this.options.keyBindings.down:
					newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
					break;
			}

			if ( snap ) {
				this.goToPage(newX, newY);
				return;
			}

			if ( newX > 0 ) {
				newX = 0;
				this.keyAcceleration = 0;
			} else if ( newX < this.maxScrollX ) {
				newX = this.maxScrollX;
				this.keyAcceleration = 0;
			}

			if ( newY > 0 ) {
				newY = 0;
				this.keyAcceleration = 0;
			} else if ( newY < this.maxScrollY ) {
				newY = this.maxScrollY;
				this.keyAcceleration = 0;
			}

			this.scrollTo(newX, newY, 0);

			this.keyTime = now;
		},

		_animate: function (destX, destY, duration, easingFn) {
			var that = this,
				startX = this.x,
				startY = this.y,
				startTime = utils.getTime(),
				destTime = startTime + duration;

			function step () {
				var now = utils.getTime(),
					newX, newY,
					easing;

				if ( now >= destTime ) {
					that.isAnimating = false;
					that._translate(destX, destY);

					if ( !that.resetPosition(that.options.bounceTime) ) {
						that._execEvent('scrollEnd');
					}

					return;
				}

				now = ( now - startTime ) / duration;
				easing = easingFn(now);
				newX = ( destX - startX ) * easing + startX;
				newY = ( destY - startY ) * easing + startY;
				that._translate(newX, newY);

				if ( that.isAnimating ) {
					rAF(step);
				}
			}

			this.isAnimating = true;
			step();
		},
		handleEvent: function (e) {
			switch ( e.type ) {
				case 'touchstart':
				case 'MSPointerDown':
				case 'mousedown':
					this._start(e);
					break;
				case 'touchmove':
				case 'MSPointerMove':
				case 'mousemove':
					this._move(e);
					break;
				case 'touchend':
				case 'MSPointerUp':
				case 'mouseup':
				case 'touchcancel':
				case 'MSPointerCancel':
				case 'mousecancel':
					this._end(e);
					break;
				case 'orientationchange':
				case 'resize':
					this._resize();
					break;
				case 'transitionend':
				case 'webkitTransitionEnd':
				case 'oTransitionEnd':
				case 'MSTransitionEnd':
					this._transitionEnd(e);
					break;
				case 'DOMMouseScroll':
				case 'mousewheel':
					this._wheel(e);
					break;
				case 'keydown':
					this._key(e);
					break;
			}
		}
	};
	function createDefaultScrollbar (direction, interactive, type) {
		var scrollbar = document.createElement('div'),
			indicator = document.createElement('div');

		if ( type === true ) {
			scrollbar.style.cssText = 'position:absolute;z-index:9999';
			indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';
		}

		indicator.className = 'iScrollIndicator';

		if ( direction == 'h' ) {
			if ( type === true ) {
				scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
				indicator.style.height = '100%';
			}
			scrollbar.className = 'iScrollHorizontalScrollbar';
		} else {
			if ( type === true ) {
				scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
				indicator.style.width = '100%';
			}
			scrollbar.className = 'iScrollVerticalScrollbar';
		}

		if ( !interactive ) {
			scrollbar.style.pointerEvents = 'none';
		}

		scrollbar.appendChild(indicator);

		return scrollbar;
	}

	function Indicator (scroller, options) {
		this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
		this.indicator = this.wrapper.children[0];
		this.indicatorStyle = this.indicator.style;
		this.scroller = scroller;

		this.options = {
			listenX: true,
			listenY: true,
			interactive: false,
			resize: true,
			defaultScrollbars: false,
			speedRatioX: 0,
			speedRatioY: 0
		};

		for ( var i in options ) {
			this.options[i] = options[i];
		}

		this.sizeRatioX = 1;
		this.sizeRatioY = 1;
		this.maxPosX = 0;
		this.maxPosY = 0;

		if ( this.options.interactive ) {
			utils.addEvent(this.indicator, 'touchstart', this);
			utils.addEvent(this.indicator, 'MSPointerDown', this);
			utils.addEvent(this.indicator, 'mousedown', this);

			utils.addEvent(window, 'touchend', this);
			utils.addEvent(window, 'MSPointerUp', this);
			utils.addEvent(window, 'mouseup', this);
		}
	}

	Indicator.prototype = {
		handleEvent: function (e) {
			switch ( e.type ) {
				case 'touchstart':
				case 'MSPointerDown':
				case 'mousedown':
					this._start(e);
					break;
				case 'touchmove':
				case 'MSPointerMove':
				case 'mousemove':
					this._move(e);
					break;
				case 'touchend':
				case 'MSPointerUp':
				case 'mouseup':
				case 'touchcancel':
				case 'MSPointerCancel':
				case 'mousecancel':
					this._end(e);
					break;
			}
		},

		destroy: function () {
			if ( this.options.interactive ) {
				utils.removeEvent(this.indicator, 'touchstart', this);
				utils.removeEvent(this.indicator, 'MSPointerDown', this);
				utils.removeEvent(this.indicator, 'mousedown', this);

				utils.removeEvent(window, 'touchmove', this);
				utils.removeEvent(window, 'MSPointerMove', this);
				utils.removeEvent(window, 'mousemove', this);

				utils.removeEvent(window, 'touchend', this);
				utils.removeEvent(window, 'MSPointerUp', this);
				utils.removeEvent(window, 'mouseup', this);
			}

			if ( this.options.defaultScrollbars ) {
				this.wrapper.parentNode.removeChild(this.wrapper);
			}
		},

		_start: function (e) {
			var point = e.touches ? e.touches[0] : e;

			(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
			e.stopPropagation();

			this.transitionTime(0);

			this.initiated = true;
			this.moved = false;
			this.lastPointX	= point.pageX;
			this.lastPointY	= point.pageY;

			this.startTime	= utils.getTime();

			utils.addEvent(window, 'touchmove', this);
			utils.addEvent(window, 'MSPointerMove', this);
			utils.addEvent(window, 'mousemove', this);

			this.scroller._execEvent('scrollStart');
		},

		_move: function (e) {
			var point = e.touches ? e.touches[0] : e,
				deltaX, deltaY,
				newX, newY,
				timestamp = utils.getTime();

			this.moved = true;

			deltaX = point.pageX - this.lastPointX;
			this.lastPointX = point.pageX;

			deltaY = point.pageY - this.lastPointY;
			this.lastPointY = point.pageY;

			newX = this.x + deltaX;
			newY = this.y + deltaY;

			this._pos(newX, newY);

			(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
			e.stopPropagation();
		},

		_end: function (e) {
			if ( !this.initiated ) {
				return;
			}

			this.initiated = false;

			(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
			e.stopPropagation();

			utils.removeEvent(window, 'touchmove', this);
			utils.removeEvent(window, 'MSPointerMove', this);
			utils.removeEvent(window, 'mousemove', this);

			if ( this.moved ) {
				this.scroller._execEvent('scrollEnd');
			}
		},

		transitionTime: function (time) {
			time = time || 0;
			this.indicatorStyle[utils.style.transitionDuration] = time + 'ms';
		},

		transitionTimingFunction: function (easing) {
			this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
		},

		refresh: function () {
			this.transitionTime(0);

			if ( this.options.listenX && !this.options.listenY ) {
				this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
			} else if ( this.options.listenY && !this.options.listenX ) {
				this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
			} else {
				this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
			}

			if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
				utils.addClass(this.wrapper, 'iScrollBothScrollbars');
				utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');

				if ( this.options.defaultScrollbars && this.options.customStyle ) {
					if ( this.options.listenX ) {
						this.wrapper.style.right = '8px';
					} else {
						this.wrapper.style.bottom = '8px';
					}
				}
			} else {
				utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
				utils.addClass(this.wrapper, 'iScrollLoneScrollbar');

				if ( this.options.defaultScrollbars && this.options.customStyle ) {
					if ( this.options.listenX ) {
						this.wrapper.style.right = '2px';
					} else {
						this.wrapper.style.bottom = '2px';
					}
				}
			}

			var r = this.wrapper.offsetHeight;	// force refresh

			if ( this.options.listenX ) {
				this.wrapperWidth = this.wrapper.clientWidth;
				if ( this.options.resize ) {
					this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / this.scroller.scrollerWidth), 8);
					this.indicatorStyle.width = this.indicatorWidth + 'px';
				} else {
					this.indicatorWidth = this.indicator.clientWidth;
				}
				this.maxPosX = this.wrapperWidth - this.indicatorWidth;
				this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
			}

			if ( this.options.listenY ) {
				this.wrapperHeight = this.wrapper.clientHeight;
				if ( this.options.resize ) {
					this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / this.scroller.scrollerHeight), 8);
					this.indicatorStyle.height = this.indicatorHeight + 'px';
				} else {
					this.indicatorHeight = this.indicator.clientHeight;
				}

				this.maxPosY = this.wrapperHeight - this.indicatorHeight;
				this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
			}

			this.updatePosition();
		},

		updatePosition: function () {
			var x = Math.round(this.sizeRatioX * this.scroller.x) || 0,
				y = Math.round(this.sizeRatioY * this.scroller.y) || 0;

			if ( !this.options.ignoreBoundaries ) {
				if ( x < 0 ) {
					x = 0;
				} else if ( x > this.maxPosX ) {
					x = this.maxPosX;
				}

				if ( y < 0 ) {
					y = 0;
				} else if ( y > this.maxPosY ) {
					y = this.maxPosY;
				}
			}

			this.x = x;
			this.y = y;

			if ( this.scroller.options.useTransform ) {
				this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
			} else {
				this.indicatorStyle.left = x + 'px';
				this.indicatorStyle.top = y + 'px';
			}
		},

		_pos: function (x, y) {
			if ( x < 0 ) {
				x = 0;
			} else if ( x > this.maxPosX ) {
				x = this.maxPosX;
			}

			if ( y < 0 ) {
				y = 0;
			} else if ( y > this.maxPosY ) {
				y = this.maxPosY;
			}

			x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
			y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;

			this.scroller.scrollTo(x, y);
		}
	};

	IScroll.ease = utils.ease;

	return IScroll;

})(window, document, Math);

;
(function ($, window, document, undefined) {
	var pluginName = "bbRadioCheck",
		defaults = {
			propertyName: "value"
		};

	function Plugin(element, options) {
		this.element = element;
		this.options = $.extend({}, defaults, options);
		this._defaults = defaults;
		this._name = pluginName;
		this.init();
	}

	Plugin.prototype = {

		init: function () {
			if (!$(this.element).data('init')) {
				$(this.element)
					.on('click', '.radioBtnElement:not(".disable") div.skinnedRadio, .checkboxElement:not(".disable") div.skinnedCheckbox', $.proxy(this._onClick, this))
					.on('change updateSkin', '.radioBtnElement:not(".disable") div.skinnedRadio input, .checkboxElement:not(".disable") div.skinnedCheckbox input', $.proxy(this._onChange, this));

				$(this.element).find(':checked').parent('div.skinnedRadio, div.skinnedCheckbox' ).addClass('checked');
				$(this.element).data('init', true);
			}
		},

		_onClick: function (e) {
			var eTarget = $(e.target),
				skin =  $(e.currentTarget),
				inp = skin.find('input'),
				isDisabled = inp.is(':disabled'),
				isInput = eTarget.is('input'),
				isChecked = inp.is(':checked'),
				isRadioBtn = inp.is(':radio');

			inp.focus();

			if (!isDisabled && !isInput) {
				if (!isChecked) {
					inp.prop('checked', true);
				} else if (!isRadioBtn) {
					inp.prop('checked', false);
				}

				inp.trigger('change',[{ customEvent: true }]);
			}
		},

		_onChange: function (e) {
			var input = $(e.currentTarget),
				group;

			if (input.is(':checkbox')) {
				input.parent().toggleClass('checked');
			} else  if (input.is(':radio')) {
				group = input.closest('.radioGroup').find('input[type="radio"][name="' + input[0].name + '"]');
				group.parent().removeClass('checked disabled');
				group.filter(':checked').parent().addClass('checked');
				group.filter(':disabled').parent().addClass('disabled');
			}
		}
	};

	$.fn[pluginName] = function (options) {
		return this.each(function () {
			if (!$.data(this, "plugin_" + pluginName)) {
				$.data(this, "plugin_" + pluginName,
					new Plugin(this, options));
			}
		});
	};

})(jQuery, window, document);
/**
 * jQuery Extended Cookie Plugin
 *
 * Author: Frederick Giasson
 *
 * Copyright (c) 2012 Structured Dynamics LLC
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

jQuery.cookie = function (key, value, options) {

	// Check if localStorage of HTML5 exists in this browser
	var isStorageAvailable = false;
	if ("localStorage" in window)
	{
		try {
			window.localStorage.setItem("isStorageAvailable", "true");
			isStorageAvailable = true;
			window.localStorage.removeItem("isStorageAvailable", "true");
		} catch (PrivateBrowsingError) {
			// iOS Private Browsing mode will throw a "QUOTA_EXCEEDED_ERRROR DOM Exception 22" error
		}
	}

	// Check if the user wants to create or delete a cookie.
	if (arguments.length > 1 && String(value) !== "[object Object]")
	{
		options = jQuery.extend({}, options);

		// Set the default value of the maxChunkSize option if it is not yet defined.
		if(options.maxChunkSize == undefined)
		{
			options.maxChunkSize = 3000;
		}

		// Set the default value of the maxNumberOfCookies option if it is not yet defined.
		if(options.maxNumberOfCookies == undefined)
		{
			options.maxNumberOfCookies = 20;
		}

		// Set the usage of the local storage to true by default
		if(options.useLocalStorage == undefined)
		{
			options.useLocalStorage = true;
		}

		// Check if the user tries to delete the cookie
		if(value === null || value === undefined)
		{
			// If the localStorage is available, and if the user requested its usage, then we first
			// try to delete it from that place
			if(options.useLocalStorage && isStorageAvailable != false)
			{
				localStorage.removeItem(key);
			}

			// Even if the localStora was used, we try to remove some possible old cookies
			// Delete all possible chunks for that cookie
			for(var i = 0; i < options.maxNumberOfCookies; i++)
			{
				if(i == 0)
				{
					// The first chunk doesn't have the chunk indicator "---"
					var exists = $.chunkedcookie(key);
				}
				else
				{
					var exists = $.chunkedcookie(key + "---" + i);
				}

				if(exists != null)
				{
					$.chunkedcookie(key + "---" + i, null, options);
				}
				else
				{
					break;
				}
			}
		}
		else
		{
			// If the localStorage is available, and if the user requested its usage,
			// then we create that value in the localStorage of the browser (and not in a cookie)
			if(options.useLocalStorage && isStorageAvailable != false)
			{
				localStorage.setItem(key, value);
			}
			else
			{
				// The user tries to create a new cookie

				// Chunk the input content
				var exp = new RegExp(".{1,"+options.maxChunkSize+"}","g");

				if(value.match != undefined)
				{
					var chunks = value.match(exp);

					// Create one cookie per chunk
					for(var i = 0; i < chunks.length; i++)
					{
						if(i == 0)
						{
							$.chunkedcookie(key, chunks[i], options);
						}
						else
						{
							$.chunkedcookie(key + "---" + i, chunks[i], options);
						}
					}
				}
				else
				{
					// The value is probably a number, so we add it to a single cookie
					$.chunkedcookie(key, value, options);
				}
			}
		}

		return(null);
	}

	// Check if options have been given for a cookie retreival operation
	if(options == undefined)
	{
		var options;

		if(arguments.length > 1 && String(value) === "[object Object]")
		{
			options = value;
		}
		else
		{
			options = {};
		}

		if(options.maxNumberOfCookies == undefined)
		{
			options.maxNumberOfCookies = 20;
		}

		if(options.useLocalStorage == undefined)
		{
			options.useLocalStorage = true;
		}
	}

	// If localStorage is available, we first check if there exists a value for that name.
	// If no value exists in the localStorage, then we continue by checking in the cookies
	// This second checkup is needed in case that a cookie has been created in the past,
	// using the old cookie jQuery plugin.
	if(isStorageAvailable != false)
	{
		var value = localStorage.getItem(key);

		if(value != undefined && value != null)
		{
			return(value);
		}
	}

	var value = "";

	// The user tries to get the value of a cookie
	for(var i = 0; i < options.maxNumberOfCookies; i++)
	{
		// Check if the next chunk exists in the browser
		if(i == 0)
		{
			var val = $.chunkedcookie(key);
		}
		else
		{
			var val = $.chunkedcookie(key + "---" + i);
		}

		// Append the value
		if(val != null)
		{
			value += val;
		}
		else
		{
			// If the value is null, and we are looking at the first chunk, then
			// it means that the cookie simply doesn't exist
			if(i == 0)
			{
				return(null);
			}

			break;
		}
	}

	// Return the entire content from all the cookies that may have been used for that value.
	return(value);
};

/**
 * The chunkedcookie function comes from the jQuery Cookie plugin available here:
 *
 *   https://github.com/carhartl/jquery-cookie
 *
 * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */
jQuery.chunkedcookie = function (key, value, options) {

	// key and at least value given, set cookie...
	if (arguments.length > 1 && String(value) !== "[object Object]") {
		options = jQuery.extend({}, options);

		if (value === null || value === undefined) {
			options.expires = -1;
		}

		if (typeof options.expires === 'number') {
			var days = options.expires, t = options.expires = new Date();
			t.setDate(t.getDate() + days);
		}

		value = String(value);

		return (document.cookie = [
			encodeURIComponent(key), '=',
			options.raw ? value : encodeURIComponent(value),
			options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
			options.path ? '; path=' + options.path : '',
			options.domain ? '; domain=' + options.domain : '',
			options.secure ? '; secure' : ''
		].join(''));
	}

	// key and possibly options given, get cookie...
	options = value || {};
	var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
	return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
};
/*
 * FancyBox 
 * Version: Custom-Fix auf Basis von 1.3.4
 * Requires: jQuery v1.9+
 */
;(function($) {
	var tmp, loading, overlay, wrap, outer, content, close, title, nav_left, nav_right, start_pos, final_pos,
		$w = $(window),
		$d = $(document),
		lastResizeW,
		lastResizeH,
		selectedIndex = 0,
		selectedOpts = {},
		selectedArray = [],
		currentIndex = 0,
		currentOpts = {},
		currentArray = [],
		ajaxLoader = null,
		imgPreloader = new Image(),
		imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,
		swfRegExp = /[^\.]\.(swf)\s*$/i,
		loadingTimer,
		loadingFrame = 1,
		titleHeight = 0,
		titleStr = '',
		busy = false,
		fx = $.extend($('<div/>')[0], { prop: 0 }),

		_abort = function() {
			loading.hide();

			imgPreloader.onerror = imgPreloader.onload = null;

			if (ajaxLoader) {
				ajaxLoader.abort();
			}

			tmp.empty();
		},

		_error = function() {
			if (false === selectedOpts.onError(selectedArray, selectedIndex, selectedOpts)) {
				loading.hide();
				busy = false;
				return;
			}

			selectedOpts.titleShow = false;

			selectedOpts.width = 'auto';
			selectedOpts.height = 'auto';

			tmp.html('<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>');

			_process_inline();
		},

		_start = function() {
			var obj = selectedArray[ selectedIndex ],
				$obj = $(obj),
				href,
				type,
				title,
				str,
				emb,
				ret,
				o;

			_abort();

			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $obj.data('fancybox') === 'undefined' ? selectedOpts : $obj.data('fancybox')));

			ret = selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts);

			if (ret === false) {
				busy = false;
				return;
			} else if (typeof ret === 'object') {
				selectedOpts = $.extend(selectedOpts, ret);
			}

			title = selectedOpts.title || (obj.nodeName ? $obj.attr('title') : obj.title) || '';

			if (obj.nodeName && !selectedOpts.orig) {
				selectedOpts.orig = $obj.children("img:first").length ? $obj.children("img:first") : $obj;
			}

			if (title === '' && selectedOpts.orig && selectedOpts.titleFromAlt) {
				title = selectedOpts.orig.attr('alt');
			}

			href = selectedOpts.href || (obj.nodeName ? $obj.attr('href') : obj.href) || null;

			if ((/^(?:javascript)/i).test(href) || href === '#') {
				href = null;
			}

			if (selectedOpts.type) {
				type = selectedOpts.type;

				if (!href) {
					href = selectedOpts.content;
				}

			} else if (selectedOpts.content) {
				type = 'html';

			} else if (href) {
				if (href.match(imgRegExp)) {
					type = 'image';

				} else if (href.match(swfRegExp)) {
					type = 'swf';

				} else if ($obj.hasClass("iframe")) {
					type = 'iframe';

				} else if (href.indexOf("#") === 0) {
					type = 'inline';

				} else {
					type = 'ajax';
				}
			}

			if (!type) {
				_error();
				return;
			}

			if (type === 'inline') {
				$obj = $(href.substr(href.indexOf("#")));
				type = $obj.length > 0 ? 'inline' : 'ajax';
			}

			selectedOpts.type = type;
			selectedOpts.href = href;
			selectedOpts.title = title;

			if (selectedOpts.autoDimensions) {
				if (selectedOpts.type === 'html' || selectedOpts.type === 'inline' || selectedOpts.type === 'ajax') {
					selectedOpts.width = 'auto';
					selectedOpts.height = 'auto';
				} else {
					selectedOpts.autoDimensions = false;	
				}
			}

			if (selectedOpts.modal) {
				selectedOpts.overlayShow = true;
				selectedOpts.hideOnOverlayClick = false;
				selectedOpts.hideOnContentClick = false;
				selectedOpts.enableEscapeButton = false;
				selectedOpts.showCloseButton = false;
			}

			selectedOpts.padding = parseInt(selectedOpts.padding, 10);
			selectedOpts.margin = parseInt(selectedOpts.margin, 10);

			tmp.css('padding', (selectedOpts.padding + selectedOpts.margin));

			$('.fancybox-inline-tmp').off('fancybox-cancel').on('fancybox-change', function() {
				$(this).replaceWith(content.children());
				console.log(content);
				console.log(content.children());
			});

			switch (type) {
				case 'html' :
					tmp.html(selectedOpts.content);
					_process_inline();
				break;

				case 'inline' :
					if ($obj.parent().is('#fancybox-content') === true) {
						busy = false;
						return;
					}

					$('<div class="fancybox-inline-tmp" />')
						.hide()
						.insertBefore($obj)
						.on('fancybox-cleanup', function() {
							$(this).replaceWith(content.children());
						}).on('fancybox-cancel', function() {
							$(this).replaceWith(tmp.children());
						});

					$obj.appendTo(tmp);

					_process_inline();
				break;

				case 'image':
					busy = false;

					$.fancybox.showActivity();

					imgPreloader = new Image();

					imgPreloader.onerror = function() {
						_error();
					};

					imgPreloader.onload = function() {
						busy = true;

						imgPreloader.onerror = imgPreloader.onload = null;

						_process_image();
					};

					imgPreloader.src = href;
				break;

				case 'swf':
					selectedOpts.scrolling = 'no';

					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
					emb = '';

					$.each(selectedOpts.swf, function(name, val) {
						str += '<param name="' + name + '" value="' + val + '"></param>';
						emb += ' ' + name + '="' + val + '"';
					});

					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';

					tmp.html(str);

					_process_inline();
				break;

				case 'ajax':
					busy = false;

					$.fancybox.showActivity();

					selectedOpts.ajax.win = selectedOpts.ajax.success;

					ajaxLoader = $.ajax($.extend({}, selectedOpts.ajax, {
						url	: href,
						data : selectedOpts.ajax.data || {},
						error : function(XMLHttpRequest) {
							if (XMLHttpRequest.status > 0) {
								_error();
							}
						},
						success : function(data, textStatus, XMLHttpRequest) {
							o = typeof XMLHttpRequest === 'object' ? XMLHttpRequest : ajaxLoader;
							if (o.status === 200) {
								if (typeof selectedOpts.ajax.win === 'function') {
									ret = selectedOpts.ajax.win(href, data, textStatus, XMLHttpRequest);

									if (ret === false) {
										loading.hide();
										return;
									} else if (typeof ret === 'string' || typeof ret === 'object') {
										data = ret;
									}
								}

								tmp.html(data);
								_process_inline();
							}
						}
					}));

				break;

				case 'iframe':
					_show();
				break;
			}
		},

		_process_inline = function() {
			var w = selectedOpts.width,
				h = selectedOpts.height;

			if (w.toString().indexOf('%') > -1) {
				w = parseInt(($w.width() - (selectedOpts.margin * 2)) * parseFloat(w) / 100, 10) + 'px';
			} else {
				w = w === 'auto' ? 'auto' : w + 'px';	
			}

			if (h.toString().indexOf('%') > -1) {
				h = parseInt(($w.height() - (selectedOpts.margin * 2)) * parseFloat(h) / 100, 10) + 'px';
			} else {
				h = h === 'auto' ? 'auto' : h + 'px';	
			}

			tmp.wrapInner('<div style="width:' + w + ';height:' + h + ';overflow: ' + (selectedOpts.scrolling === 'auto' ? 'auto' : (selectedOpts.scrolling === 'yes' ? 'scroll' : 'hidden')) + ';position:relative;"></div>');

			selectedOpts.width = tmp.width();
			selectedOpts.height = tmp.height();

			_show();
		},

		_process_image = function() {
			selectedOpts.width = imgPreloader.width;
			selectedOpts.height = imgPreloader.height;

			$("<img />").attr({
				'id' : 'fancybox-img',
				'src' : imgPreloader.src,
				'alt' : selectedOpts.title
			}).appendTo(tmp);

			_show();
		},

		_show = function() {
			var pos, equal, finish_resizing;

			loading.hide();

			if (currentOpts && currentOpts.onCleanup && wrap.is(":visible") && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
				//$.event.trigger('fancybox-cancel');
				$('.fancybox-inline-tmp').trigger('fancybox-cancel');
				busy = false;
				return;
			}

			busy = true;

			$(content.add(overlay)).off();

			$w.off("resize.fb scroll.fb");
			$d.off('keydown.fb');

			if (wrap.is(":visible") && currentOpts.titlePosition !== 'outside') {
				wrap.css('height', wrap.height());
			}

			currentArray = selectedArray;
			currentIndex = selectedIndex;
			currentOpts = selectedOpts;

			if (currentOpts.overlayShow) {
				overlay.css({
					'background-color' : currentOpts.overlayColor,
					'opacity' : currentOpts.overlayOpacity,
					'cursor' : currentOpts.hideOnOverlayClick ? 'pointer' : 'auto',
					'height' : $d.height()
				});

				if (!overlay.is(':visible')) {
					overlay.show();
				}
			} else {
				overlay.hide();
			}

			final_pos = _get_zoom_to();

			_process_title();

			if (wrap.is(":visible")) {
				$(close.add(nav_left).add(nav_right)).hide();

				pos = wrap.position();

				start_pos = {
					top		: pos.top,
					left	: pos.left,
					width	: wrap.width(),
					height	: wrap.height()
				};

				equal = (start_pos.width === final_pos.width && start_pos.height === final_pos.height);

				content.fadeTo(currentOpts.changeFade, 0.3, function() {
					finish_resizing = function() {
						content.html(tmp.contents()).fadeTo(currentOpts.changeFade, 1, _finish);
					};

					//$.event.trigger('fancybox-change');
					$('.fancybox-inline-tmp').trigger('fancybox-change');
					content
						.empty()
						.removeAttr('filter')
						.css({
							'border-width' : currentOpts.padding,
							'width'	: final_pos.width - currentOpts.padding * 2,
							'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
						});

					if (equal) {
						finish_resizing();
					} else {
						fx.prop = 0;

						$(fx).animate({prop: 1}, {
							duration	: currentOpts.changeSpeed,
							easing		: currentOpts.easingChange,
							step		: _draw,
							complete	: finish_resizing
						});
					}
				});

				return;
			}

			wrap.removeAttr("style");

			content.css('border-width', currentOpts.padding);

			if (currentOpts.transitionIn === 'elastic') {
				start_pos = _get_zoom_from();

				content.html(tmp.contents());

				wrap.show();

				if (currentOpts.opacity) {
					final_pos.opacity = 0;
				}

				fx.prop = 0;

				$(fx).animate({prop: 1}, {
					duration	: currentOpts.speedIn,
					easing		: currentOpts.easingIn,
					step		: _draw,
					complete	: _finish
				});

				return;
			}

			if (currentOpts.titlePosition === 'inside' && titleHeight > 0) {	
				title.show();	
			}

			content
				.css({
					'width' : final_pos.width - currentOpts.padding * 2,
					'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
				})
				.html(tmp.contents());

			wrap
				.css(final_pos)
				.fadeIn(currentOpts.transitionIn === 'none' ? 0 : currentOpts.speedIn, _finish);
		},

		_format_title = function(title) {
			if (title && title.length) {
				if (currentOpts.titlePosition === 'float') {
					return '<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">' + title + '</td><td id="fancybox-title-float-right"></td></tr></table>';
				}

				return '<div id="fancybox-title-' + currentOpts.titlePosition + '">' + title + '</div>';
			}

			return false;
		},

		_process_title = function() {
			titleStr = currentOpts.title || '';
			titleHeight = 0;

			title
				.empty()
				.removeAttr('style')
				.removeClass();

			if (currentOpts.titleShow === false) {
				title.hide();
				return;
			}

			titleStr = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(titleStr, currentArray, currentIndex, currentOpts) : _format_title(titleStr);

			if (!titleStr || titleStr === '') {
				title.hide();
				return;
			}

			title
				.addClass('fancybox-title-' + currentOpts.titlePosition)
				.html(titleStr)
				.appendTo('body')
				.show();

			switch (currentOpts.titlePosition) {
				case 'inside':
					title
						.css({
							'width' : final_pos.width - (currentOpts.padding * 2),
							'marginLeft' : currentOpts.padding,
							'marginRight' : currentOpts.padding
						});

					titleHeight = title.outerHeight(true);

					title.appendTo(outer);

					final_pos.height += titleHeight;
				break;

				case 'over':
					title
						.css({
							'marginLeft' : currentOpts.padding,
							'width'	: final_pos.width - (currentOpts.padding * 2),
							'bottom' : currentOpts.padding
						})
						.appendTo(outer);
				break;

				case 'float':
					title
						.css('left', parseInt((title.width() - final_pos.width - 40)/ 2, 10) * -1)
						.appendTo(wrap);
				break;

				default:
					title
						.css({
							'width' : final_pos.width - (currentOpts.padding * 2),
							'paddingLeft' : currentOpts.padding,
							'paddingRight' : currentOpts.padding
						})
						.appendTo(wrap);
				break;
			}

			title.hide();
		},

		_set_navigation = function() {
			if (currentOpts.enableEscapeButton || currentOpts.enableKeyboardNav) {
				$d.on('keydown.fb', function(e) {
					if (e.keyCode === 27 && currentOpts.enableEscapeButton) {
						e.preventDefault();
						$.fancybox.close();

					} else if ((e.keyCode === 37 || e.keyCode === 39) && currentOpts.enableKeyboardNav && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT') {
						e.preventDefault();
						$.fancybox[ e.keyCode === 37 ? 'prev' : 'next']();
					}
				});
			}

			if (!currentOpts.showNavArrows) { 
				nav_left.hide();
				nav_right.hide();
				return;
			}

			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
				nav_left.show();
			}

			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== (currentArray.length -1)) {
				nav_right.show();
			}
		},

		_finish = function () {
			if (selectedOpts.autoDimensions) {
				content.css('height', 'auto');
			}

			wrap.css('height', 'auto');

			if (titleStr && titleStr.length) {
				title.show();
			}

			if (currentOpts.showCloseButton) {
				close.show();
			}

			_set_navigation();
	
			if (currentOpts.hideOnContentClick)	{
				content.on('click', $.fancybox.close);
			}

			if (currentOpts.hideOnOverlayClick)	{
				overlay.on('click', $.fancybox.close);
			}

			$w.on("resize.fb", $.fancybox.resize);

			if (currentOpts.centerOnScroll) {
				$w.on("scroll.fb", $.fancybox.center);
			}

			if (currentOpts.type === 'iframe') {
				$('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" allowtransparency="true" scrolling="' + selectedOpts.scrolling + '" src="' + currentOpts.href + '"></iframe>').appendTo(content);
			}

			wrap.show();

			busy = false;

			$.fancybox.center();

			currentOpts.onComplete(currentArray, currentIndex, currentOpts);

			_preload_images();
		},

		_preload_images = function() {
			var href, 
				objNext;

			if ((currentArray.length -1) > currentIndex) {
				href = currentArray[ currentIndex + 1 ].href;

				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
					objNext = new Image();
					objNext.src = href;
				}
			}

			if (currentIndex > 0) {
				href = currentArray[ currentIndex - 1 ].href;

				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
					objNext = new Image();
					objNext.src = href;
				}
			}
		},

		_draw = function(pos) {
			var dim = {
				width : parseInt(start_pos.width + (final_pos.width - start_pos.width) * pos, 10),
				height : parseInt(start_pos.height + (final_pos.height - start_pos.height) * pos, 10),

				top : parseInt(start_pos.top + (final_pos.top - start_pos.top) * pos, 10),
				left : parseInt(start_pos.left + (final_pos.left - start_pos.left) * pos, 10)
			};

			if (typeof final_pos.opacity !== 'undefined') {
				dim.opacity = pos < 0.5 ? 0.5 : pos;
			}

			wrap.css(dim);

			content.css({
				'width' : dim.width - currentOpts.padding * 2,
				'height' : dim.height - (titleHeight * pos) - currentOpts.padding * 2
			});
		},

		_get_viewport = function() {
			return [
				$w.width() - (currentOpts.margin * 2),
				$w.height() - (currentOpts.margin * 2),
				$d.scrollLeft() + currentOpts.margin,
				$d.scrollTop() + currentOpts.margin
			];
		},

		_get_zoom_to = function () {
			var view = _get_viewport(),
				to = {},
				resize = currentOpts.autoScale,
				double_padding = currentOpts.padding * 2,
				ratio;

			if (currentOpts.width.toString().indexOf('%') > -1) {
				to.width = parseInt((view[0] * parseFloat(currentOpts.width)) / 100, 10);
			} else {
				to.width = currentOpts.width + double_padding;
			}

			if (currentOpts.height.toString().indexOf('%') > -1) {
				to.height = parseInt((view[1] * parseFloat(currentOpts.height)) / 100, 10);
			} else {
				to.height = currentOpts.height + double_padding;
			}

			if (resize && (to.width > view[0] || to.height > view[1])) {
				if (selectedOpts.type === 'image' || selectedOpts.type === 'swf') {
					ratio = (currentOpts.width) / (currentOpts.height);

					if ((to.width) > view[0]) {
						to.width = view[0];
						to.height = parseInt(((to.width - double_padding) / ratio) + double_padding, 10);
					}

					if ((to.height) > view[1]) {
						to.height = view[1];
						to.width = parseInt(((to.height - double_padding) * ratio) + double_padding, 10);
					}

				} else {
					to.width = Math.min(to.width, view[0]);
					to.height = Math.min(to.height, view[1]);
				}
			}

			to.top = parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - to.height - 40) * 0.5)), 10);
			to.left = parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - to.width - 40) * 0.5)), 10);

			return to;
		},

		_get_obj_pos = function(obj) {
			var pos = obj.offset();

			pos.top += parseInt(obj.css('paddingTop'), 10) || 0;
			pos.left += parseInt(obj.css('paddingLeft'), 10) || 0;

			pos.top += parseInt(obj.css('border-top-width'), 10) || 0;
			pos.left += parseInt(obj.css('border-left-width'), 10) || 0;

			pos.width = obj.width();
			pos.height = obj.height();

			return pos;
		},

		_get_zoom_from = function() {
			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
				from = {},
				pos,
				view;

			if (orig && orig.length) {
				pos = _get_obj_pos(orig);

				from = {
					width : pos.width + (currentOpts.padding * 2),
					height : pos.height + (currentOpts.padding * 2),
					top	: pos.top - currentOpts.padding - 20,
					left : pos.left - currentOpts.padding - 20
				};

			} else {
				view = _get_viewport();

				from = {
					width : currentOpts.padding * 2,
					height : currentOpts.padding * 2,
					top	: parseInt(view[3] + view[1] * 0.5, 10),
					left : parseInt(view[2] + view[0] * 0.5, 10)
				};
			}

			return from;
		},

		_animate_loading = function() {
			if (!loading.is(':visible')){
				clearInterval(loadingTimer);
				return;
			}

			$('div', loading).css('top', (loadingFrame * -40) + 'px');

			loadingFrame = (loadingFrame + 1) % 12;
		};

	/*
	 * Public methods 
	 */

	$.fn.fancybox = function(options) {
		var rel, $t = $(this);
		
		if (!$t.length) {
			return this;
		}

		$t
			.data('fancybox', $.extend({}, options, ($.metadata ? $t.metadata() : {})))
			.off('click.fb')
			.on('click.fb', function(e) {
				e.preventDefault();

				if (busy) {
					return;
				}

				busy = true;

				$t.blur();

				selectedArray = [];
				selectedIndex = 0;

				rel = $t.attr('rel') || '';

				if (!rel || rel === 'nofollow') {
					selectedArray.push(this);
				} else {
					selectedArray = $('a[rel="' + rel + '"], area[rel="' + rel + '"]');
					selectedIndex = selectedArray.index(this);
				}

				_start();

				return;
			});

		return this;
	};

	$.fancybox = function(obj) {
		var i, j, opts;

		if (busy) {
			return;
		}

		busy = true;
		opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};

		selectedArray = [];
		selectedIndex = parseInt(opts.index, 10) || 0;

		if ($.isArray(obj)) {
			for (i = 0, j = obj.length; i < j; i++) {
				if (typeof obj[i] === 'object') {
					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
				} else {
					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
				}
			}

			selectedArray = jQuery.merge(selectedArray, obj);

		} else {
			if (typeof obj === 'object') {
				$(obj).data('fancybox', $.extend({}, opts, obj));
			} else {
				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
			}

			selectedArray.push(obj);
		}

		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
			selectedIndex = 0;
		}

		_start();
	};

	$.fancybox.showActivity = function() {
		clearInterval(loadingTimer);
		loading.show();
		loadingTimer = setInterval(_animate_loading, 66);
	};

	$.fancybox.hideActivity = function() {
		loading.hide();
	};

	$.fancybox.next = function() {
		return $.fancybox.pos(currentIndex + 1);
	};

	$.fancybox.prev = function() {
		return $.fancybox.pos(currentIndex - 1);
	};

	$.fancybox.pos = function(pos) {
		if (busy) {
			return;
		}

		pos = parseInt(pos, 10);

		selectedArray = currentArray;

		if (pos > -1 && pos < currentArray.length) {
			selectedIndex = pos;
			_start();

		} else if (currentOpts.cyclic && currentArray.length > 1) {
			selectedIndex = pos >= currentArray.length ? 0 : currentArray.length - 1;
			_start();
		}

		return;
	};

	$.fancybox.cancel = function() {
		if (busy) {
			return;
		}

		busy = true;

		//$.event.trigger('fancybox-cancel');
		$('.fancybox-inline-tmp').trigger('fancybox-cancel');

		_abort();

		selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);

		busy = false;
	};

	// Note: within an iframe use - parent.$.fancybox.close();
	$.fancybox.close = function() {
		var pos;
		
		if (busy || wrap.is(':hidden')) {
			return;
		}

		busy = true;

		if (currentOpts && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
			busy = false;
			return;
		}

		_abort();

		$(close.add(nav_left).add(nav_right)).hide();

		$(content.add(overlay)).off();

		$w.off("resize.fb scroll.fb");
		$d.off('keydown.fb');

		content.find('iframe').attr('src', 'about:blank');

		if (currentOpts.titlePosition !== 'inside') {
			title.empty();
		}

		wrap.stop();

		function _cleanup() {
			overlay.fadeOut('fast');

			title.empty().hide();
			wrap.hide();

			//$.event.trigger('fancybox-cleanup');
			$('.fancybox-inline-tmp, select:not(#fancybox-tmp select)').trigger('fancybox-cleanup');

			content.empty();

			currentOpts.onClosed(currentArray, currentIndex, currentOpts);

			currentArray = selectedOpts	= [];
			currentIndex = selectedIndex = 0;
			currentOpts = selectedOpts	= {};

			busy = false;
		}

		if (currentOpts.transitionOut === 'elastic') {
			start_pos = _get_zoom_from();

			pos = wrap.position();

			final_pos = {
				top		: pos.top,
				left	: pos.left,
				width	: wrap.width(),
				height	: wrap.height()
			};

			if (currentOpts.opacity) {
				final_pos.opacity = 1;
			}

			title.empty().hide();

			fx.prop = 1;

			$(fx).animate({ prop: 0 }, {
				duration	: currentOpts.speedOut,
				easing		: currentOpts.easingOut,
				step		: _draw,
				complete	: _cleanup
			});

		} else {
			wrap.fadeOut(currentOpts.transitionOut === 'none' ? 0 : currentOpts.speedOut, _cleanup);
		}
	};

	$.fancybox.resize = function() {
		var newW = $w.width(),
			newH = $w.height();
			
		if (newW !== lastResizeW || newH !== lastResizeH) {
			lastResizeW = newW;
			lastResizeH = newH;
			if (overlay.is(':visible')) {
				overlay.css('height', $d.height());
			}
			$.fancybox.center(true);
		}
	};

	$.fancybox.center = function() {
		var view, align;

		if (busy) {
			return;	
		}

		align = arguments[0] === true ? 1 : 0;
		view = _get_viewport();

		if (!align && (wrap.width() > view[0] || wrap.height() > view[1])) {
			return;	
		}

		wrap
			.stop()
			.animate({
				'top' : parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - content.height() - 40) * 0.5) - currentOpts.padding), 10),
				'left' : parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - content.width() - 40) * 0.5) - currentOpts.padding), 10)
			}, typeof arguments[0] === 'number' ? arguments[0] : 200);
	};

	$.fancybox.init = function() {
		if ($("#fancybox-wrap").length) {
			return;
		}

		$('body').append(
			tmp	= $('<div id="fancybox-tmp"></div>'),
			loading	= $('<div id="fancybox-loading"><div></div></div>'),
			overlay	= $('<div id="fancybox-overlay"></div>'),
			wrap = $('<div id="fancybox-wrap"></div>')
		);

		outer = $('<div id="fancybox-outer"></div>')
			.append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>')
			.appendTo(wrap);

		outer.append(
			content = $('<div id="fancybox-content"></div>'),
			close = $('<div id="fancybox-close"></div>'),
			title = $('<div id="fancybox-title"></div>'),

			nav_left = $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
			nav_right = $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
		);

		close.click($.fancybox.close);
		loading.click($.fancybox.cancel);

		nav_left.click(function(e) {
			e.preventDefault();
			$.fancybox.prev();
		});

		nav_right.click(function(e) {
			e.preventDefault();
			$.fancybox.next();
		});

		if ($.fn.mousewheel) {
			wrap.on('mousewheel.fb', function(e, delta) {
				if (busy) {
					e.preventDefault();

				} else if ($(e.target).get(0).clientHeight === 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) {
					e.preventDefault();
					$.fancybox[ delta > 0 ? 'prev' : 'next']();
				}
			});
		}

		if (!$.support.opacity) {
			wrap.addClass('fancybox-ie');
		}

		lastResizeW = $w.width();
		lastResizeH = $w.height();
	};

	$.fn.fancybox.defaults = {
		padding : 10,
		margin : 40,
		opacity : false,
		modal : false,
		cyclic : false,
		scrolling : 'auto',	// 'auto', 'yes' or 'no'

		width : 560,
		height : 340,

		autoScale : true,
		autoDimensions : true,
		centerOnScroll : false,

		ajax : {},
		swf : { wmode: 'transparent' },

		hideOnOverlayClick : true,
		hideOnContentClick : false,

		overlayShow : true,
		overlayOpacity : 0.7,
		overlayColor : '#777',

		titleShow : true,
		titlePosition : 'float', // 'float', 'outside', 'inside' or 'over'
		titleFormat : null,
		titleFromAlt : false,

		transitionIn : 'fade', // 'elastic', 'fade' or 'none'
		transitionOut : 'fade', // 'elastic', 'fade' or 'none'

		speedIn : 300,
		speedOut : 300,

		changeSpeed : 300,
		changeFade : 'fast',

		easingIn : 'swing',
		easingOut : 'swing',

		showCloseButton : true,
		showNavArrows : true,
		enableEscapeButton : true,
		enableKeyboardNav : true,

		onStart : function(){},
		onCancel : function(){},
		onComplete : function(){},
		onCleanup : function(){},
		onClosed : function(){},
		onError : function(){}
	};

	$d.ready(function() {
		$.fancybox.init();
	});

})(jQuery);
/*! noUiSlider - 8.0.1 - 2015-06-29 19:11:22 */

!function(a){"function"==typeof define&&define.amd?define([],a):"object"==typeof exports?module.exports=a(require("jquery")):window.noUiSlider=a()}(function(){"use strict";function a(a){return a.filter(function(a){return this[a]?!1:this[a]=!0},{})}function b(a,b){return Math.round(a/b)*b}function c(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.defaultView||c.parentWindow,e=c.documentElement,f=d.pageXOffset;return/webkit.*Chrome.*Mobile/i.test(navigator.userAgent)&&(f=0),{top:b.top+d.pageYOffset-e.clientTop,left:b.left+f-e.clientLeft}}function d(a){return"number"==typeof a&&!isNaN(a)&&isFinite(a)}function e(a){var b=Math.pow(10,7);return Number((Math.round(a*b)/b).toFixed(7))}function f(a,b,c){k(a,b),setTimeout(function(){l(a,b)},c)}function g(a){return Math.max(Math.min(a,100),0)}function h(a){return Array.isArray(a)?a:[a]}function j(a){var b=a.split(".");return b.length>1?b[1].length:0}function k(a,b){a.classList?a.classList.add(b):a.className+=" "+b}function l(a,b){a.classList?a.classList.remove(b):a.className=a.className.replace(new RegExp("(^|\\b)"+b.split(" ").join("|")+"(\\b|$)","gi")," ")}function m(a,b){a.classList?a.classList.contains(b):new RegExp("(^| )"+b+"( |$)","gi").test(a.className)}function n(a,b){return 100/(b-a)}function o(a,b){return 100*b/(a[1]-a[0])}function p(a,b){return o(a,a[0]<0?b+Math.abs(a[0]):b-a[0])}function q(a,b){return b*(a[1]-a[0])/100+a[0]}function r(a,b){for(var c=1;a>=b[c];)c+=1;return c}function s(a,b,c){if(c>=a.slice(-1)[0])return 100;var d,e,f,g,h=r(c,a);return d=a[h-1],e=a[h],f=b[h-1],g=b[h],f+p([d,e],c)/n(f,g)}function t(a,b,c){if(c>=100)return a.slice(-1)[0];var d,e,f,g,h=r(c,b);return d=a[h-1],e=a[h],f=b[h-1],g=b[h],q([d,e],(c-f)*n(f,g))}function u(a,c,d,e){if(100===e)return e;var f,g,h=r(e,a);return d?(f=a[h-1],g=a[h],e-f>(g-f)/2?g:f):c[h-1]?a[h-1]+b(e-a[h-1],c[h-1]):e}function v(a,b,c){var e;if("number"==typeof b&&(b=[b]),"[object Array]"!==Object.prototype.toString.call(b))throw new Error("noUiSlider: 'range' contains invalid value.");if(e="min"===a?0:"max"===a?100:parseFloat(a),!d(e)||!d(b[0]))throw new Error("noUiSlider: 'range' value isn't numeric.");c.xPct.push(e),c.xVal.push(b[0]),e?c.xSteps.push(isNaN(b[1])?!1:b[1]):isNaN(b[1])||(c.xSteps[0]=b[1])}function w(a,b,c){return b?void(c.xSteps[a]=o([c.xVal[a],c.xVal[a+1]],b)/n(c.xPct[a],c.xPct[a+1])):!0}function x(a,b,c,d){this.xPct=[],this.xVal=[],this.xSteps=[d||!1],this.xNumSteps=[!1],this.snap=b,this.direction=c;var e,f=[];for(e in a)a.hasOwnProperty(e)&&f.push([a[e],e]);for(f.sort(function(a,b){return a[0]-b[0]}),e=0;e<f.length;e++)v(f[e][1],f[e][0],this);for(this.xNumSteps=this.xSteps.slice(0),e=0;e<this.xNumSteps.length;e++)w(e,this.xNumSteps[e],this)}function y(a,b){if(!d(b))throw new Error("noUiSlider: 'step' is not numeric.");a.singleStep=b}function z(a,b){if("object"!=typeof b||Array.isArray(b))throw new Error("noUiSlider: 'range' is not an object.");if(void 0===b.min||void 0===b.max)throw new Error("noUiSlider: Missing 'min' or 'max' in 'range'.");a.spectrum=new x(b,a.snap,a.dir,a.singleStep)}function A(a,b){if(b=h(b),!Array.isArray(b)||!b.length||b.length>2)throw new Error("noUiSlider: 'start' option is incorrect.");a.handles=b.length,a.start=b}function B(a,b){if(a.snap=b,"boolean"!=typeof b)throw new Error("noUiSlider: 'snap' option must be a boolean.")}function C(a,b){if(a.animate=b,"boolean"!=typeof b)throw new Error("noUiSlider: 'animate' option must be a boolean.")}function D(a,b){if("lower"===b&&1===a.handles)a.connect=1;else if("upper"===b&&1===a.handles)a.connect=2;else if(b===!0&&2===a.handles)a.connect=3;else{if(b!==!1)throw new Error("noUiSlider: 'connect' option doesn't match handle count.");a.connect=0}}function E(a,b){switch(b){case"horizontal":a.ort=0;break;case"vertical":a.ort=1;break;default:throw new Error("noUiSlider: 'orientation' option is invalid.")}}function F(a,b){if(!d(b))throw new Error("noUiSlider: 'margin' option must be numeric.");if(a.margin=a.spectrum.getMargin(b),!a.margin)throw new Error("noUiSlider: 'margin' option is only supported on linear sliders.")}function G(a,b){if(!d(b))throw new Error("noUiSlider: 'limit' option must be numeric.");if(a.limit=a.spectrum.getMargin(b),!a.limit)throw new Error("noUiSlider: 'limit' option is only supported on linear sliders.")}function H(a,b){switch(b){case"ltr":a.dir=0;break;case"rtl":a.dir=1,a.connect=[0,2,1,3][a.connect];break;default:throw new Error("noUiSlider: 'direction' option was not recognized.")}}function I(a,b){if("string"!=typeof b)throw new Error("noUiSlider: 'behaviour' must be a string containing options.");var c=b.indexOf("tap")>=0,d=b.indexOf("drag")>=0,e=b.indexOf("fixed")>=0,f=b.indexOf("snap")>=0;a.events={tap:c||f,drag:d,fixed:e,snap:f}}function J(a,b){if(a.format=b,"function"==typeof b.to&&"function"==typeof b.from)return!0;throw new Error("noUiSlider: 'format' requires 'to' and 'from' methods.")}function K(a){var b,c={margin:0,limit:0,animate:!0,format:V};b={step:{r:!1,t:y},start:{r:!0,t:A},connect:{r:!0,t:D},direction:{r:!0,t:H},snap:{r:!1,t:B},animate:{r:!1,t:C},range:{r:!0,t:z},orientation:{r:!1,t:E},margin:{r:!1,t:F},limit:{r:!1,t:G},behaviour:{r:!0,t:I},format:{r:!1,t:J}};var d={connect:!1,direction:"ltr",behaviour:"tap",orientation:"horizontal"};return Object.keys(d).forEach(function(b){void 0===a[b]&&(a[b]=d[b])}),Object.keys(b).forEach(function(d){var e=b[d];if(void 0===a[d]){if(e.r)throw new Error("noUiSlider: '"+d+"' is required.");return!0}e.t(c,a[d])}),c.pips=a.pips,c.style=c.ort?"top":"left",c}function L(a,b,c){var d=a+b[0],e=a+b[1];return c?(0>d&&(e+=Math.abs(d)),e>100&&(d-=e-100),[g(d),g(e)]):[d,e]}function M(a){a.preventDefault();var b,c,d=0===a.type.indexOf("touch"),e=0===a.type.indexOf("mouse"),f=0===a.type.indexOf("pointer"),g=a;return 0===a.type.indexOf("MSPointer")&&(f=!0),d&&(b=a.changedTouches[0].pageX,c=a.changedTouches[0].pageY),(e||f)&&(b=a.clientX+window.pageXOffset,c=a.clientY+window.pageYOffset),g.points=[b,c],g.cursor=e||f,g}function N(a,b){var c=document.createElement("div"),d=document.createElement("div"),e=["-lower","-upper"];return a&&e.reverse(),k(d,U[3]),k(d,U[3]+e[b]),k(c,U[2]),c.appendChild(d),c}function O(a,b,c){switch(a){case 1:k(b,U[7]),k(c[0],U[6]);break;case 3:k(c[1],U[6]);case 2:k(c[0],U[7]);case 0:k(b,U[6])}}function P(a,b,c){var d,e=[];for(d=0;a>d;d+=1)e.push(c.appendChild(N(b,d)));return e}function Q(a,b,c){k(c,U[0]),k(c,U[8+a]),k(c,U[4+b]);var d=document.createElement("div");return k(d,U[1]),c.appendChild(d),d}function R(b,d){function e(a,b,c){if("range"===a||"steps"===a)return N.xVal;if("count"===a){var d,e=100/(b-1),f=0;for(b=[];(d=f++*e)<=100;)b.push(d);a="positions"}return"positions"===a?b.map(function(a){return N.fromStepping(c?N.getStep(a):a)}):"values"===a?c?b.map(function(a){return N.fromStepping(N.getStep(N.toStepping(a)))}):b:void 0}function n(b,c,d){var e=N.direction,f={},g=N.xVal[0],h=N.xVal[N.xVal.length-1],i=!1,j=!1,k=0;return N.direction=0,d=a(d.slice().sort(function(a,b){return a-b})),d[0]!==g&&(d.unshift(g),i=!0),d[d.length-1]!==h&&(d.push(h),j=!0),d.forEach(function(a,e){var g,h,l,m,n,o,p,q,r,s,t=a,u=d[e+1];if("steps"===c&&(g=N.xNumSteps[e]),g||(g=u-t),t!==!1&&void 0!==u)for(h=t;u>=h;h+=g){for(m=N.toStepping(h),n=m-k,q=n/b,r=Math.round(q),s=n/r,l=1;r>=l;l+=1)o=k+l*s,f[o.toFixed(5)]=["x",0];p=d.indexOf(h)>-1?1:"steps"===c?2:0,!e&&i&&(p=0),h===u&&j||(f[m.toFixed(5)]=[h,p]),k=m}}),N.direction=e,f}function o(a,b,c){function e(a){return["-normal","-large","-sub"][a]}function f(a,b,c){return'class="'+b+" "+b+"-"+h+" "+b+e(c[1],c[0])+'" style="'+d.style+": "+a+'%"'}function g(a,d){N.direction&&(a=100-a),d[1]=d[1]&&b?b(d[0],d[1]):d[1],i.innerHTML+="<div "+f(a,"noUi-marker",d)+"></div>",d[1]&&(i.innerHTML+="<div "+f(a,"noUi-value",d)+">"+c.to(d[0])+"</div>")}var h=["horizontal","vertical"][d.ort],i=document.createElement("div");return k(i,"noUi-pips"),k(i,"noUi-pips-"+h),Object.keys(a).forEach(function(b){g(b,a[b])}),i}function p(a){var b=a.mode,c=a.density||1,d=a.filter||!1,f=a.values||!1,g=a.stepped||!1,h=e(b,f,g),i=n(c,b,h),j=a.format||{to:Math.round};return J.appendChild(o(i,d,j))}function q(){return H["offset"+["Width","Height"][d.ort]]}function r(a,b){void 0!==b&&(b=Math.abs(b-d.dir)),Object.keys(S).forEach(function(c){var d=c.split(".")[0];a===d&&S[c].forEach(function(a){a(h(C()),b,s(Array.prototype.slice.call(R)))})})}function s(a){return 1===a.length?a[0]:d.dir?a.reverse():a}function t(a,b,c,e){var f=function(b){return J.hasAttribute("disabled")?!1:m(J,U[14])?!1:(b=M(b),a===T.start&&void 0!==b.buttons&&b.buttons>1?!1:(b.calcPoint=b.points[d.ort],void c(b,e)))},g=[];return a.split(" ").forEach(function(a){b.addEventListener(a,f,!1),g.push([a,f])}),g}function u(a,b){var c,d=b.handles||I,e=!1,f=100*(a.calcPoint-b.start)/q(),g=d[0]===I[0]?0:1;if(c=L(f,b.positions,d.length>1),e=z(d[0],c[g],1===d.length),d.length>1){if(e=z(d[1],c[g?0:1],!1)||e)for(i=0;i<b.handles.length;i++)r("slide",i)}else e&&r("slide",g)}function v(a,b){var c=H.getElementsByClassName(U[15]),d=b.handles[0]===I[0]?0:1;c.length&&l(c[0],U[15]),a.cursor&&(document.body.style.cursor="",document.body.removeEventListener("selectstart",document.body.noUiListener));var e=document.documentElement;e.noUiListeners.forEach(function(a){e.removeEventListener(a[0],a[1])}),l(J,U[12]),r("set",d),r("change",d)}function w(a,b){var c=document.documentElement;if(1===b.handles.length&&(k(b.handles[0].children[0],U[15]),b.handles[0].hasAttribute("disabled")))return!1;a.stopPropagation();var d=t(T.move,c,u,{start:a.calcPoint,handles:b.handles,positions:[K[0],K[I.length-1]]}),e=t(T.end,c,v,{handles:b.handles});if(c.noUiListeners=d.concat(e),a.cursor){document.body.style.cursor=getComputedStyle(a.target).cursor,I.length>1&&k(J,U[12]);var f=function(){return!1};document.body.noUiListener=f,document.body.addEventListener("selectstart",f,!1)}}function x(a){var b,e,g=a.calcPoint,h=0;return a.stopPropagation(),I.forEach(function(a){h+=c(a)[d.style]}),b=h/2>g||1===I.length?0:1,g-=c(H)[d.style],e=100*g/q(),d.events.snap||f(J,U[14],300),I[b].hasAttribute("disabled")?!1:(z(I[b],e),r("slide",b),r("set",b),r("change",b),void(d.events.snap&&w(a,{handles:[I[h]]})))}function y(a){var b,c;if(!a.fixed)for(b=0;b<I.length;b+=1)t(T.start,I[b].children[0],w,{handles:[I[b]]});a.tap&&t(T.start,H,x,{handles:I}),a.drag&&(c=[H.getElementsByClassName(U[7])[0]],k(c[0],U[10]),a.fixed&&c.push(I[c[0]===I[0]?1:0].children[0]),c.forEach(function(a){t(T.start,a,w,{handles:I})}))}function z(a,b,c){var e=a!==I[0]?1:0,f=K[0]+d.margin,h=K[1]-d.margin,i=K[0]+d.limit,j=K[1]-d.limit;return I.length>1&&(b=e?Math.max(b,f):Math.min(b,h)),c!==!1&&d.limit&&I.length>1&&(b=e?Math.min(b,i):Math.max(b,j)),b=N.getStep(b),b=g(parseFloat(b.toFixed(7))),b===K[e]?!1:(a.style[d.style]=b+"%",a.previousSibling||(l(a,U[17]),b>50&&k(a,U[17])),K[e]=b,R[e]=N.fromStepping(b),r("update",e),!0)}function A(a,b){var c,e,f;for(d.limit&&(a+=1),c=0;a>c;c+=1)e=c%2,f=b[e],null!==f&&f!==!1&&("number"==typeof f&&(f=String(f)),f=d.format.from(f),(f===!1||isNaN(f)||z(I[e],N.toStepping(f),c===3-d.dir)===!1)&&r("update",e))}function B(a){var b,c,e=h(a);for(d.dir&&d.handles>1&&e.reverse(),d.animate&&-1!==K[0]&&f(J,U[14],300),b=I.length>1?3:1,1===e.length&&(b=1),A(b,e),c=0;c<I.length;c++)r("set",c)}function C(){var a,b=[];for(a=0;a<d.handles;a+=1)b[a]=d.format.to(R[a]);return s(b)}function D(){U.forEach(function(a){a&&l(J,a)}),J.innerHTML="",delete J.noUiSlider}function E(){var a=K.map(function(a,b){var c=N.getApplicableStep(a),d=j(String(c[2])),e=R[b],f=100===a?null:c[2],g=Number((e-c[2]).toFixed(d)),h=0===a?null:g>=c[1]?c[2]:c[0]||!1;return[h,f]});return s(a)}function F(a,b){S[a]=S[a]||[],S[a].push(b),"update"===a.split(".")[0]&&I.forEach(function(a,b){r("update",b)})}function G(a){var b=a.split(".")[0],c=a.substring(b.length);Object.keys(S).forEach(function(a){var d=a.split(".")[0],e=a.substring(d.length);b&&b!==d||c&&c!==e||delete S[a]})}var H,I,J=b,K=[-1,-1],N=d.spectrum,R=[],S={};if(J.noUiSlider)throw new Error("Slider was already initialized.");return H=Q(d.dir,d.ort,J),I=P(d.handles,d.dir,H),O(d.connect,J,I),y(d.events),d.pips&&p(d.pips),{destroy:D,steps:E,on:F,off:G,get:C,set:B}}function S(a,b){if(!a.nodeName)throw new Error("noUiSlider.create requires a single element.");var c=K(b,a),d=R(a,c);d.set(c.start),a.noUiSlider=d}var T=window.navigator.pointerEnabled?{start:"pointerdown",move:"pointermove",end:"pointerup"}:window.navigator.msPointerEnabled?{start:"MSPointerDown",move:"MSPointerMove",end:"MSPointerUp"}:{start:"mousedown touchstart",move:"mousemove touchmove",end:"mouseup touchend"},U=["noUi-target","noUi-base","noUi-origin","noUi-handle","noUi-horizontal","noUi-vertical","noUi-background","noUi-connect","noUi-ltr","noUi-rtl","noUi-dragable","","noUi-state-drag","","noUi-state-tap","noUi-active","","noUi-stacking"];x.prototype.getMargin=function(a){return 2===this.xPct.length?o(this.xVal,a):!1},x.prototype.toStepping=function(a){return a=s(this.xVal,this.xPct,a),this.direction&&(a=100-a),a},x.prototype.fromStepping=function(a){return this.direction&&(a=100-a),e(t(this.xVal,this.xPct,a))},x.prototype.getStep=function(a){return this.direction&&(a=100-a),a=u(this.xPct,this.xSteps,this.snap,a),this.direction&&(a=100-a),a},x.prototype.getApplicableStep=function(a){var b=r(a,this.xPct),c=100===a?2:1;return[this.xNumSteps[b-2],this.xVal[b-c],this.xNumSteps[b-c]]},x.prototype.convert=function(a){return this.getStep(this.toStepping(a))};var V={to:function(a){return a.toFixed(2)},from:Number};return{create:S}});
/*! jQuery Address v${version} | (c) 2009, 2013 Rostislav Hristov | jquery.org/license */
(function ($) {

    $.address = (function () {

        var _trigger = function(name) {
               var e = $.extend($.Event(name), (function() {
                    var parameters = {},
                        parameterNames = $.address.parameterNames();
                    for (var i = 0, l = parameterNames.length; i < l; i++) {
                        parameters[parameterNames[i]] = $.address.parameter(parameterNames[i]);
                    }
                    return {
                        value: $.address.value(),
                        path: $.address.path(),
                        pathNames: $.address.pathNames(),
                        parameterNames: parameterNames,
                        parameters: parameters,
                        queryString: $.address.queryString()
                    };
                }).call($.address));
                $($.address).trigger(e);
                return e;
            },
            _array = function(obj) {
                return Array.prototype.slice.call(obj);
            },
            _bind = function(value, data, fn) {
                $().bind.apply($($.address), Array.prototype.slice.call(arguments));
                return $.address;
            },
            _unbind = function(value,  fn) {
                $().unbind.apply($($.address), Array.prototype.slice.call(arguments));
                return $.address;
            },
            _supportsState = function() {
                return (_h.pushState && _opts.state !== UNDEFINED);
            },
            _hrefState = function() {
                return ('/' + _l.pathname.replace(new RegExp(_opts.state), '') + 
                    _l.search + (_hrefHash() ? '#' + _hrefHash() : '')).replace(_re, '/');
            },
            _hrefHash = function() {
                var index = _l.href.indexOf('#');
                return index != -1 ? _l.href.substr(index + 1) : '';
            },
            _href = function() {
                return _supportsState() ? _hrefState() : _hrefHash();
            },
            _window = function() {
                try {
                    return top.document !== UNDEFINED && top.document.title !== UNDEFINED && top.jQuery !== UNDEFINED && 
                        top.jQuery.address !== UNDEFINED && top.jQuery.address.frames() !== false ? top : window;
                } catch (e) { 
                    return window;
                }
            },
            _js = function() {
                return 'javascript';
            },
            _strict = function(value) {
                value = value.toString();
                return (_opts.strict && value.substr(0, 1) != '/' ? '/' : '') + value;
            },
            _cssint = function(el, value) {
                return parseInt(el.css(value), 10);
            },
            _listen = function() {
                if (!_silent) {
                    var hash = _href(),
                        diff = decodeURI(_value) != decodeURI(hash);
                    if (diff) {
                        if (_msie && _version < 7) {
                            _l.reload();
                        } else {
                            if (_msie && !_hashchange && _opts.history) {
                                _st(_html, 50);
                            }
                            _value = hash;
                            _update(FALSE);
                        }
                    }
                }
            },
            _update = function(internal) {
                _st(_track, 10);
                return _trigger(CHANGE).isDefaultPrevented() || 
                    _trigger(internal ? INTERNAL_CHANGE : EXTERNAL_CHANGE).isDefaultPrevented();
            },
            _track = function() {
                if (_opts.tracker !== 'null' && _opts.tracker !== NULL) {
                    var fn = $.isFunction(_opts.tracker) ? _opts.tracker : _t[_opts.tracker],
                        value = (_l.pathname + _l.search + 
                                ($.address && !_supportsState() ? $.address.value() : ''))
                                .replace(/\/\//, '/').replace(/^\/$/, '');
                    if ($.isFunction(fn)) {
                        fn(value);
                    } else {
                      if ($.isFunction(_t.urchinTracker)) {
                        _t.urchinTracker(value);
                      }
                      if (_t.pageTracker !== UNDEFINED && $.isFunction(_t.pageTracker._trackPageview)) {
                          _t.pageTracker._trackPageview(value);
                      }
                      if (_t._gaq !== UNDEFINED && $.isFunction(_t._gaq.push)) {
                          _t._gaq.push(['_trackPageview', decodeURI(value)]);
                      }
                      if ($.isFunction(_t.ga)) {
                          _t.ga('send', 'pageview', value);
                      }
                    }
                }
            },
            _html = function() {
                var src = _js() + ':' + FALSE + ';document.open();document.writeln(\'<html><head><title>' + 
                    _d.title.replace(/\'/g, '\\\'') + '</title><script>var ' + ID + ' = "' + encodeURIComponent(_href()).replace(/\'/g, '\\\'') + 
                    (_d.domain != _l.hostname ? '";document.domain="' + _d.domain : '') + 
                    '";</' + 'script></head></html>\');document.close();';
                if (_version < 7) {
                    _frame.src = src;
                } else {
                    _frame.contentWindow.location.replace(src);
                }
            },
            _options = function() {
                if (_url && _qi != -1) {
                    var i, param, params = _url.substr(_qi + 1).split('&');
                    for (i = 0; i < params.length; i++) {
                        param = params[i].split('=');
                        if (/^(autoUpdate|history|strict|wrap)$/.test(param[0])) {
                            _opts[param[0]] = (isNaN(param[1]) ? /^(true|yes)$/i.test(param[1]) : (parseInt(param[1], 10) !== 0));
                        }
                        if (/^(state|tracker)$/.test(param[0])) {
                            _opts[param[0]] = param[1];
                        }
                    }
                    _url = NULL;
                }
                _value = _href();
            },
            _load = function() {
                if (!_loaded) {
                    _loaded = TRUE;
                    _options();
                    $('a[rel*="address:"]').address();
                    if (_opts.wrap) {
                        var body = $('body'),
                            wrap = $('body > *')
                                .wrapAll('<div style="padding:' + 
                                    (_cssint(body, 'marginTop') + _cssint(body, 'paddingTop')) + 'px ' + 
                                    (_cssint(body, 'marginRight') + _cssint(body, 'paddingRight')) + 'px ' + 
                                    (_cssint(body, 'marginBottom') + _cssint(body, 'paddingBottom')) + 'px ' + 
                                    (_cssint(body, 'marginLeft') + _cssint(body, 'paddingLeft')) + 'px;" />')
                                .parent()
                                .wrap('<div id="' + ID + '" style="height:100%;overflow:auto;position:relative;' + 
                                    (_webkit && !window.statusbar.visible ? 'resize:both;' : '') + '" />');
                        $('html, body')
                            .css({
                                height: '100%',
                                margin: 0,
                                padding: 0,
                                overflow: 'hidden'
                            });
                        if (_webkit) {
                            $('<style type="text/css" />')
                                .appendTo('head')
                                .text('#' + ID + '::-webkit-resizer { background-color: #fff; }');
                        }
                    }
                    if (_msie && !_hashchange) {
                        var frameset = _d.getElementsByTagName('frameset')[0];
                        _frame = _d.createElement((frameset ? '' : 'i') + 'frame');
                        _frame.src = _js() + ':' + FALSE;
                        if (frameset) {
                            frameset.insertAdjacentElement('beforeEnd', _frame);
                            frameset[frameset.cols ? 'cols' : 'rows'] += ',0';
                            _frame.noResize = TRUE;
                            _frame.frameBorder = _frame.frameSpacing = 0;
                        } else {
                            _frame.style.display = 'none';
                            _frame.style.width = _frame.style.height = 0;
                            _frame.tabIndex = -1;
                            _d.body.insertAdjacentElement('afterBegin', _frame);
                        }
                        _st(function() {
                            $(_frame).bind('load', function() {
                                var win = _frame.contentWindow;
                                _value = win[ID] !== UNDEFINED ? win[ID] : '';
                                if (_value != _href()) {
                                    _update(FALSE);
                                    _l.hash = _value;
                                }
                            });
                            if (_frame.contentWindow[ID] === UNDEFINED) {
                                _html();
                            }
                        }, 50);
                    }
                    _st(function() {
                        _trigger('init');
                        _update(FALSE);
                    }, 1);
                    if (!_supportsState()) {
                        if ((_msie && _version > 7) || (!_msie && _hashchange)) {
                            if (_t.addEventListener) {
                                _t.addEventListener(HASH_CHANGE, _listen, FALSE);
                            } else if (_t.attachEvent) {
                                _t.attachEvent('on' + HASH_CHANGE, _listen);
                            }
                        } else {
                            _si(_listen, 50);
                        }
                    }
                    if ('state' in window.history) {
                        $(window).trigger('popstate');
                    }
                }
            },
            _popstate = function() {
                if (decodeURI(_value) != decodeURI(_href())) {
                    _value = _href();
                    _update(FALSE);
                }
            },
            _unload = function() {
                if (_t.removeEventListener) {
                    _t.removeEventListener(HASH_CHANGE, _listen, FALSE);
                } else if (_t.detachEvent) {
                    _t.detachEvent('on' + HASH_CHANGE, _listen);
                }
            },
            _uaMatch = function(ua) {
                ua = ua.toLowerCase();
                var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
                    /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
                    /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
                    /(msie) ([\w.]+)/.exec( ua ) ||
                    ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
                    [];
                return {
                    browser: match[ 1 ] || '',
                    version: match[ 2 ] || '0'
                };
            },
            _detectBrowser = function() {
                var browser = {},
                    matched = _uaMatch(navigator.userAgent);
                if (matched.browser) {
                    browser[matched.browser] = true;
                    browser.version = matched.version;
                }
                if (browser.chrome) {
                    browser.webkit = true;
                } else if (browser.webkit) {
                    browser.safari = true;
                }
                return browser;
            },
            UNDEFINED,
            NULL = null,
            ID = 'jQueryAddress',
            STRING = 'string',
            HASH_CHANGE = 'hashchange',
            INIT = 'init',
            CHANGE = 'change',
            INTERNAL_CHANGE = 'internalChange',
            EXTERNAL_CHANGE = 'externalChange',
            TRUE = true,
            FALSE = false,
            _opts = {
                autoUpdate: TRUE, 
                history: TRUE, 
                strict: TRUE,
                frames: TRUE,
                wrap: FALSE
            },
            _browser = _detectBrowser(),
            _version = parseFloat(_browser.version),
            _webkit = _browser.webkit || _browser.safari,
            _msie = _browser.msie,
            _t = _window(),
            _d = _t.document,
            _h = _t.history, 
            _l = _t.location,
            _si = setInterval,
            _st = setTimeout,
            _re = /\/{2,9}/g,
            _agent = navigator.userAgent,
            _hashchange = 'on' + HASH_CHANGE in _t,
            _frame,
            _form,
            _url = $('script:last').attr('src'),
            _qi = _url ? _url.indexOf('?') : -1,
            _title = _d.title, 
            _silent = FALSE,
            _loaded = FALSE,
            _juststart = TRUE,
            _updating = FALSE,
            _listeners = {}, 
            _value = _href();
            
        if (_msie) {
            _version = parseFloat(_agent.substr(_agent.indexOf('MSIE') + 4));
            if (_d.documentMode && _d.documentMode != _version) {
                _version = _d.documentMode != 8 ? 7 : 8;
            }
            var pc = _d.onpropertychange;
            _d.onpropertychange = function() {
                if (pc) {
                    pc.call(_d);
                }
                if (_d.title != _title && _d.title.indexOf('#' + _href()) != -1) {
                    _d.title = _title;
                }
            };
        }
        
        if (_h.navigationMode) {
            _h.navigationMode = 'compatible';
        }
        if (document.readyState == 'complete') {
            var interval = setInterval(function() {
                if ($.address) {
                    _load();
                    clearInterval(interval);
                }
            }, 50);
        } else {
            _options();
            $(_load);
        }
        $(window).bind('popstate', _popstate).bind('unload', _unload);

        return {
            bind: function(type, data, fn) {
                return _bind.apply(this, _array(arguments));
            },
            unbind: function(type, fn) {
                return _unbind.apply(this, _array(arguments));
            },
            init: function(data, fn) {
                return _bind.apply(this, [INIT].concat(_array(arguments)));
            },
            change: function(data, fn) {
                return _bind.apply(this, [CHANGE].concat(_array(arguments)));
            },
            internalChange: function(data, fn) {
                return _bind.apply(this, [INTERNAL_CHANGE].concat(_array(arguments)));
            },
            externalChange: function(data, fn) {
                return _bind.apply(this, [EXTERNAL_CHANGE].concat(_array(arguments)));
            },
            baseURL: function() {
                var url = _l.href;
                if (url.indexOf('#') != -1) {
                    url = url.substr(0, url.indexOf('#'));
                }
                if (/\/$/.test(url)) {
                    url = url.substr(0, url.length - 1);
                }
                return url;
            },
            autoUpdate: function(value) {
                if (value !== UNDEFINED) {
                    _opts.autoUpdate = value;
                    return this;
                }
                return _opts.autoUpdate;
            },
            history: function(value) {
                if (value !== UNDEFINED) {
                    _opts.history = value;
                    return this;
                }
                return _opts.history;
            },
            state: function(value) {
                if (value !== UNDEFINED) {
                    _opts.state = value;
                    var hrefState = _hrefState();
                    if (_opts.state !== UNDEFINED) {
                        if (_h.pushState) {
                            if (hrefState.substr(0, 3) == '/#/') {
                                _l.replace(_opts.state.replace(/^\/$/, '') + hrefState.substr(2));
                            }
                        } else if (hrefState != '/' && hrefState.replace(/^\/#/, '') != _hrefHash()) {
                            _st(function() {
                                _l.replace(_opts.state.replace(/^\/$/, '') + '/#' + hrefState);
                            }, 1);
                        }
                    }
                    return this;
                }
                return _opts.state;
            },
            frames: function(value) {
                if (value !== UNDEFINED) {
                    _opts.frames = value;
                    _t = _window();
                    return this;
                }
                return _opts.frames;
            },            
            strict: function(value) {
                if (value !== UNDEFINED) {
                    _opts.strict = value;
                    return this;
                }
                return _opts.strict;
            },
            tracker: function(value) {
                if (value !== UNDEFINED) {
                    _opts.tracker = value;
                    return this;
                }
                return _opts.tracker;
            },
            wrap: function(value) {
                if (value !== UNDEFINED) {
                    _opts.wrap = value;
                    return this;
                }
                return _opts.wrap;
            },
            update: function() {
                _updating = TRUE;
                this.value(_value);
                _updating = FALSE;
                return this;
            },
            title: function(value) {
                if (value !== UNDEFINED) {
                    _st(function() {
                        _title = _d.title = value;
                        if (_juststart && _frame && _frame.contentWindow && _frame.contentWindow.document) {
                            _frame.contentWindow.document.title = value;
                            _juststart = FALSE;
                        }
                    }, 50);
                    return this;
                }
                return _d.title;
            },
            value: function(value) {
                if (value !== UNDEFINED) {
                    value = _strict(value);
                    if (value == '/') {
                        value = '';
                    }
                    if (_value == value && !_updating) {
                        return;
                    }
                    _value = value;
                    if (_opts.autoUpdate || _updating) {
                        if (_update(TRUE)) {
                            return this;
                        }
                        if (_supportsState()) {
                            _h[_opts.history ? 'pushState' : 'replaceState']({}, '', 
                                    _opts.state.replace(/\/$/, '') + (_value === '' ? '/' : _value));
                        } else {
                            _silent = TRUE;
                            if (_webkit) {
                                if (_opts.history) {
                                    _l.hash = '#' + _value;
                                } else {
                                    _l.replace('#' + _value);
                                }
                            } else if (_value != _href()) {
                                if (_opts.history) {
                                    _l.hash = '#' + _value;
                                } else {
                                    _l.replace('#' + _value);
                                }
                            }
                            if ((_msie && !_hashchange) && _opts.history) {
                                _st(_html, 50);
                            }
                            if (_webkit) {
                                _st(function(){ _silent = FALSE; }, 1);
                            } else {
                                _silent = FALSE;
                            }
                        }
                    }
                    return this;
                }
                return _strict(_value);
            },
            path: function(value) {
                if (value !== UNDEFINED) {
                    var qs = this.queryString(),
                        hash = this.hash();
                    this.value(value + (qs ? '?' + qs : '') + (hash ? '#' + hash : ''));
                    return this;
                }
                return _strict(_value).split('#')[0].split('?')[0];
            },
            pathNames: function() {
                var path = this.path(),
                    names = path.replace(_re, '/').split('/');
                if (path.substr(0, 1) == '/' || path.length === 0) {
                    names.splice(0, 1);
                }
                if (path.substr(path.length - 1, 1) == '/') {
                    names.splice(names.length - 1, 1);
                }
                return names;
            },
            queryString: function(value) {
                if (value !== UNDEFINED) {
                    var hash = this.hash();
                    this.value(this.path() + (value ? '?' + value : '') + (hash ? '#' + hash : ''));
                    return this;
                }
                var arr = _value.split('?');
                return arr.slice(1, arr.length).join('?').split('#')[0];
            },
            parameter: function(name, value, append) {
                var i, params;
                if (value !== UNDEFINED) {
                    var names = this.parameterNames();
                    params = [];
                    value = value === UNDEFINED || value === NULL ? '' : value.toString();
                    for (i = 0; i < names.length; i++) {
                        var n = names[i],
                            v = this.parameter(n);
                        if (typeof v == STRING) {
                            v = [v];
                        }
                        if (n == name) {
                            v = (value === NULL || value === '') ? [] : 
                                (append ? v.concat([value]) : [value]);
                        }
                        for (var j = 0; j < v.length; j++) {
                            params.push(n + '=' + v[j]);
                        }
                    }
                    if ($.inArray(name, names) == -1 && value !== NULL && value !== '') {
                        params.push(name + '=' + value);
                    }
                    this.queryString(params.join('&'));
                    return this;
                }
                value = this.queryString();
                if (value) {
                    var r = [];
                    params = value.split('&');
                    for (i = 0; i < params.length; i++) {
                        var p = params[i].split('=');
                        if (p[0] == name) {
                            r.push(p.slice(1).join('='));
                        }
                    }
                    if (r.length !== 0) {
                        return r.length != 1 ? r : r[0];
                    }
                }
            },
            parameterNames: function() {
                var qs = this.queryString(),
                    names = [];
                if (qs && qs.indexOf('=') != -1) {
                    var params = qs.split('&');
                    for (var i = 0; i < params.length; i++) {
                        var name = params[i].split('=')[0];
                        if ($.inArray(name, names) == -1) {
                            names.push(name);
                        }
                    }
                }
                return names;
            },
            hash: function(value) {
                if (value !== UNDEFINED) {
                    this.value(_value.split('#')[0] + (value ? '#' + value : ''));
                    return this;
                }
                var arr = _value.split('#');
                return arr.slice(1, arr.length).join('#');                
            }
        };
    })();
    
    $.fn.address = function(fn) {
        $(this).each(function(index) {
            if (!$(this).data('address')) {
                $(this).on('click', function(e) {
                    if (e.shiftKey || e.ctrlKey || e.metaKey || e.which == 2) {
                        return true;
                    }
                    var target = e.currentTarget;
                    if ($(target).is('a')) {
                        e.preventDefault();
                        var value = fn ? fn.call(target) : 
                            /address:/.test($(target).attr('rel')) ? $(target).attr('rel').split('address:')[1].split(' ')[0] : 
                            $.address.state() !== undefined && !/^\/?$/.test($.address.state()) ? 
                                    $(target).attr('href').replace(new RegExp('^(.*' + $.address.state() + '|\\.)'), '') : 
                                    $(target).attr('href').replace(/^(#\!?|\.)/, '');
                        $.address.value(value);
                    }
                }).on('submit', function(e) {
                    var target = e.currentTarget;
                    if ($(target).is('form')) {
                        e.preventDefault();
                        var action = $(target).attr('action'),
                            value = fn ? fn.call(target) : (action.indexOf('?') != -1 ? action.replace(/&$/, '') : action + '?') + 
                                $(target).serialize();
                        $.address.value(value);
                    }
                }).data('address', true);
            }
        });
        return this;
    };
    
})(jQuery);

/*! Copyright 2012, Ben Lin (http://dreamerslab.com/)
 * Licensed under the MIT License (LICENSE.txt).
 *
 * Version: 1.0.18
 *
 * Requires: jQuery >= 1.2.3
 */
(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a);
}else{a(jQuery);}}(function(a){a.fn.addBack=a.fn.addBack||a.fn.andSelf;a.fn.extend({actual:function(b,l){if(!this[b]){throw'$.actual => The jQuery method "'+b+'" you called does not exist';
}var f={absolute:false,clone:false,includeMargin:false,display:"block"};var i=a.extend(f,l);var e=this.eq(0);var h,j;if(i.clone===true){h=function(){var m="position: absolute !important; top: -1000 !important; ";
e=e.clone().attr("style",m).appendTo("body");};j=function(){e.remove();};}else{var g=[];var d="";var c;h=function(){c=e.parents().addBack().filter(":hidden");
d+="visibility: hidden !important; display: "+i.display+" !important; ";if(i.absolute===true){d+="position: absolute !important; ";}c.each(function(){var m=a(this);
var n=m.attr("style");g.push(n);m.attr("style",n?n+";"+d:d);});};j=function(){c.each(function(m){var o=a(this);var n=g[m];if(n===undefined){o.removeAttr("style");
}else{o.attr("style",n);}});};}h();var k=/(outer)/.test(b)?e[b](i.includeMargin):e[b]();j();return k;}});}));

//     Underscore.js 1.8.3
//     http://underscorejs.org
//     (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
//     Underscore may be freely distributed under the MIT license.
(function(){function n(n){function t(t,r,e,u,i,o){for(;i>=0&&o>i;i+=n){var a=u?u[i]:i;e=r(e,t[a],a,t)}return e}return function(r,e,u,i){e=b(e,i,4);var o=!k(r)&&m.keys(r),a=(o||r).length,c=n>0?0:a-1;return arguments.length<3&&(u=r[o?o[c]:c],c+=n),t(r,e,u,o,c,a)}}function t(n){return function(t,r,e){r=x(r,e);for(var u=O(t),i=n>0?0:u-1;i>=0&&u>i;i+=n)if(r(t[i],i,t))return i;return-1}}function r(n,t,r){return function(e,u,i){var o=0,a=O(e);if("number"==typeof i)n>0?o=i>=0?i:Math.max(i+a,o):a=i>=0?Math.min(i+1,a):i+a+1;else if(r&&i&&a)return i=r(e,u),e[i]===u?i:-1;if(u!==u)return i=t(l.call(e,o,a),m.isNaN),i>=0?i+o:-1;for(i=n>0?o:a-1;i>=0&&a>i;i+=n)if(e[i]===u)return i;return-1}}function e(n,t){var r=I.length,e=n.constructor,u=m.isFunction(e)&&e.prototype||a,i="constructor";for(m.has(n,i)&&!m.contains(t,i)&&t.push(i);r--;)i=I[r],i in n&&n[i]!==u[i]&&!m.contains(t,i)&&t.push(i)}var u=this,i=u._,o=Array.prototype,a=Object.prototype,c=Function.prototype,f=o.push,l=o.slice,s=a.toString,p=a.hasOwnProperty,h=Array.isArray,v=Object.keys,g=c.bind,y=Object.create,d=function(){},m=function(n){return n instanceof m?n:this instanceof m?void(this._wrapped=n):new m(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=m),exports._=m):u._=m,m.VERSION="1.8.3";var b=function(n,t,r){if(t===void 0)return n;switch(null==r?3:r){case 1:return function(r){return n.call(t,r)};case 2:return function(r,e){return n.call(t,r,e)};case 3:return function(r,e,u){return n.call(t,r,e,u)};case 4:return function(r,e,u,i){return n.call(t,r,e,u,i)}}return function(){return n.apply(t,arguments)}},x=function(n,t,r){return null==n?m.identity:m.isFunction(n)?b(n,t,r):m.isObject(n)?m.matcher(n):m.property(n)};m.iteratee=function(n,t){return x(n,t,1/0)};var _=function(n,t){return function(r){var e=arguments.length;if(2>e||null==r)return r;for(var u=1;e>u;u++)for(var i=arguments[u],o=n(i),a=o.length,c=0;a>c;c++){var f=o[c];t&&r[f]!==void 0||(r[f]=i[f])}return r}},j=function(n){if(!m.isObject(n))return{};if(y)return y(n);d.prototype=n;var t=new d;return d.prototype=null,t},w=function(n){return function(t){return null==t?void 0:t[n]}},A=Math.pow(2,53)-1,O=w("length"),k=function(n){var t=O(n);return"number"==typeof t&&t>=0&&A>=t};m.each=m.forEach=function(n,t,r){t=b(t,r);var e,u;if(k(n))for(e=0,u=n.length;u>e;e++)t(n[e],e,n);else{var i=m.keys(n);for(e=0,u=i.length;u>e;e++)t(n[i[e]],i[e],n)}return n},m.map=m.collect=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=Array(u),o=0;u>o;o++){var a=e?e[o]:o;i[o]=t(n[a],a,n)}return i},m.reduce=m.foldl=m.inject=n(1),m.reduceRight=m.foldr=n(-1),m.find=m.detect=function(n,t,r){var e;return e=k(n)?m.findIndex(n,t,r):m.findKey(n,t,r),e!==void 0&&e!==-1?n[e]:void 0},m.filter=m.select=function(n,t,r){var e=[];return t=x(t,r),m.each(n,function(n,r,u){t(n,r,u)&&e.push(n)}),e},m.reject=function(n,t,r){return m.filter(n,m.negate(x(t)),r)},m.every=m.all=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(!t(n[o],o,n))return!1}return!0},m.some=m.any=function(n,t,r){t=x(t,r);for(var e=!k(n)&&m.keys(n),u=(e||n).length,i=0;u>i;i++){var o=e?e[i]:i;if(t(n[o],o,n))return!0}return!1},m.contains=m.includes=m.include=function(n,t,r,e){return k(n)||(n=m.values(n)),("number"!=typeof r||e)&&(r=0),m.indexOf(n,t,r)>=0},m.invoke=function(n,t){var r=l.call(arguments,2),e=m.isFunction(t);return m.map(n,function(n){var u=e?t:n[t];return null==u?u:u.apply(n,r)})},m.pluck=function(n,t){return m.map(n,m.property(t))},m.where=function(n,t){return m.filter(n,m.matcher(t))},m.findWhere=function(n,t){return m.find(n,m.matcher(t))},m.max=function(n,t,r){var e,u,i=-1/0,o=-1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],e>i&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(u>o||u===-1/0&&i===-1/0)&&(i=n,o=u)});return i},m.min=function(n,t,r){var e,u,i=1/0,o=1/0;if(null==t&&null!=n){n=k(n)?n:m.values(n);for(var a=0,c=n.length;c>a;a++)e=n[a],i>e&&(i=e)}else t=x(t,r),m.each(n,function(n,r,e){u=t(n,r,e),(o>u||1/0===u&&1/0===i)&&(i=n,o=u)});return i},m.shuffle=function(n){for(var t,r=k(n)?n:m.values(n),e=r.length,u=Array(e),i=0;e>i;i++)t=m.random(0,i),t!==i&&(u[i]=u[t]),u[t]=r[i];return u},m.sample=function(n,t,r){return null==t||r?(k(n)||(n=m.values(n)),n[m.random(n.length-1)]):m.shuffle(n).slice(0,Math.max(0,t))},m.sortBy=function(n,t,r){return t=x(t,r),m.pluck(m.map(n,function(n,r,e){return{value:n,index:r,criteria:t(n,r,e)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=x(r,e),m.each(t,function(e,i){var o=r(e,i,t);n(u,e,o)}),u}};m.groupBy=F(function(n,t,r){m.has(n,r)?n[r].push(t):n[r]=[t]}),m.indexBy=F(function(n,t,r){n[r]=t}),m.countBy=F(function(n,t,r){m.has(n,r)?n[r]++:n[r]=1}),m.toArray=function(n){return n?m.isArray(n)?l.call(n):k(n)?m.map(n,m.identity):m.values(n):[]},m.size=function(n){return null==n?0:k(n)?n.length:m.keys(n).length},m.partition=function(n,t,r){t=x(t,r);var e=[],u=[];return m.each(n,function(n,r,i){(t(n,r,i)?e:u).push(n)}),[e,u]},m.first=m.head=m.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:m.initial(n,n.length-t)},m.initial=function(n,t,r){return l.call(n,0,Math.max(0,n.length-(null==t||r?1:t)))},m.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:m.rest(n,Math.max(0,n.length-t))},m.rest=m.tail=m.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},m.compact=function(n){return m.filter(n,m.identity)};var S=function(n,t,r,e){for(var u=[],i=0,o=e||0,a=O(n);a>o;o++){var c=n[o];if(k(c)&&(m.isArray(c)||m.isArguments(c))){t||(c=S(c,t,r));var f=0,l=c.length;for(u.length+=l;l>f;)u[i++]=c[f++]}else r||(u[i++]=c)}return u};m.flatten=function(n,t){return S(n,t,!1)},m.without=function(n){return m.difference(n,l.call(arguments,1))},m.uniq=m.unique=function(n,t,r,e){m.isBoolean(t)||(e=r,r=t,t=!1),null!=r&&(r=x(r,e));for(var u=[],i=[],o=0,a=O(n);a>o;o++){var c=n[o],f=r?r(c,o,n):c;t?(o&&i===f||u.push(c),i=f):r?m.contains(i,f)||(i.push(f),u.push(c)):m.contains(u,c)||u.push(c)}return u},m.union=function(){return m.uniq(S(arguments,!0,!0))},m.intersection=function(n){for(var t=[],r=arguments.length,e=0,u=O(n);u>e;e++){var i=n[e];if(!m.contains(t,i)){for(var o=1;r>o&&m.contains(arguments[o],i);o++);o===r&&t.push(i)}}return t},m.difference=function(n){var t=S(arguments,!0,!0,1);return m.filter(n,function(n){return!m.contains(t,n)})},m.zip=function(){return m.unzip(arguments)},m.unzip=function(n){for(var t=n&&m.max(n,O).length||0,r=Array(t),e=0;t>e;e++)r[e]=m.pluck(n,e);return r},m.object=function(n,t){for(var r={},e=0,u=O(n);u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},m.findIndex=t(1),m.findLastIndex=t(-1),m.sortedIndex=function(n,t,r,e){r=x(r,e,1);for(var u=r(t),i=0,o=O(n);o>i;){var a=Math.floor((i+o)/2);r(n[a])<u?i=a+1:o=a}return i},m.indexOf=r(1,m.findIndex,m.sortedIndex),m.lastIndexOf=r(-1,m.findLastIndex),m.range=function(n,t,r){null==t&&(t=n||0,n=0),r=r||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=Array(e),i=0;e>i;i++,n+=r)u[i]=n;return u};var E=function(n,t,r,e,u){if(!(e instanceof t))return n.apply(r,u);var i=j(n.prototype),o=n.apply(i,u);return m.isObject(o)?o:i};m.bind=function(n,t){if(g&&n.bind===g)return g.apply(n,l.call(arguments,1));if(!m.isFunction(n))throw new TypeError("Bind must be called on a function");var r=l.call(arguments,2),e=function(){return E(n,e,t,this,r.concat(l.call(arguments)))};return e},m.partial=function(n){var t=l.call(arguments,1),r=function(){for(var e=0,u=t.length,i=Array(u),o=0;u>o;o++)i[o]=t[o]===m?arguments[e++]:t[o];for(;e<arguments.length;)i.push(arguments[e++]);return E(n,r,this,this,i)};return r},m.bindAll=function(n){var t,r,e=arguments.length;if(1>=e)throw new Error("bindAll must be passed function names");for(t=1;e>t;t++)r=arguments[t],n[r]=m.bind(n[r],n);return n},m.memoize=function(n,t){var r=function(e){var u=r.cache,i=""+(t?t.apply(this,arguments):e);return m.has(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return r.cache={},r},m.delay=function(n,t){var r=l.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},m.defer=m.partial(m.delay,m,1),m.throttle=function(n,t,r){var e,u,i,o=null,a=0;r||(r={});var c=function(){a=r.leading===!1?0:m.now(),o=null,i=n.apply(e,u),o||(e=u=null)};return function(){var f=m.now();a||r.leading!==!1||(a=f);var l=t-(f-a);return e=this,u=arguments,0>=l||l>t?(o&&(clearTimeout(o),o=null),a=f,i=n.apply(e,u),o||(e=u=null)):o||r.trailing===!1||(o=setTimeout(c,l)),i}},m.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var f=m.now()-o;t>f&&f>=0?e=setTimeout(c,t-f):(e=null,r||(a=n.apply(i,u),e||(i=u=null)))};return function(){i=this,u=arguments,o=m.now();var f=r&&!e;return e||(e=setTimeout(c,t)),f&&(a=n.apply(i,u),i=u=null),a}},m.wrap=function(n,t){return m.partial(t,n)},m.negate=function(n){return function(){return!n.apply(this,arguments)}},m.compose=function(){var n=arguments,t=n.length-1;return function(){for(var r=t,e=n[t].apply(this,arguments);r--;)e=n[r].call(this,e);return e}},m.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},m.before=function(n,t){var r;return function(){return--n>0&&(r=t.apply(this,arguments)),1>=n&&(t=null),r}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),I=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(n){if(!m.isObject(n))return[];if(v)return v(n);var t=[];for(var r in n)m.has(n,r)&&t.push(r);return M&&e(n,t),t},m.allKeys=function(n){if(!m.isObject(n))return[];var t=[];for(var r in n)t.push(r);return M&&e(n,t),t},m.values=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},m.mapObject=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=u.length,o={},a=0;i>a;a++)e=u[a],o[e]=t(n[e],e,n);return o},m.pairs=function(n){for(var t=m.keys(n),r=t.length,e=Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},m.invert=function(n){for(var t={},r=m.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},m.functions=m.methods=function(n){var t=[];for(var r in n)m.isFunction(n[r])&&t.push(r);return t.sort()},m.extend=_(m.allKeys),m.extendOwn=m.assign=_(m.keys),m.findKey=function(n,t,r){t=x(t,r);for(var e,u=m.keys(n),i=0,o=u.length;o>i;i++)if(e=u[i],t(n[e],e,n))return e},m.pick=function(n,t,r){var e,u,i={},o=n;if(null==o)return i;m.isFunction(t)?(u=m.allKeys(o),e=b(t,r)):(u=S(arguments,!1,!1,1),e=function(n,t,r){return t in r},o=Object(o));for(var a=0,c=u.length;c>a;a++){var f=u[a],l=o[f];e(l,f,o)&&(i[f]=l)}return i},m.omit=function(n,t,r){if(m.isFunction(t))t=m.negate(t);else{var e=m.map(S(arguments,!1,!1,1),String);t=function(n,t){return!m.contains(e,t)}}return m.pick(n,t,r)},m.defaults=_(m.allKeys,!0),m.create=function(n,t){var r=j(n);return t&&m.extendOwn(r,t),r},m.clone=function(n){return m.isObject(n)?m.isArray(n)?n.slice():m.extend({},n):n},m.tap=function(n,t){return t(n),n},m.isMatch=function(n,t){var r=m.keys(t),e=r.length;if(null==n)return!e;for(var u=Object(n),i=0;e>i;i++){var o=r[i];if(t[o]!==u[o]||!(o in u))return!1}return!0};var N=function(n,t,r,e){if(n===t)return 0!==n||1/n===1/t;if(null==n||null==t)return n===t;n instanceof m&&(n=n._wrapped),t instanceof m&&(t=t._wrapped);var u=s.call(n);if(u!==s.call(t))return!1;switch(u){case"[object RegExp]":case"[object String]":return""+n==""+t;case"[object Number]":return+n!==+n?+t!==+t:0===+n?1/+n===1/t:+n===+t;case"[object Date]":case"[object Boolean]":return+n===+t}var i="[object Array]"===u;if(!i){if("object"!=typeof n||"object"!=typeof t)return!1;var o=n.constructor,a=t.constructor;if(o!==a&&!(m.isFunction(o)&&o instanceof o&&m.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1}r=r||[],e=e||[];for(var c=r.length;c--;)if(r[c]===n)return e[c]===t;if(r.push(n),e.push(t),i){if(c=n.length,c!==t.length)return!1;for(;c--;)if(!N(n[c],t[c],r,e))return!1}else{var f,l=m.keys(n);if(c=l.length,m.keys(t).length!==c)return!1;for(;c--;)if(f=l[c],!m.has(t,f)||!N(n[f],t[f],r,e))return!1}return r.pop(),e.pop(),!0};m.isEqual=function(n,t){return N(n,t)},m.isEmpty=function(n){return null==n?!0:k(n)&&(m.isArray(n)||m.isString(n)||m.isArguments(n))?0===n.length:0===m.keys(n).length},m.isElement=function(n){return!(!n||1!==n.nodeType)},m.isArray=h||function(n){return"[object Array]"===s.call(n)},m.isObject=function(n){var t=typeof n;return"function"===t||"object"===t&&!!n},m.each(["Arguments","Function","String","Number","Date","RegExp","Error"],function(n){m["is"+n]=function(t){return s.call(t)==="[object "+n+"]"}}),m.isArguments(arguments)||(m.isArguments=function(n){return m.has(n,"callee")}),"function"!=typeof/./&&"object"!=typeof Int8Array&&(m.isFunction=function(n){return"function"==typeof n||!1}),m.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},m.isNaN=function(n){return m.isNumber(n)&&n!==+n},m.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"===s.call(n)},m.isNull=function(n){return null===n},m.isUndefined=function(n){return n===void 0},m.has=function(n,t){return null!=n&&p.call(n,t)},m.noConflict=function(){return u._=i,this},m.identity=function(n){return n},m.constant=function(n){return function(){return n}},m.noop=function(){},m.property=w,m.propertyOf=function(n){return null==n?function(){}:function(t){return n[t]}},m.matcher=m.matches=function(n){return n=m.extendOwn({},n),function(t){return m.isMatch(t,n)}},m.times=function(n,t,r){var e=Array(Math.max(0,n));t=b(t,r,1);for(var u=0;n>u;u++)e[u]=t(u);return e},m.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},m.now=Date.now||function(){return(new Date).getTime()};var B={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},T=m.invert(B),R=function(n){var t=function(t){return n[t]},r="(?:"+m.keys(n).join("|")+")",e=RegExp(r),u=RegExp(r,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};m.escape=R(B),m.unescape=R(T),m.result=function(n,t,r){var e=null==n?void 0:n[t];return e===void 0&&(e=r),m.isFunction(e)?e.call(n):e};var q=0;m.uniqueId=function(n){var t=++q+"";return n?n+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var K=/(.)^/,z={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\u2028|\u2029/g,L=function(n){return"\\"+z[n]};m.template=function(n,t,r){!t&&r&&(t=r),t=m.defaults({},t,m.templateSettings);var e=RegExp([(t.escape||K).source,(t.interpolate||K).source,(t.evaluate||K).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,o,a){return i+=n.slice(u,a).replace(D,L),u=a+t.length,r?i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":e?i+="'+\n((__t=("+e+"))==null?'':__t)+\n'":o&&(i+="';\n"+o+"\n__p+='"),t}),i+="';\n",t.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var o=new Function(t.variable||"obj","_",i)}catch(a){throw a.source=i,a}var c=function(n){return o.call(this,n,m)},f=t.variable||"obj";return c.source="function("+f+"){\n"+i+"}",c},m.chain=function(n){var t=m(n);return t._chain=!0,t};var P=function(n,t){return n._chain?m(t).chain():t};m.mixin=function(n){m.each(m.functions(n),function(t){var r=m[t]=n[t];m.prototype[t]=function(){var n=[this._wrapped];return f.apply(n,arguments),P(this,r.apply(m,n))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=o[n];m.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!==n&&"splice"!==n||0!==r.length||delete r[0],P(this,r)}}),m.each(["concat","join","slice"],function(n){var t=o[n];m.prototype[n]=function(){return P(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},"function"==typeof define&&define.amd&&define("underscore",[],function(){return m})}).call(this);

//! moment.js
//! version : 2.10.3
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Dc.apply(null,arguments)}function b(a){Dc=a}function c(a){return"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function f(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function g(a,b){for(var c in b)f(b,c)&&(a[c]=b[c]);return f(b,"toString")&&(a.toString=b.toString),f(b,"valueOf")&&(a.valueOf=b.valueOf),a}function h(a,b,c,d){return za(a,b,c,d,!0).utc()}function i(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function j(a){return null==a._pf&&(a._pf=i()),a._pf}function k(a){if(null==a._isValid){var b=j(a);a._isValid=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function l(a){var b=h(0/0);return null!=a?g(j(b),a):j(b).userInvalidated=!0,b}function m(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=j(b)),"undefined"!=typeof b._locale&&(a._locale=b._locale),Fc.length>0)for(c in Fc)d=Fc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function n(b){m(this,b),this._d=new Date(+b._d),Gc===!1&&(Gc=!0,a.updateOffset(this),Gc=!1)}function o(a){return a instanceof n||null!=a&&null!=a._isAMomentObject}function p(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function q(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&p(a[d])!==p(b[d]))&&g++;return g+f}function r(){}function s(a){return a?a.toLowerCase().replace("_","-"):a}function t(a){for(var b,c,d,e,f=0;f<a.length;){for(e=s(a[f]).split("-"),b=e.length,c=s(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=u(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&q(e,c,!0)>=b-1)break;b--}f++}return null}function u(a){var b=null;if(!Hc[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Ec._abbr,require("./locale/"+a),v(b)}catch(c){}return Hc[a]}function v(a,b){var c;return a&&(c="undefined"==typeof b?x(a):w(a,b),c&&(Ec=c)),Ec._abbr}function w(a,b){return null!==b?(b.abbr=a,Hc[a]||(Hc[a]=new r),Hc[a].set(b),v(a),Hc[a]):(delete Hc[a],null)}function x(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Ec;if(!c(a)){if(b=u(a))return b;a=[a]}return t(a)}function y(a,b){var c=a.toLowerCase();Ic[c]=Ic[c+"s"]=Ic[b]=a}function z(a){return"string"==typeof a?Ic[a]||Ic[a.toLowerCase()]:void 0}function A(a){var b,c,d={};for(c in a)f(a,c)&&(b=z(c),b&&(d[b]=a[c]));return d}function B(b,c){return function(d){return null!=d?(D(this,b,d),a.updateOffset(this,c),this):C(this,b)}}function C(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function D(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function E(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=z(a),"function"==typeof this[a])return this[a](b);return this}function F(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.length<b;)d="0"+d;return(e?c?"+":"":"-")+d}function G(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Mc[a]=e),b&&(Mc[b[0]]=function(){return F(e.apply(this,arguments),b[1],b[2])}),c&&(Mc[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function H(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function I(a){var b,c,d=a.match(Jc);for(b=0,c=d.length;c>b;b++)Mc[d[b]]?d[b]=Mc[d[b]]:d[b]=H(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function J(a,b){return a.isValid()?(b=K(b,a.localeData()),Lc[b]||(Lc[b]=I(b)),Lc[b](a)):a.localeData().invalidDate()}function K(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Kc.lastIndex=0;d>=0&&Kc.test(a);)a=a.replace(Kc,c),Kc.lastIndex=0,d-=1;return a}function L(a,b,c){_c[a]="function"==typeof b?b:function(a){return a&&c?c:b}}function M(a,b){return f(_c,a)?_c[a](b._strict,b._locale):new RegExp(N(a))}function N(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function O(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=p(a)}),c=0;c<a.length;c++)ad[a[c]]=d}function P(a,b){O(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function Q(a,b,c){null!=b&&f(ad,a)&&ad[a](b,c._a,c,a)}function R(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function S(a){return this._months[a.month()]}function T(a){return this._monthsShort[a.month()]}function U(a,b,c){var d,e,f;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function V(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),R(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function W(b){return null!=b?(V(this,b),a.updateOffset(this,!0),this):C(this,"Month")}function X(){return R(this.year(),this.month())}function Y(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[cd]<0||c[cd]>11?cd:c[dd]<1||c[dd]>R(c[bd],c[cd])?dd:c[ed]<0||c[ed]>24||24===c[ed]&&(0!==c[fd]||0!==c[gd]||0!==c[hd])?ed:c[fd]<0||c[fd]>59?fd:c[gd]<0||c[gd]>59?gd:c[hd]<0||c[hd]>999?hd:-1,j(a)._overflowDayOfYear&&(bd>b||b>dd)&&(b=dd),j(a).overflow=b),a}function Z(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function $(a,b){var c=!0,d=a+"\n"+(new Error).stack;return g(function(){return c&&(Z(d),c=!1),b.apply(this,arguments)},b)}function _(a,b){kd[a]||(Z(b),kd[a]=!0)}function aa(a){var b,c,d=a._i,e=ld.exec(d);if(e){for(j(a).iso=!0,b=0,c=md.length;c>b;b++)if(md[b][1].exec(d)){a._f=md[b][0]+(e[6]||" ");break}for(b=0,c=nd.length;c>b;b++)if(nd[b][1].exec(d)){a._f+=nd[b][0];break}d.match(Yc)&&(a._f+="Z"),ta(a)}else a._isValid=!1}function ba(b){var c=od.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(aa(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ca(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function da(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function ea(a){return fa(a)?366:365}function fa(a){return a%4===0&&a%100!==0||a%400===0}function ga(){return fa(this.year())}function ha(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=Aa(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ia(a){return ha(a,this._week.dow,this._week.doy).week}function ja(){return this._week.dow}function ka(){return this._week.doy}function la(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function ma(a){var b=ha(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function na(a,b,c,d,e){var f,g,h=da(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:ea(a-1)+g}}function oa(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function pa(a,b,c){return null!=a?a:null!=b?b:c}function qa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function ra(a){var b,c,d,e,f=[];if(!a._d){for(d=qa(a),a._w&&null==a._a[dd]&&null==a._a[cd]&&sa(a),a._dayOfYear&&(e=pa(a._a[bd],d[bd]),a._dayOfYear>ea(e)&&(j(a)._overflowDayOfYear=!0),c=da(e,0,a._dayOfYear),a._a[cd]=c.getUTCMonth(),a._a[dd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[ed]&&0===a._a[fd]&&0===a._a[gd]&&0===a._a[hd]&&(a._nextDay=!0,a._a[ed]=0),a._d=(a._useUTC?da:ca).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[ed]=24)}}function sa(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=pa(b.GG,a._a[bd],ha(Aa(),1,4).year),d=pa(b.W,1),e=pa(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=pa(b.gg,a._a[bd],ha(Aa(),f,g).year),d=pa(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=na(c,d,e,g,f),a._a[bd]=h.year,a._dayOfYear=h.dayOfYear}function ta(b){if(b._f===a.ISO_8601)return void aa(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=K(b._f,b._locale).match(Jc)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(M(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),Mc[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),Q(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[ed]<=12&&b._a[ed]>0&&(j(b).bigHour=void 0),b._a[ed]=ua(b._locale,b._a[ed],b._meridiem),ra(b),Y(b)}function ua(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function va(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(0/0));for(e=0;e<a._f.length;e++)f=0,b=m({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],ta(b),k(b)&&(f+=j(b).charsLeftOver,f+=10*j(b).unusedTokens.length,j(b).score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function wa(a){if(!a._d){var b=A(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],ra(a)}}function xa(a){var b,e=a._i,f=a._f;return a._locale=a._locale||x(a._l),null===e||void 0===f&&""===e?l({nullInput:!0}):("string"==typeof e&&(a._i=e=a._locale.preparse(e)),o(e)?new n(Y(e)):(c(f)?va(a):f?ta(a):d(e)?a._d=e:ya(a),b=new n(Y(a)),b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b))}function ya(b){var f=b._i;void 0===f?b._d=new Date:d(f)?b._d=new Date(+f):"string"==typeof f?ba(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),ra(b)):"object"==typeof f?wa(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function za(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,xa(f)}function Aa(a,b,c,d){return za(a,b,c,d,!1)}function Ba(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Aa();for(d=b[0],e=1;e<b.length;++e)b[e][a](d)&&(d=b[e]);return d}function Ca(){var a=[].slice.call(arguments,0);return Ba("isBefore",a)}function Da(){var a=[].slice.call(arguments,0);return Ba("isAfter",a)}function Ea(a){var b=A(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=x(),this._bubble()}function Fa(a){return a instanceof Ea}function Ga(a,b){G(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+F(~~(a/60),2)+b+F(~~a%60,2)})}function Ha(a){var b=(a||"").match(Yc)||[],c=b[b.length-1]||[],d=(c+"").match(td)||["-",0,0],e=+(60*d[1])+p(d[2]);return"+"===d[0]?e:-e}function Ia(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(o(b)||d(b)?+b:+Aa(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Aa(b).local();return c._isUTC?Aa(b).zone(c._offset||0):Aa(b).local()}function Ja(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ka(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ha(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ja(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?$a(this,Va(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ja(this)}function La(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Ma(a){return this.utcOffset(0,a)}function Na(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ja(this),"m")),this}function Oa(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ha(this._i)),this}function Pa(a){return a=a?Aa(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Qa(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ra(){if(this._a){var a=this._isUTC?h(this._a):Aa(this._a);return this.isValid()&&q(this._a,a.toArray())>0}return!1}function Sa(){return!this._isUTC}function Ta(){return this._isUTC}function Ua(){return this._isUTC&&0===this._offset}function Va(a,b){var c,d,e,g=a,h=null;return Fa(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=ud.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:p(h[dd])*c,h:p(h[ed])*c,m:p(h[fd])*c,s:p(h[gd])*c,ms:p(h[hd])*c}):(h=vd.exec(a))?(c="-"===h[1]?-1:1,g={y:Wa(h[2],c),M:Wa(h[3],c),d:Wa(h[4],c),h:Wa(h[5],c),m:Wa(h[6],c),s:Wa(h[7],c),w:Wa(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=Ya(Aa(g.from),Aa(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Ea(g),Fa(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function Wa(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function Xa(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Ya(a,b){var c;return b=Ia(b,a),a.isBefore(b)?c=Xa(a,b):(c=Xa(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function Za(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(_(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Va(c,d),$a(this,e,a),this}}function $a(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&D(b,"Date",C(b,"Date")+g*d),h&&V(b,C(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function _a(a){var b=a||Aa(),c=Ia(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,Aa(b)))}function ab(){return new n(this)}function bb(a,b){var c;return b=z("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Aa(a),+this>+a):(c=o(a)?+a:+Aa(a),c<+this.clone().startOf(b))}function cb(a,b){var c;return b=z("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Aa(a),+a>+this):(c=o(a)?+a:+Aa(a),+this.clone().endOf(b)<c)}function db(a,b,c){return this.isAfter(a,c)&&this.isBefore(b,c)}function eb(a,b){var c;return b=z(b||"millisecond"),"millisecond"===b?(a=o(a)?a:Aa(a),+this===+a):(c=+Aa(a),+this.clone().startOf(b)<=c&&c<=+this.clone().endOf(b))}function fb(a){return 0>a?Math.ceil(a):Math.floor(a)}function gb(a,b,c){var d,e,f=Ia(a,this),g=6e4*(f.utcOffset()-this.utcOffset());return b=z(b),"year"===b||"month"===b||"quarter"===b?(e=hb(this,f),"quarter"===b?e/=3:"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:fb(e)}function hb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function ib(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function jb(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?"function"==typeof Date.prototype.toISOString?this.toDate().toISOString():J(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):J(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function kb(b){var c=J(this,b||a.defaultFormat);return this.localeData().postformat(c)}function lb(a,b){return this.isValid()?Va({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function mb(a){return this.from(Aa(),a)}function nb(a,b){return this.isValid()?Va({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function ob(a){return this.to(Aa(),a)}function pb(a){var b;return void 0===a?this._locale._abbr:(b=x(a),null!=b&&(this._locale=b),this)}function qb(){return this._locale}function rb(a){switch(a=z(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function sb(a){return a=z(a),void 0===a||"millisecond"===a?this:this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms")}function tb(){return+this._d-6e4*(this._offset||0)}function ub(){return Math.floor(+this/1e3)}function vb(){return this._offset?new Date(+this):this._d}function wb(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function xb(){return k(this)}function yb(){return g({},j(this))}function zb(){return j(this).overflow}function Ab(a,b){G(0,[a,a.length],0,b)}function Bb(a,b,c){return ha(Aa([a,11,31+b-c]),b,c).week}function Cb(a){var b=ha(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")}function Db(a){var b=ha(this,1,4).year;return null==a?b:this.add(a-b,"y")}function Eb(){return Bb(this.year(),1,4)}function Fb(){var a=this.localeData()._week;return Bb(this.year(),a.dow,a.doy)}function Gb(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}function Hb(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function Ib(a){return this._weekdays[a.day()]}function Jb(a){return this._weekdaysShort[a.day()]}function Kb(a){return this._weekdaysMin[a.day()]}function Lb(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=Aa([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Mb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Hb(a,this.localeData()),this.add(a-b,"d")):b}function Nb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Ob(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Pb(a,b){G(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Qb(a,b){return b._meridiemParse}function Rb(a){return"p"===(a+"").toLowerCase().charAt(0)}function Sb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Tb(a){G(0,[a,3],0,"millisecond")}function Ub(){return this._isUTC?"UTC":""}function Vb(){return this._isUTC?"Coordinated Universal Time":""}function Wb(a){return Aa(1e3*a)}function Xb(){return Aa.apply(null,arguments).parseZone()}function Yb(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function Zb(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b}function $b(){return this._invalidDate}function _b(a){return this._ordinal.replace("%d",a)}function ac(a){return a}function bc(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function cc(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function dc(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function ec(a,b,c,d){var e=x(),f=h().set(d,b);return e[c](f,a)}function fc(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return ec(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=ec(a,f,c,e);return g}function gc(a,b){return fc(a,b,"months",12,"month")}function hc(a,b){return fc(a,b,"monthsShort",12,"month")}function ic(a,b){return fc(a,b,"weekdays",7,"day")}function jc(a,b){return fc(a,b,"weekdaysShort",7,"day")}function kc(a,b){return fc(a,b,"weekdaysMin",7,"day")}function lc(){var a=this._data;return this._milliseconds=Rd(this._milliseconds),this._days=Rd(this._days),this._months=Rd(this._months),a.milliseconds=Rd(a.milliseconds),a.seconds=Rd(a.seconds),a.minutes=Rd(a.minutes),a.hours=Rd(a.hours),a.months=Rd(a.months),a.years=Rd(a.years),this}function mc(a,b,c,d){var e=Va(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function nc(a,b){return mc(this,a,b,1)}function oc(a,b){return mc(this,a,b,-1)}function pc(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;return g.milliseconds=d%1e3,a=fb(d/1e3),g.seconds=a%60,b=fb(a/60),g.minutes=b%60,c=fb(b/60),g.hours=c%24,e+=fb(c/24),h=fb(qc(e)),e-=fb(rc(h)),f+=fb(e/30),e%=30,h+=fb(f/12),f%=12,g.days=e,g.months=f,g.years=h,this}function qc(a){return 400*a/146097}function rc(a){return 146097*a/400}function sc(a){var b,c,d=this._milliseconds;if(a=z(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+12*qc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(rc(this._months/12)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function tc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*p(this._months/12)}function uc(a){return function(){return this.as(a)}}function vc(a){return a=z(a),this[a+"s"]()}function wc(a){return function(){return this._data[a]}}function xc(){return fb(this.days()/7)}function yc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function zc(a,b,c){var d=Va(a).abs(),e=fe(d.as("s")),f=fe(d.as("m")),g=fe(d.as("h")),h=fe(d.as("d")),i=fe(d.as("M")),j=fe(d.as("y")),k=e<ge.s&&["s",e]||1===f&&["m"]||f<ge.m&&["mm",f]||1===g&&["h"]||g<ge.h&&["hh",g]||1===h&&["d"]||h<ge.d&&["dd",h]||1===i&&["M"]||i<ge.M&&["MM",i]||1===j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,yc.apply(null,k)}function Ac(a,b){return void 0===ge[a]?!1:void 0===b?ge[a]:(ge[a]=b,!0)}function Bc(a){var b=this.localeData(),c=zc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Cc(){var a=he(this.years()),b=he(this.months()),c=he(this.days()),d=he(this.hours()),e=he(this.minutes()),f=he(this.seconds()+this.milliseconds()/1e3),g=this.asSeconds();return g?(0>g?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}var Dc,Ec,Fc=a.momentProperties=[],Gc=!1,Hc={},Ic={},Jc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,Kc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Lc={},Mc={},Nc=/\d/,Oc=/\d\d/,Pc=/\d{3}/,Qc=/\d{4}/,Rc=/[+-]?\d{6}/,Sc=/\d\d?/,Tc=/\d{1,3}/,Uc=/\d{1,4}/,Vc=/[+-]?\d{1,6}/,Wc=/\d+/,Xc=/[+-]?\d+/,Yc=/Z|[+-]\d\d:?\d\d/gi,Zc=/[+-]?\d+(\.\d{1,3})?/,$c=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,_c={},ad={},bd=0,cd=1,dd=2,ed=3,fd=4,gd=5,hd=6;G("M",["MM",2],"Mo",function(){return this.month()+1}),G("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),G("MMMM",0,0,function(a){return this.localeData().months(this,a)}),y("month","M"),L("M",Sc),L("MM",Sc,Oc),L("MMM",$c),L("MMMM",$c),O(["M","MM"],function(a,b){b[cd]=p(a)-1}),O(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[cd]=e:j(c).invalidMonth=a});var id="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),jd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),kd={};a.suppressDeprecationWarnings=!1;var ld=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,md=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],nd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],od=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=$("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),G(0,["YY",2],0,function(){return this.year()%100}),G(0,["YYYY",4],0,"year"),G(0,["YYYYY",5],0,"year"),G(0,["YYYYYY",6,!0],0,"year"),y("year","y"),L("Y",Xc),L("YY",Sc,Oc),L("YYYY",Uc,Qc),L("YYYYY",Vc,Rc),L("YYYYYY",Vc,Rc),O(["YYYY","YYYYY","YYYYYY"],bd),O("YY",function(b,c){c[bd]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return p(a)+(p(a)>68?1900:2e3)};var pd=B("FullYear",!1);G("w",["ww",2],"wo","week"),G("W",["WW",2],"Wo","isoWeek"),y("week","w"),y("isoWeek","W"),L("w",Sc),L("ww",Sc,Oc),L("W",Sc),L("WW",Sc,Oc),P(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=p(a)});var qd={dow:0,doy:6};G("DDD",["DDDD",3],"DDDo","dayOfYear"),y("dayOfYear","DDD"),L("DDD",Tc),L("DDDD",Pc),O(["DDD","DDDD"],function(a,b,c){c._dayOfYear=p(a)}),a.ISO_8601=function(){};var rd=$("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Aa.apply(null,arguments);return this>a?this:a}),sd=$("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Aa.apply(null,arguments);return a>this?this:a});Ga("Z",":"),Ga("ZZ",""),L("Z",Yc),L("ZZ",Yc),O(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ha(a)});var td=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var ud=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,vd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Va.fn=Ea.prototype;var wd=Za(1,"add"),xd=Za(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var yd=$("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});G(0,["gg",2],0,function(){return this.weekYear()%100}),G(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Ab("gggg","weekYear"),Ab("ggggg","weekYear"),Ab("GGGG","isoWeekYear"),Ab("GGGGG","isoWeekYear"),y("weekYear","gg"),y("isoWeekYear","GG"),L("G",Xc),L("g",Xc),L("GG",Sc,Oc),L("gg",Sc,Oc),L("GGGG",Uc,Qc),L("gggg",Uc,Qc),L("GGGGG",Vc,Rc),L("ggggg",Vc,Rc),P(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=p(a)}),P(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),G("Q",0,0,"quarter"),y("quarter","Q"),L("Q",Nc),O("Q",function(a,b){b[cd]=3*(p(a)-1)}),G("D",["DD",2],"Do","date"),y("date","D"),L("D",Sc),L("DD",Sc,Oc),L("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),O(["D","DD"],dd),O("Do",function(a,b){b[dd]=p(a.match(Sc)[0],10)});var zd=B("Date",!0);G("d",0,"do","day"),G("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),G("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),G("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),G("e",0,0,"weekday"),G("E",0,0,"isoWeekday"),y("day","d"),y("weekday","e"),y("isoWeekday","E"),L("d",Sc),L("e",Sc),L("E",Sc),L("dd",$c),L("ddd",$c),L("dddd",$c),P(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:j(c).invalidWeekday=a}),P(["d","e","E"],function(a,b,c,d){b[d]=p(a)});var Ad="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Bd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Cd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");G("H",["HH",2],0,"hour"),G("h",["hh",2],0,function(){return this.hours()%12||12}),Pb("a",!0),Pb("A",!1),y("hour","h"),L("a",Qb),L("A",Qb),L("H",Sc),L("h",Sc),L("HH",Sc,Oc),L("hh",Sc,Oc),O(["H","HH"],ed),O(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),O(["h","hh"],function(a,b,c){b[ed]=p(a),j(c).bigHour=!0});var Dd=/[ap]\.?m?\.?/i,Ed=B("Hours",!0);G("m",["mm",2],0,"minute"),y("minute","m"),L("m",Sc),L("mm",Sc,Oc),O(["m","mm"],fd);var Fd=B("Minutes",!1);G("s",["ss",2],0,"second"),y("second","s"),L("s",Sc),L("ss",Sc,Oc),O(["s","ss"],gd);var Gd=B("Seconds",!1);G("S",0,0,function(){return~~(this.millisecond()/100)}),G(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),Tb("SSS"),Tb("SSSS"),y("millisecond","ms"),L("S",Tc,Nc),L("SS",Tc,Oc),L("SSS",Tc,Pc),L("SSSS",Wc),O(["S","SS","SSS","SSSS"],function(a,b){b[hd]=p(1e3*("0."+a))});var Hd=B("Milliseconds",!1);G("z",0,0,"zoneAbbr"),G("zz",0,0,"zoneName");var Id=n.prototype;Id.add=wd,Id.calendar=_a,Id.clone=ab,Id.diff=gb,Id.endOf=sb,Id.format=kb,Id.from=lb,Id.fromNow=mb,Id.to=nb,Id.toNow=ob,Id.get=E,Id.invalidAt=zb,Id.isAfter=bb,Id.isBefore=cb,Id.isBetween=db,Id.isSame=eb,Id.isValid=xb,Id.lang=yd,Id.locale=pb,Id.localeData=qb,Id.max=sd,Id.min=rd,Id.parsingFlags=yb,Id.set=E,Id.startOf=rb,Id.subtract=xd,Id.toArray=wb,Id.toDate=vb,Id.toISOString=jb,Id.toJSON=jb,Id.toString=ib,Id.unix=ub,Id.valueOf=tb,Id.year=pd,Id.isLeapYear=ga,Id.weekYear=Cb,Id.isoWeekYear=Db,Id.quarter=Id.quarters=Gb,Id.month=W,Id.daysInMonth=X,Id.week=Id.weeks=la,Id.isoWeek=Id.isoWeeks=ma,Id.weeksInYear=Fb,Id.isoWeeksInYear=Eb,Id.date=zd,Id.day=Id.days=Mb,Id.weekday=Nb,Id.isoWeekday=Ob,Id.dayOfYear=oa,Id.hour=Id.hours=Ed,Id.minute=Id.minutes=Fd,Id.second=Id.seconds=Gd,Id.millisecond=Id.milliseconds=Hd,Id.utcOffset=Ka,Id.utc=Ma,Id.local=Na,Id.parseZone=Oa,Id.hasAlignedHourOffset=Pa,Id.isDST=Qa,Id.isDSTShifted=Ra,Id.isLocal=Sa,Id.isUtcOffset=Ta,Id.isUtc=Ua,Id.isUTC=Ua,Id.zoneAbbr=Ub,Id.zoneName=Vb,Id.dates=$("dates accessor is deprecated. Use date instead.",zd),Id.months=$("months accessor is deprecated. Use month instead",W),Id.years=$("years accessor is deprecated. Use year instead",pd),Id.zone=$("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",La);var Jd=Id,Kd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Ld={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},Md="Invalid date",Nd="%d",Od=/\d{1,2}/,Pd={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",
hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Qd=r.prototype;Qd._calendar=Kd,Qd.calendar=Yb,Qd._longDateFormat=Ld,Qd.longDateFormat=Zb,Qd._invalidDate=Md,Qd.invalidDate=$b,Qd._ordinal=Nd,Qd.ordinal=_b,Qd._ordinalParse=Od,Qd.preparse=ac,Qd.postformat=ac,Qd._relativeTime=Pd,Qd.relativeTime=bc,Qd.pastFuture=cc,Qd.set=dc,Qd.months=S,Qd._months=id,Qd.monthsShort=T,Qd._monthsShort=jd,Qd.monthsParse=U,Qd.week=ia,Qd._week=qd,Qd.firstDayOfYear=ka,Qd.firstDayOfWeek=ja,Qd.weekdays=Ib,Qd._weekdays=Ad,Qd.weekdaysMin=Kb,Qd._weekdaysMin=Cd,Qd.weekdaysShort=Jb,Qd._weekdaysShort=Bd,Qd.weekdaysParse=Lb,Qd.isPM=Rb,Qd._meridiemParse=Dd,Qd.meridiem=Sb,v("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===p(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=$("moment.lang is deprecated. Use moment.locale instead.",v),a.langData=$("moment.langData is deprecated. Use moment.localeData instead.",x);var Rd=Math.abs,Sd=uc("ms"),Td=uc("s"),Ud=uc("m"),Vd=uc("h"),Wd=uc("d"),Xd=uc("w"),Yd=uc("M"),Zd=uc("y"),$d=wc("milliseconds"),_d=wc("seconds"),ae=wc("minutes"),be=wc("hours"),ce=wc("days"),de=wc("months"),ee=wc("years"),fe=Math.round,ge={s:45,m:45,h:22,d:26,M:11},he=Math.abs,ie=Ea.prototype;ie.abs=lc,ie.add=nc,ie.subtract=oc,ie.as=sc,ie.asMilliseconds=Sd,ie.asSeconds=Td,ie.asMinutes=Ud,ie.asHours=Vd,ie.asDays=Wd,ie.asWeeks=Xd,ie.asMonths=Yd,ie.asYears=Zd,ie.valueOf=tc,ie._bubble=pc,ie.get=vc,ie.milliseconds=$d,ie.seconds=_d,ie.minutes=ae,ie.hours=be,ie.days=ce,ie.weeks=xc,ie.months=de,ie.years=ee,ie.humanize=Bc,ie.toISOString=Cc,ie.toString=Cc,ie.toJSON=Cc,ie.locale=pb,ie.localeData=qb,ie.toIsoString=$("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Cc),ie.lang=yd,G("X",0,0,"unix"),G("x",0,0,"valueOf"),L("x",Xc),L("X",Zc),O("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),O("x",function(a,b,c){c._d=new Date(p(a))}),a.version="2.10.3",b(Aa),a.fn=Jd,a.min=Ca,a.max=Da,a.utc=h,a.unix=Wb,a.months=gc,a.isDate=d,a.locale=v,a.invalid=l,a.duration=Va,a.isMoment=o,a.weekdays=ic,a.parseZone=Xb,a.localeData=x,a.isDuration=Fa,a.monthsShort=hc,a.weekdaysMin=kc,a.defineLocale=w,a.weekdaysShort=jc,a.normalizeUnits=z,a.relativeTimeThreshold=Ac;var je=a;return je});
//! moment.js locale configuration
//! locale : german (de)
//! author : lluchs : https://github.com/lluchs
//! author: Menelion Elensúle: https://github.com/Oire

(function (global, factory) {
   typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) :
   typeof define === 'function' && define.amd ? define(['moment'], factory) :
   factory(global.moment)
}(this, function (moment) { 'use strict';


    function processRelativeTime(number, withoutSuffix, key, isFuture) {
        var format = {
            'm': ['eine Minute', 'einer Minute'],
            'h': ['eine Stunde', 'einer Stunde'],
            'd': ['ein Tag', 'einem Tag'],
            'dd': [number + ' Tage', number + ' Tagen'],
            'M': ['ein Monat', 'einem Monat'],
            'MM': [number + ' Monate', number + ' Monaten'],
            'y': ['ein Jahr', 'einem Jahr'],
            'yy': [number + ' Jahre', number + ' Jahren']
        };
        return withoutSuffix ? format[key][0] : format[key][1];
    }

    var de = moment.defineLocale('de', {
        months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
        monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
        weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
        weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
        weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
        longDateFormat : {
            LT: 'HH:mm',
            LTS: 'HH:mm:ss',
            L : 'DD.MM.YYYY',
            LL : 'D. MMMM YYYY',
            LLL : 'D. MMMM YYYY LT',
            LLLL : 'dddd, D. MMMM YYYY LT'
        },
        calendar : {
            sameDay: '[Heute um] LT [Uhr]',
            sameElse: 'L',
            nextDay: '[Morgen um] LT [Uhr]',
            nextWeek: 'dddd [um] LT [Uhr]',
            lastDay: '[Gestern um] LT [Uhr]',
            lastWeek: '[letzten] dddd [um] LT [Uhr]'
        },
        relativeTime : {
            future : 'in %s',
            past : 'vor %s',
            s : 'ein paar Sekunden',
            m : processRelativeTime,
            mm : '%d Minuten',
            h : processRelativeTime,
            hh : '%d Stunden',
            d : processRelativeTime,
            dd : processRelativeTime,
            M : processRelativeTime,
            MM : processRelativeTime,
            y : processRelativeTime,
            yy : processRelativeTime
        },
        ordinalParse: /\d{1,2}\./,
        ordinal : '%d.',
        week : {
            dow : 1, // Monday is the first day of the week.
            doy : 4  // The week that contains Jan 4th is the first week of the year.
        }
    });

    return de;

}));
/*
 *               ~ CLNDR v1.2.14 ~
 * ==============================================
 *       https://github.com/kylestetz/CLNDR
 * ==============================================
 *  created by kyle stetz (github.com/kylestetz)
 *        &available under the MIT license
 * http://opensource.org/licenses/mit-license.php
 * ==============================================
 *
 * This is the fully-commented development version of CLNDR.
 * For the production version, check out clndr.min.js
 * at https://github.com/kylestetz/CLNDR
 *
 * This work is based on the
 * jQuery lightweight plugin boilerplate
 * Original author: @ajpiano
 * Further changes, comments: @addyosmani
 * Licensed under the MIT license
 */

(function (factory) {

	if (typeof define === 'function' && define.amd) {

		// AMD. Register as an anonymous module.
		define(['jquery', 'moment'], factory);
	} else if (typeof exports === 'object') {

		// Node/CommonJS
		factory(require('jquery'), require('moment'));
	} else {

		// Browser globals
		factory(jQuery, moment);
	}

}(function ($, moment) {

	// This is the default calendar template. This can be overridden.
	var clndrTemplate = "<div class='clndr-controls'>" +
		"<div class='clndr-control-button'><span class='clndr-previous-button'>previous</span></div><div class='month'><%= month %> <%= year %></div><div class='clndr-control-button rightalign'><span class='clndr-next-button'>next</span></div>" +
		"</div>" +
		"<table class='clndr-table' border='0' cellspacing='0' cellpadding='0'>" +
		"<thead>" +
		"<tr class='header-days'>" +
		"<% for(var i = 0; i < daysOfTheWeek.length; i++) { %>" +
		"<td class='header-day'><%= daysOfTheWeek[i] %></td>" +
		"<% } %>" +
		"</tr>" +
		"</thead>" +
		"<tbody>" +
		"<% for(var i = 0; i < numberOfRows; i++){ %>" +
		"<tr>" +
		"<% for(var j = 0; j < 7; j++){ %>" +
		"<% var d = j + i * 7; %>" +
		"<td class='<%= days[d].classes %>'><div class='day-contents'><%= days[d].day %>" +
		"</div></td>" +
		"<% } %>" +
		"</tr>" +
		"<% } %>" +
		"</tbody>" +
		"</table>";

	var pluginName = 'clndr';

	var defaults = {
		template: clndrTemplate,
		weekOffset: 0,
		startWithMonth: null,
		clickEvents: {
			click: null,
			nextMonth: null,
			previousMonth: null,
			nextYear: null,
			previousYear: null,
			today: null,
			onMonthChange: null,
			onYearChange: null
		},
		targets: {
			nextButton: 'clndr-next-button',
			previousButton: 'clndr-previous-button',
			nextYearButton: 'clndr-next-year-button',
			previousYearButton: 'clndr-previous-year-button',
			todayButton: 'clndr-today-button',
			day: 'day',
			empty: 'empty'
		},
		classes: {
			today: "today",
			event: "event",
			past: "past",
			lastMonth: "last-month",
			nextMonth: "next-month",
			adjacentMonth: "adjacent-month",
			inactive: "inactive",
			selected: "selected"
		},
		events: [],
		extras: null,
		dateParameter: 'date',
		multiDayEvents: null,
		doneRendering: null,
		render: null,
		daysOfTheWeek: null,
		showAdjacentMonths: true,
		adjacentDaysChangeMonth: false,
		ready: null,
		constraints: null,
		forceSixRows: null,
		trackSelectedDate: false,
		selectedDate: null,
		lengthOfTime: {
			months: null,
			days: null,
			interval: 1
		}
	};

	// The actual plugin constructor
	function Clndr( element, options ) {
		this.element = element;

		// merge the default options with user-provided options
		this.options = $.extend(true, {}, defaults, options);

		// if there are events, we should run them through our addMomentObjectToEvents function
		// which will add a date object that we can use to make life easier. This is only necessary
		// when events are provided on instantiation, since our setEvents function uses addMomentObjectToEvents.
		if(this.options.events.length) {
			if(this.options.multiDayEvents) {
				this.options.events = this.addMultiDayMomentObjectsToEvents(this.options.events);
			} else {
				this.options.events = this.addMomentObjectToEvents(this.options.events);
			}
		}

		// this used to be a place where we'd figure out the current month, but since
		// we want to open up support for arbitrary lengths of time we're going to
		// store the current range in addition to the current month.
		if(this.options.lengthOfTime.months || this.options.lengthOfTime.days) {
			// we want to establish intervalStart and intervalEnd, which will keep track
			// of our boundaries. Let's look at the possibilities...
			if(this.options.lengthOfTime.months) {
				// gonna go right ahead and annihilate any chance for bugs here.
				this.options.lengthOfTime.days = null;
				// the length is specified in months. Is there a start date?
				if(this.options.lengthOfTime.startDate) {
					this.intervalStart = moment(this.options.lengthOfTime.startDate).startOf('month');
				} else if(this.options.startWithMonth) {
					this.intervalStart = moment(this.options.startWithMonth).startOf('month');
				} else {
					this.intervalStart = moment().startOf('month');
				}
				// subtract a day so that we are at the end of the interval. We always
				// want intervalEnd to be inclusive.
				this.intervalEnd = moment(this.intervalStart).add(this.options.lengthOfTime.months, 'months').subtract(1, 'days');
				this.month = this.intervalStart.clone();
			} else if(this.options.lengthOfTime.days) {
				// the length is specified in days. Start date?
				if(this.options.lengthOfTime.startDate) {
					this.intervalStart = moment(this.options.lengthOfTime.startDate).startOf('day');
				} else {
					this.intervalStart = moment().weekday(0).startOf('day');
				}
				this.intervalEnd = moment(this.intervalStart).add(this.options.lengthOfTime.days - 1, 'days').endOf('day');
				this.month = this.intervalStart.clone();
			}
		} else {
			this.month = moment().startOf('month');
			this.intervalStart = moment(this.month);
			this.intervalEnd = moment(this.month).endOf('month');
		}

		if(this.options.startWithMonth) {
			this.month = moment(this.options.startWithMonth).startOf('month');
			this.intervalStart = moment(this.month);
			this.intervalEnd = moment(this.month).endOf('month');
		}

		// if we've got constraints set, make sure the interval is within them.
		if(this.options.constraints) {
			// first check if the start date exists & is later than now.
			if(this.options.constraints.startDate) {
				var startMoment = moment(this.options.constraints.startDate);
				if(this.intervalStart.isBefore(startMoment, 'month')) {
					// try to preserve the date by moving only the month...
					this.intervalStart.set('month', startMoment.month()).set('year', startMoment.year());
					this.month.set('month', startMoment.month()).set('year', startMoment.year());
				}
			}
			// make sure the intervalEnd is before the endDate
			if(this.options.constraints.endDate) {
				var endMoment = moment(this.options.constraints.endDate);
				if(this.intervalEnd.isAfter(endMoment, 'month')) {
					this.intervalEnd.set('month', endMoment.month()).set('year', endMoment.year());
					this.month.set('month', endMoment.month()).set('year', endMoment.year());
				}
			}
		}

		this._defaults = defaults;
		this._name = pluginName;

		// Some first-time initialization -> day of the week offset,
		// template compiling, making and storing some elements we'll need later,
		// & event handling for the controller.
		this.init();
	}

	Clndr.prototype.init = function () {
		// create the days of the week using moment's current language setting
		this.daysOfTheWeek = this.options.daysOfTheWeek || [];
		if(!this.options.daysOfTheWeek) {
			this.daysOfTheWeek = [];
			for(var i = 0; i < 7; i++) {
				this.daysOfTheWeek.push( moment().weekday(i).format('dd').charAt(0) );
			}
		}
		// shuffle the week if there's an offset
		if(this.options.weekOffset) {
			this.daysOfTheWeek = this.shiftWeekdayLabels(this.options.weekOffset);
		}

		// quick & dirty test to make sure rendering is possible.
		if( !$.isFunction(this.options.render) ) {
			this.options.render = null;
			if (typeof _ === 'undefined') {
				throw new Error("Underscore was not found. Please include underscore.js OR provide a custom render function.");
			}
			else {
				// we're just going ahead and using underscore here if no render method has been supplied.
				this.compiledClndrTemplate = _.template(this.options.template);
			}
		}

		// create the parent element that will hold the plugin & save it for later
		$(this.element).html("<div class='clndr'></div>");
		this.calendarContainer = $('.clndr', this.element);

		// attach event handlers for clicks on buttons/cells
		this.bindEvents();

		// do a normal render of the calendar template
		this.render();

		// if a ready callback has been provided, call it.
		if(this.options.ready) {
			this.options.ready.apply(this, []);
		}
	};

	Clndr.prototype.shiftWeekdayLabels = function(offset) {
		var days = this.daysOfTheWeek;
		for(var i = 0; i < offset; i++) {
			days.push( days.shift() );
		}
		return days;
	};

	// This is where the magic happens. Given a starting date and ending date,
	// an array of calendarDay objects is constructed that contains appropriate
	// events and classes depending on the circumstance.
	Clndr.prototype.createDaysObject = function(startDate, endDate) {
		// this array will hold numbers for the entire grid (even the blank spaces)
		var daysArray = [];
		var date = startDate.clone();
		var lengthOfInterval = endDate.diff(startDate, 'days');

		// this is a helper object so that days can resolve their classes correctly.
		// Don't use it for anything please.
		this._currentIntervalStart = startDate.clone();

		// filter the events list (if it exists) to events that are happening last month, this month and next month (within the current grid view)
		this.eventsLastMonth = [];
		this.eventsThisInterval = [];
		this.eventsNextMonth = [];

		if(this.options.events.length) {

			// EVENT PARSING
			// here are the only two cases where we don't get an event in our interval:
			// startDate | endDate   | e.start   | e.end
			// e.start   | e.end     | startDate | endDate
			this.eventsThisInterval = $(this.options.events).filter( function() {
				if(
					this._clndrEndDateObject.isBefore(startDate) ||
						this._clndrStartDateObject.isAfter(endDate)
					) {
					return false;
				} else {
					return true;
				}
			}).toArray();

			if(this.options.showAdjacentMonths) {
				var startOfLastMonth = startDate.clone().subtract(1, 'months').startOf('month');
				var endOfLastMonth = startOfLastMonth.clone().endOf('month');
				var startOfNextMonth = endDate.clone().add(1, 'months').startOf('month');
				var endOfNextMonth = startOfNextMonth.clone().endOf('month');

				this.eventsLastMonth = $(this.options.events).filter( function() {
					if(
						this._clndrEndDateObject.isBefore(startOfLastMonth) ||
							this._clndrStartDateObject.isAfter(endOfLastMonth)
						) {
						return false;
					} else {
						return true;
					}
				}).toArray();

				this.eventsNextMonth = $(this.options.events).filter( function() {
					if(
						this._clndrEndDateObject.isBefore(startOfNextMonth) ||
							this._clndrStartDateObject.isAfter(endOfNextMonth)
						) {
						return false;
					} else {
						return true;
					}
				}).toArray();
			}
		}

		// if diff is greater than 0, we'll have to fill in last days of the previous month
		// to account for the empty boxes in the grid.
		// we also need to take into account the weekOffset parameter.
		// None of this needs to happen if the interval is being specified in days rather than months.
		if(!this.options.lengthOfTime.days) {
			var diff = date.weekday() - this.options.weekOffset;
			if(diff < 0) diff += 7;

			if(this.options.showAdjacentMonths) {
				for(var i = 0; i < diff; i++) {
					var day = moment([startDate.year(), startDate.month(), i - diff + 1]);
					daysArray.push( this.createDayObject(day, this.eventsLastMonth) );
				}
			} else {
				for(var i = 0; i < diff; i++) {
					daysArray.push( this.calendarDay({
						classes: this.options.targets.empty + " " + this.options.classes.lastMonth
					}) );
				}
			}
		}

		// now we push all of the days in the interval
		var dateIterator = startDate.clone();
		while( dateIterator.isBefore(endDate) || dateIterator.isSame(endDate, 'day') ) {
			daysArray.push( this.createDayObject(dateIterator.clone(), this.eventsThisInterval) );
			dateIterator.add(1, 'days');
		}

		// ...and if there are any trailing blank boxes, fill those in
		// with the next month first days.
		// Again, we can ignore this if the interval is specified in days.
		if(!this.options.lengthOfTime.days) {
			while(daysArray.length % 7 !== 0) {
				if(this.options.showAdjacentMonths) {
					daysArray.push( this.createDayObject(dateIterator.clone(), this.eventsNextMonth) );
				} else {
					daysArray.push( this.calendarDay({
						classes: this.options.targets.empty + " " + this.options.classes.nextMonth
					}) );
				}
				dateIterator.add(1, 'days');
			}
		}

		// if we want to force six rows of calendar, now's our Last Chance to add another row.
		// if the 42 seems explicit it's because we're creating a 7-row grid and 6 rows of 7 is always 42!
		if(this.options.forceSixRows && daysArray.length !== 42 ) {
			while(daysArray.length < 42) {
				if(this.options.showAdjacentMonths) {
					daysArray.push( this.createDayObject(dateIterator.clone(), this.eventsNextMonth) );
					dateIterator.add(1, 'days');
				} else {
					daysArray.push( this.calendarDay({
						classes: this.options.targets.empty + " " + this.options.classes.nextMonth
					}) );
				}
			}
		}

		return daysArray;
	};

	Clndr.prototype.createDayObject = function(day, monthEvents) {
		var eventsToday = [];
		var now = moment();
		var self = this;

		// validate moment date
		if (!day.isValid() && day.hasOwnProperty('_d') && day._d != undefined) {
			day = moment(day._d);
		}

		var j = 0, l = monthEvents.length;
		for(j; j < l; j++) {
			// keep in mind that the events here already passed the month/year test.
			// now all we have to compare is the moment.date(), which returns the day of the month.
			var start = monthEvents[j]._clndrStartDateObject;
			var end = monthEvents[j]._clndrEndDateObject;
			// if today is the same day as start or is after the start, and
			// if today is the same day as the end or before the end ...
			// woohoo semantics!
			if( ( day.isSame(start, 'day') || day.isAfter(start, 'day') ) &&
				( day.isSame(end, 'day') || day.isBefore(end, 'day') ) ) {
				eventsToday.push( monthEvents[j] );
			}
		}

		var properties = {
			isInactive: false,
			isAdjacentMonth: false,
			isToday: false,
		};
		var extraClasses = "";

		if(now.format("YYYY-MM-DD") == day.format("YYYY-MM-DD")) {
			extraClasses += (" " + this.options.classes.today);
			properties.isToday = true;
		}
		if(day.isBefore(now, 'day')) {
			extraClasses += (" " + this.options.classes.past);
		}
		if(eventsToday.length) {
			extraClasses += (" " + this.options.classes.event);
		}
		if(!this.options.lengthOfTime.days) {
			if(this._currentIntervalStart.month() > day.month()) {
				extraClasses += (" " + this.options.classes.adjacentMonth);
				properties.isAdjacentMonth = true;

				this._currentIntervalStart.year() === day.year()
					? extraClasses += (" " + this.options.classes.lastMonth)
					: extraClasses += (" " + this.options.classes.nextMonth);

			} else if(this._currentIntervalStart.month() < day.month()) {
				extraClasses += (" " + this.options.classes.adjacentMonth);
				properties.isAdjacentMonth = true;

				this._currentIntervalStart.year() === day.year()
					? extraClasses += (" " + this.options.classes.nextMonth)
					: extraClasses += (" " + this.options.classes.lastMonth);
			}
		}

		// if there are constraints, we need to add the inactive class to the days outside of them
		if(this.options.constraints) {
			if(this.options.constraints.startDate && day.isBefore(moment( this.options.constraints.startDate ))) {
				extraClasses += (" " + this.options.classes.inactive);
				properties.isInactive = true;
			}
			if(this.options.constraints.endDate && day.isAfter(moment( this.options.constraints.endDate ))) {
				extraClasses += (" " + this.options.classes.inactive);
				properties.isInactive = true;
			}
		}

		// validate moment date
		if (!day.isValid() && day.hasOwnProperty('_d') && day._d != undefined) {
			day = moment(day._d);
		}

		// check whether the day is "selected"
		if (this.options.selectedDate && day.isSame(moment(this.options.selectedDate), 'day')) {
			extraClasses += (" " + this.options.classes.selected);
		}

		// we're moving away from using IDs in favor of classes, since when
		// using multiple calendars on a page we are technically violating the
		// uniqueness of IDs.
		extraClasses += " calendar-day-" + day.format("YYYY-MM-DD");

		// day of week
		extraClasses += " calendar-dow-" + day.weekday();

		return this.calendarDay({
			day: day.date(),
			classes: this.options.targets.day + extraClasses,
			events: eventsToday,
			date: day,
			properties: properties
		});
	};

	Clndr.prototype.render = function() {
		// get rid of the previous set of calendar parts.
		// TODO: figure out if this is the right way to ensure proper garbage collection?
		this.calendarContainer.children().remove();

		var data = {};

		if(this.options.lengthOfTime.days) {
			var days = this.createDaysObject(this.intervalStart.clone(), this.intervalEnd.clone());

			data = {
				daysOfTheWeek: this.daysOfTheWeek,
				numberOfRows: Math.ceil(days.length / 7),
				months: [],
				days: days,
				month: null,
				year: null,
				intervalStart: this.intervalStart.clone(),
				intervalEnd: this.intervalEnd.clone(),
				eventsThisInterval: this.eventsThisInterval,
				eventsLastMonth: [],
				eventsNextMonth: [],
				extras: this.options.extras
			};

		} else if(this.options.lengthOfTime.months) {

			var months = [];
			var eventsThisInterval = [];

			for(i = 0; i < this.options.lengthOfTime.months; i++) {
				var currentIntervalStart = this.intervalStart.clone().add(i, 'months');
				var currentIntervalEnd = currentIntervalStart.clone().endOf('month');
				var days = this.createDaysObject(currentIntervalStart, currentIntervalEnd);
				// save events processed for each month into a master array of events for
				// this interval
				eventsThisInterval.push(this.eventsThisInterval);
				months.push({
					month: currentIntervalStart,
					days: days
				});
			}

			data = {
				daysOfTheWeek: this.daysOfTheWeek,
				numberOfRows: _.reduce(months, function(memo, monthObj) {
					return memo + Math.ceil(monthObj.days.length / 7);
				}, 0),
				months: months,
				days: [],
				month: null,
				year: null,
				intervalStart: this.intervalStart,
				intervalEnd: this.intervalEnd,
				eventsThisInterval: eventsThisInterval,
				eventsLastMonth: this.eventsLastMonth,
				eventsNextMonth: this.eventsNextMonth,
				extras: this.options.extras
			};
		} else {
			// get an array of days and blank spaces
			var days = this.createDaysObject(this.month.clone().startOf('month'), this.month.clone().endOf('month'));
			// this is to prevent a scope/naming issue between this.month and data.month
			var currentMonth = this.month;

			var data = {
				daysOfTheWeek: this.daysOfTheWeek,
				numberOfRows: Math.ceil(days.length / 7),
				months: [],
				days: days,
				month: this.month.format('MMMM'),
				year: this.month.year(),
				eventsThisMonth: this.eventsThisInterval,
				eventsLastMonth: this.eventsLastMonth,
				eventsNextMonth: this.eventsNextMonth,
				extras: this.options.extras
			};
		}

		// render the calendar with the data above & bind events to its elements
		if(!this.options.render) {
			this.calendarContainer.html(this.compiledClndrTemplate(data));
		} else {
			this.calendarContainer.html(this.options.render.apply(this, [data]));
		}

		// if there are constraints, we need to add the 'inactive' class to the controls
		if(this.options.constraints) {
			// in the interest of clarity we're just going to remove all inactive classes and re-apply them each render.
			for(var target in this.options.targets) {
				if(target != this.options.targets.day) {
					this.element.find('.' + this.options.targets[target]).toggleClass(this.options.classes.inactive, false);
				}
			}

			var start = null;
			var end = null;

			if(this.options.constraints.startDate) {
				start = moment(this.options.constraints.startDate);
			}
			if(this.options.constraints.endDate) {
				end = moment(this.options.constraints.endDate);
			}
			// deal with the month controls first.
			// do we have room to go back?
			if(start && (start.isAfter(this.intervalStart) || start.isSame(this.intervalStart, 'day'))) {
				this.element.find('.' + this.options.targets.previousButton).toggleClass(this.options.classes.inactive, true);
			}
			// do we have room to go forward?
			if(end && (end.isBefore(this.intervalEnd) || end.isSame(this.intervalEnd, 'day'))) {
				this.element.find('.' + this.options.targets.nextButton).toggleClass(this.options.classes.inactive, true);
			}
			// what's last year looking like?
			if(start && start.isAfter(this.intervalStart.clone().subtract(1, 'years')) ) {
				this.element.find('.' + this.options.targets.previousYearButton).toggleClass(this.options.classes.inactive, true);
			}
			// how about next year?
			if(end && end.isBefore(this.intervalEnd.clone().add(1, 'years')) ) {
				this.element.find('.' + this.options.targets.nextYearButton).toggleClass(this.options.classes.inactive, true);
			}
			// today? we could put this in init(), but we want to support the user changing the constraints on a living instance.
			if(( start && start.isAfter( moment(), 'month' ) ) || ( end && end.isBefore( moment(), 'month' ) )) {
				this.element.find('.' + this.options.targets.today).toggleClass(this.options.classes.inactive, true);
			}
		}

		if(this.options.doneRendering) {
			this.options.doneRendering.apply(this, []);
		}
	};

	Clndr.prototype.bindEvents = function() {
		var $container = $(this.element);
		var self = this;
		var eventType = 'click';
		if (self.options.useTouchEvents === true) {
			eventType = 'touchstart';
		}

		// target the day elements and give them click events
		$container.on(eventType +'.clndr', '.'+this.options.targets.day, function(event) {
			if(self.options.clickEvents.click) {
				var target = self.buildTargetObject(event.currentTarget, true);
				self.options.clickEvents.click.apply(self, [target]);
			}
			// if adjacentDaysChangeMonth is on, we need to change the month here.
			if(self.options.adjacentDaysChangeMonth) {
				if($(event.currentTarget).is( '.' + self.options.classes.lastMonth )) {
					self.backActionWithContext(self);
				} else if($(event.currentTarget).is( '.' + self.options.classes.nextMonth )) {
					self.forwardActionWithContext(self);
				}
			}
			// if trackSelectedDate is on, we need to handle click on a new day
			if (self.options.trackSelectedDate) {
				// remember new selected date
				self.options.selectedDate = self.getTargetDateString(event.currentTarget);

				// handle "selected" class
				$(event.currentTarget)
					.siblings().removeClass(self.options.classes.selected).end()
					.addClass(self.options.classes.selected);
			}
		});
		// target the empty calendar boxes as well
		$container.on(eventType +'.clndr', '.'+this.options.targets.empty, function(event) {
			if(self.options.clickEvents.click) {
				var target = self.buildTargetObject(event.currentTarget, false);
				self.options.clickEvents.click.apply(self, [target]);
			}
			if(self.options.adjacentDaysChangeMonth) {
				if($(event.currentTarget).is( '.' + self.options.classes.lastMonth )) {
					self.backActionWithContext(self);
				} else if($(event.currentTarget).is( '.' + self.options.classes.nextMonth )) {
					self.forwardActionWithContext(self);
				}
			}
		});

		// bind the previous, next and today buttons
		$container
			.on(eventType +'.clndr', '.'+this.options.targets.previousButton, { context: this }, this.backAction)
			.on(eventType +'.clndr', '.'+this.options.targets.nextButton, { context: this }, this.forwardAction)
			.on(eventType +'.clndr', '.'+this.options.targets.todayButton, { context: this }, this.todayAction)
			.on(eventType +'.clndr', '.'+this.options.targets.nextYearButton, { context: this }, this.nextYearAction)
			.on(eventType +'.clndr', '.'+this.options.targets.previousYearButton, { context: this }, this.previousYearAction);
	}

	// If the user provided a click callback we'd like to give them something nice to work with.
	// buildTargetObject takes the DOM element that was clicked and returns an object with
	// the DOM element, events, and the date (if the latter two exist). Currently it is based on the id,
	// however it'd be nice to use a data- attribute in the future.
	Clndr.prototype.buildTargetObject = function(currentTarget, targetWasDay) {
		// This is our default target object, assuming we hit an empty day with no events.
		var target = {
			element: currentTarget,
			events: [],
			date: null
		};
		// did we click on a day or just an empty box?
		if(targetWasDay) {
			var dateString = this.getTargetDateString(currentTarget);
			target.date = (dateString) ? moment(dateString) : null;

			// do we have events?
			if(this.options.events) {
				// are any of the events happening today?
				if(this.options.multiDayEvents) {
					target.events = $.makeArray( $(this.options.events).filter( function() {
						// filter the dates down to the ones that match.
						return ( ( target.date.isSame(this._clndrStartDateObject, 'day') || target.date.isAfter(this._clndrStartDateObject, 'day') ) &&
							( target.date.isSame(this._clndrEndDateObject, 'day') || target.date.isBefore(this._clndrEndDateObject, 'day') ) );
					}) );
				} else {
					target.events = $.makeArray( $(this.options.events).filter( function() {
						// filter the dates down to the ones that match.
						return this._clndrStartDateObject.format('YYYY-MM-DD') == dateString;
					}) );
				}
			}
		}

		return target;
	}

	// get moment date object of the date associated with the given target.
	// this method is meant to be called on ".day" elements.
	Clndr.prototype.getTargetDateString = function(target) {
		// Our identifier is in the list of classNames. Find it!
		var classNameIndex = target.className.indexOf('calendar-day-');
		if(classNameIndex !== -1) {
			// our unique identifier is always 23 characters long.
			// If this feels a little wonky, that's probably because it is.
			// Open to suggestions on how to improve this guy.
			return target.className.substring(classNameIndex + 13, classNameIndex + 23);
		}

		return null;
	}

	// the click handlers in bindEvents need a context, so these are wrappers
	// to the actual functions. Todo: better way to handle this?
	Clndr.prototype.forwardAction = function(event) {
		var self = event.data.context;
		self.forwardActionWithContext(self);
	};

	Clndr.prototype.backAction = function(event) {
		var self = event.data.context;
		self.backActionWithContext(self);
	};

	// These are called directly, except for in the bindEvent click handlers,
	// where forwardAction and backAction proxy to these guys.
	Clndr.prototype.backActionWithContext = function(self) {
		// before we do anything, check if there is an inactive class on the month control.
		// if it does, we want to return and take no action.
		if(self.element.find('.' + self.options.targets.previousButton).hasClass('inactive')) {
			return;
		}

		var yearChanged = null;

		if(!self.options.lengthOfTime.days) {
			// shift the interval by a month (or several months)
			self.intervalStart.subtract(self.options.lengthOfTime.interval, 'months').startOf('month');
			self.intervalEnd = self.intervalStart.clone().add(self.options.lengthOfTime.months || self.options.lengthOfTime.interval, 'months').subtract(1, 'days').endOf('month');

			if(!self.options.lengthOfTime.months) {
				yearChanged = !self.month.isSame( moment(self.month).subtract(1, 'months'), 'year');
			}

			self.month = self.intervalStart.clone();
		} else {
			// shift the interval in days
			self.intervalStart.subtract(self.options.lengthOfTime.interval, 'days').startOf('day');
			self.intervalEnd = self.intervalStart.clone().add(self.options.lengthOfTime.days - 1, 'days').endOf('day');
			// this is useless, i think, but i'll keep it as a precaution for now
			self.month = self.intervalStart.clone();
		}

		self.render();

		if(!self.options.lengthOfTime.days && !self.options.lengthOfTime.months) {
			if(self.options.clickEvents.previousMonth) {
				self.options.clickEvents.previousMonth.apply( self, [moment(self.month)] );
			}
			if(self.options.clickEvents.onMonthChange) {
				self.options.clickEvents.onMonthChange.apply( self, [moment(self.month)] );
			}
			if(yearChanged) {
				if(self.options.clickEvents.onYearChange) {
					self.options.clickEvents.onYearChange.apply( self, [moment(self.month)] );
				}
			}
		} else {
			if(self.options.clickEvents.previousInterval) {
				self.options.clickEvents.previousInterval.apply( self, [moment(self.intervalStart), moment(self.intervalEnd)] );
			}
			if(self.options.clickEvents.onIntervalChange) {
				self.options.clickEvents.onIntervalChange.apply( self, [moment(self.intervalStart), moment(self.intervalEnd)] );
			}
		}
	};

	Clndr.prototype.forwardActionWithContext = function(self) {
		// before we do anything, check if there is an inactive class on the month control.
		// if it does, we want to return and take no action.
		if(self.element.find('.' + self.options.targets.nextButton).hasClass('inactive')) {
			return;
		}

		var yearChanged = null;

		if(!self.options.lengthOfTime.days) {
			// shift the interval by a month (or several months)
			self.intervalStart.add(self.options.lengthOfTime.interval, 'months').startOf('month');
			self.intervalEnd = self.intervalStart.clone().add(self.options.lengthOfTime.months || self.options.lengthOfTime.interval, 'months').subtract(1, 'days').endOf('month');

			if(!self.options.lengthOfTime.months) {
				yearChanged = !self.month.isSame( moment(self.month).add(1, 'months'), 'year');
			}

			self.month = self.intervalStart.clone();
		} else {
			// shift the interval in days
			self.intervalStart.add(self.options.lengthOfTime.interval, 'days').startOf('day');
			self.intervalEnd = self.intervalStart.clone().add(self.options.lengthOfTime.days - 1, 'days').endOf('day');
			// this is useless, i think, but i'll keep it as a precaution for now
			self.month = self.intervalStart.clone();
		}

		self.render();

		if(!self.options.lengthOfTime.days && !self.options.lengthOfTime.months) {
			if(self.options.clickEvents.previousMonth) {
				self.options.clickEvents.previousMonth.apply( self, [moment(self.month)] );
			}
			if(self.options.clickEvents.onMonthChange) {
				self.options.clickEvents.onMonthChange.apply( self, [moment(self.month)] );
			}
			if(yearChanged) {
				if(self.options.clickEvents.onYearChange) {
					self.options.clickEvents.onYearChange.apply( self, [moment(self.month)] );
				}
			}
		} else {
			if(self.options.clickEvents.nextInterval) {
				self.options.clickEvents.nextInterval.apply( self, [moment(self.intervalStart), moment(self.intervalEnd)] );
			}
			if(self.options.clickEvents.onIntervalChange) {
				self.options.clickEvents.onIntervalChange.apply( self, [moment(self.intervalStart), moment(self.intervalEnd)] );
			}
		}
	};

	Clndr.prototype.todayAction = function(event) {
		var self = event.data.context;

		// did we switch months when the today button was hit?
		var monthChanged = !self.month.isSame(moment(), 'month');
		var yearChanged = !self.month.isSame(moment(), 'year');

		self.month = moment().startOf('month');

		if(self.options.lengthOfTime.days) {
			// if there was a startDate specified, we should figure out what the weekday is and
			// use that as the starting point of our interval. If not, go to today.weekday(0)
			if(self.options.lengthOfTime.startDate) {
				self.intervalStart = moment().weekday(self.options.lengthOfTime.startDate.weekday()).startOf('day');
			} else {
				self.intervalStart = moment().weekday(0).startOf('day');
			}
			self.intervalEnd = self.intervalStart.clone().add(self.options.lengthOfTime.days - 1, 'days').endOf('day');

		} else if(self.options.lengthOfTime.months) {
			// set the intervalStart to this month.
			self.intervalStart = moment().startOf('month');
			self.intervalEnd = self.intervalStart.clone().add(self.options.lengthOfTime.months || self.options.lengthOfTime.interval, 'months').subtract(1, 'days').endOf('month');
		} else if(monthChanged) {
			// no need to re-render if we didn't change months.
			self.render();

			// fire the today event handler regardless of whether the month changed.
			if(self.options.clickEvents.today) {
				self.options.clickEvents.today.apply( self, [moment(self.month)] );
			}

			// fire the onMonthChange callback
			if(self.options.clickEvents.onMonthChange) {
				self.options.clickEvents.onMonthChange.apply( self, [moment(self.month)] );
			}
			// maybe fire the onYearChange callback?
			if(yearChanged) {
				if(self.options.clickEvents.onYearChange) {
					self.options.clickEvents.onYearChange.apply( self, [moment(self.month)] );
				}
			}
		}

		if(self.options.lengthOfTime.days || self.options.lengthOfTime.months) {
			self.render();
			// fire the today event handler regardless of whether the month changed.
			if(self.options.clickEvents.today) {
				self.options.clickEvents.today.apply( self, [moment(self.month)] );
			}
			if(self.options.clickEvents.onIntervalChange) {
				self.options.clickEvents.onIntervalChange.apply( self, [moment(self.intervalStart), moment(self.intervalEnd)] );
			}
		}
	};

	Clndr.prototype.nextYearAction = function(event) {
		var self = event.data.context;
		// before we do anything, check if there is an inactive class on the month control.
		// if it does, we want to return and take no action.
		if(self.element.find('.' + self.options.targets.nextYearButton).hasClass('inactive')) {
			return;
		}

		self.month.add(1, 'years');
		self.intervalStart.add(1, 'years');
		self.intervalEnd.add(1, 'years');

		self.render();

		if(self.options.clickEvents.nextYear) {
			self.options.clickEvents.nextYear.apply( self, [moment(self.month)] );
		}
		if(self.options.lengthOfTime.days || self.options.lengthOfTime.months) {
			if(self.options.clickEvents.onIntervalChange) {
				self.options.clickEvents.onIntervalChange.apply( self, [moment(self.intervalStart), moment(self.intervalEnd)] );
			}
		} else {
			if(self.options.clickEvents.onMonthChange) {
				self.options.clickEvents.onMonthChange.apply( self, [moment(self.month)] );
			}
			if(self.options.clickEvents.onYearChange) {
				self.options.clickEvents.onYearChange.apply( self, [moment(self.month)] );
			}
		}
	};

	Clndr.prototype.previousYearAction = function(event) {
		var self = event.data.context;
		// before we do anything, check if there is an inactive class on the month control.
		// if it does, we want to return and take no action.
		console.log(self.element.find('.' + self.options.targets.previousYear));
		if(self.element.find('.' + self.options.targets.previousYearButton).hasClass('inactive')) {
			return;
		}

		self.month.subtract(1, 'years');
		self.intervalStart.subtract(1, 'years');
		self.intervalEnd.subtract(1, 'years');

		self.render();

		if(self.options.clickEvents.previousYear) {
			self.options.clickEvents.previousYear.apply( self, [moment(self.month)] );
		}
		if(self.options.lengthOfTime.days || self.options.lengthOfTime.months) {
			if(self.options.clickEvents.onIntervalChange) {
				self.options.clickEvents.onIntervalChange.apply( self, [moment(self.intervalStart), moment(self.intervalEnd)] );
			}
		} else {
			if(self.options.clickEvents.onMonthChange) {
				self.options.clickEvents.onMonthChange.apply( self, [moment(self.month)] );
			}
			if(self.options.clickEvents.onYearChange) {
				self.options.clickEvents.onYearChange.apply( self, [moment(self.month)] );
			}
		}
	};

	Clndr.prototype.forward = function(options) {
		if(!this.options.lengthOfTime.days) {
			// shift the interval by a month (or several months)
			this.intervalStart.add(this.options.lengthOfTime.interval, 'months').startOf('month');
			this.intervalEnd = this.intervalStart.clone().add(this.options.lengthOfTime.months || this.options.lengthOfTime.interval, 'months').subtract(1, 'days').endOf('month');
			this.month = this.intervalStart.clone();
		} else {
			// shift the interval in days
			this.intervalStart.add(this.options.lengthOfTime.interval, 'days').startOf('day');
			this.intervalEnd = this.intervalStart.clone().add(this.options.lengthOfTime.days - 1, 'days').endOf('day');
			this.month = this.intervalStart.clone();
		}

		this.render();

		if(options && options.withCallbacks) {
			if(this.options.lengthOfTime.days || this.options.lengthOfTime.months) {
				if(this.options.clickEvents.onIntervalChange) {
					this.options.clickEvents.onIntervalChange.apply( this, [moment(this.intervalStart), moment(this.intervalEnd)] );
				}
			} else {
				if(this.options.clickEvents.onMonthChange) {
					this.options.clickEvents.onMonthChange.apply( this, [moment(this.month)] );
				}
				// We entered a new year
				if (this.month.month() === 0 && this.options.clickEvents.onYearChange) {
					this.options.clickEvents.onYearChange.apply( this, [moment(this.month)] );
				}
			}
		}

		return this;
	}

	Clndr.prototype.back = function(options) {
		if(!this.options.lengthOfTime.days) {
			// shift the interval by a month (or several months)
			this.intervalStart.subtract(this.options.lengthOfTime.interval, 'months').startOf('month');
			this.intervalEnd = this.intervalStart.clone().add(this.options.lengthOfTime.months || this.options.lengthOfTime.interval, 'months').subtract(1, 'days').endOf('month');
			this.month = this.intervalStart.clone();
		} else {
			// shift the interval in days
			this.intervalStart.subtract(this.options.lengthOfTime.interval, 'days').startOf('day');
			this.intervalEnd = this.intervalStart.clone().add(this.options.lengthOfTime.days - 1, 'days').endOf('day');
			this.month = this.intervalStart.clone();
		}

		this.render();

		if(options && options.withCallbacks) {
			if(this.options.lengthOfTime.days || this.options.lengthOfTime.months) {
				if(this.options.clickEvents.onIntervalChange) {
					this.options.clickEvents.onIntervalChange.apply( this, [moment(this.intervalStart), moment(this.intervalEnd)] );
				}
			} else {
				if(this.options.clickEvents.onMonthChange) {
					this.options.clickEvents.onMonthChange.apply( this, [moment(this.month)] );
				}
				// We went all the way back to previous year
				if (this.month.month() === 11 && this.options.clickEvents.onYearChange) {
					this.options.clickEvents.onYearChange.apply( this, [moment(this.month)] );
				}
			}
		}

		return this;
	}

	// alternate names for convenience
	Clndr.prototype.next = function(options) {
		this.forward(options);
		return this;
	}

	Clndr.prototype.previous = function(options) {
		this.back(options);
		return this;
	}

	Clndr.prototype.setMonth = function(newMonth, options) {
		// accepts 0 - 11 or a full/partial month name e.g. "Jan", "February", "Mar"
		if(!this.options.lengthOfTime.days && !this.options.lengthOfTime.months) {
			this.month.month(newMonth);
			this.intervalStart = this.month.clone().startOf('month');
			this.intervalEnd = this.intervalStart.clone().endOf('month');
			this.render();
			if(options && options.withCallbacks) {
				if(this.options.clickEvents.onMonthChange) {
					this.options.clickEvents.onMonthChange.apply( this, [moment(this.month)] );
				}
			}
		} else {
			console.log('You are using a custom date interval; use Clndr.setIntervalStart(startDate) instead.');
		}
		return this;
	}

	Clndr.prototype.setIntervalStart = function(newDate, options) {
		// accepts a date string or moment object
		if(this.options.lengthOfTime.days) {
			this.intervalStart = moment(newDate).startOf('day');
			this.intervalEnd = this.intervalStart.clone().add(this.options.lengthOfTime.days - 1, 'days').endOf('day');
		} else if(this.options.lengthOfTime.months) {
			this.intervalStart = moment(newDate).startOf('month');
			this.intervalEnd = this.intervalStart.clone().add(this.options.lengthOfTime.months || this.options.lengthOfTime.interval, 'months').subtract(1, 'days').endOf('month');
			this.month = this.intervalStart.clone();
		}

		if(this.options.lengthOfTime.days || this.options.lengthOfTime.months) {
			this.render();

			if(options && options.withCallbacks) {
				if(this.options.clickEvents.onIntervalChange) {
					this.options.clickEvents.onIntervalChange.apply( this, [moment(this.intervalStart), moment(this.intervalEnd)] );
				}
			}
		} else {
			console.log('You are using a custom date interval; use Clndr.setIntervalStart(startDate) instead.');
		}
		return this;
	}

	Clndr.prototype.nextYear = function(options) {
		this.month.add(1, 'year');
		this.intervalStart.add(1, 'year');
		this.intervalEnd.add(1, 'year');
		this.render();
		if(options && options.withCallbacks) {
			if(this.options.clickEvents.onYearChange) {
				this.options.clickEvents.onYearChange.apply( this, [moment(this.month)] );
			}
			if(this.options.clickEvents.onIntervalChange) {
				this.options.clickEvents.onIntervalChange.apply( this, [moment(this.intervalStart), moment(this.intervalEnd)] );
			}
		}
		return this;
	}

	Clndr.prototype.previousYear = function(options) {
		this.month.subtract(1, 'year');
		this.intervalStart.subtract(1, 'year');
		this.intervalEnd.subtract(1, 'year');
		this.render();
		if(options && options.withCallbacks) {
			if(this.options.clickEvents.onYearChange) {
				this.options.clickEvents.onYearChange.apply( this, [moment(this.month)] );
			}
			if(this.options.clickEvents.onIntervalChange) {
				this.options.clickEvents.onIntervalChange.apply( this, [moment(this.intervalStart), moment(this.intervalEnd)] );
			}
		}
		return this;
	}

	Clndr.prototype.setYear = function(newYear, options) {
		this.month.year(newYear);
		this.intervalStart.year(newYear);
		this.intervalEnd.year(newYear);
		this.render();
		if(options && options.withCallbacks) {
			if(this.options.clickEvents.onYearChange) {
				this.options.clickEvents.onYearChange.apply( this, [moment(this.month)] );
			}
			if(this.options.clickEvents.onIntervalChange) {
				this.options.clickEvents.onIntervalChange.apply( this, [moment(this.intervalStart), moment(this.intervalEnd)] );
			}
		}
		return this;
	}

	Clndr.prototype.setEvents = function(events) {
		// go through each event and add a moment object
		if(this.options.multiDayEvents) {
			this.options.events = this.addMultiDayMomentObjectsToEvents(events);
		} else {
			this.options.events = this.addMomentObjectToEvents(events);
		}

		this.render();
		return this;
	};

	Clndr.prototype.addEvents = function(events) {
		// go through each event and add a moment object
		if(this.options.multiDayEvents) {
			this.options.events = $.merge(this.options.events, this.addMultiDayMomentObjectsToEvents(events));
		} else {
			this.options.events = $.merge(this.options.events, this.addMomentObjectToEvents(events));
		}

		this.render();
		return this;
	};

	Clndr.prototype.removeEvents = function(matchingFunction) {
		for (var i = this.options.events.length-1; i >= 0; i--) {
			if(matchingFunction(this.options.events[i]) == true) {
				this.options.events.splice(i, 1);
			}
		}

		this.render();
		return this;
	};

	Clndr.prototype.addMomentObjectToEvents = function(events) {
		var self = this;
		var i = 0, l = events.length;
		for(i; i < l; i++) {
			// add the date as both start and end, since it's a single-day event by default
			events[i]._clndrStartDateObject = moment( events[i][self.options.dateParameter] );
			events[i]._clndrEndDateObject = moment( events[i][self.options.dateParameter] );
		}
		return events;
	}

	Clndr.prototype.addMultiDayMomentObjectsToEvents = function(events) {
		var self = this;
		var i = 0, l = events.length;
		for(i; i < l; i++) {
			// if we don't find the startDate OR endDate fields, look for singleDay
			if(!events[i][self.options.multiDayEvents.endDate] && !events[i][self.options.multiDayEvents.startDate]) {
				events[i]._clndrEndDateObject = moment( events[i][self.options.multiDayEvents.singleDay] );
				events[i]._clndrStartDateObject = moment( events[i][self.options.multiDayEvents.singleDay] );
			} else {
				// otherwise use startDate and endDate, or whichever one is present.
				events[i]._clndrEndDateObject = moment( events[i][self.options.multiDayEvents.endDate] || events[i][self.options.multiDayEvents.startDate] );
				events[i]._clndrStartDateObject = moment( events[i][self.options.multiDayEvents.startDate] || events[i][self.options.multiDayEvents.endDate] );
			}
		}
		return events;
	}

	Clndr.prototype.calendarDay = function(options) {
		var defaults = { day: "", classes: this.options.targets.empty, events: [], date: null };
		return $.extend({}, defaults, options);
	}

	$.fn.clndr = function(options) {
		if(this.length === 1) {
			if(!this.data('plugin_clndr')) {
				var clndr_instance = new Clndr(this, options);
				this.data('plugin_clndr', clndr_instance);
				return clndr_instance;
			}
		} else if(this.length > 1) {
			throw new Error("CLNDR does not support multiple elements yet. Make sure your clndr selector returns only one element.");
		}
	}

}));
/*! Tablesaw - v1.0.4 - 2015-02-19
* https://github.com/filamentgroup/tablesaw
* Copyright (c) 2015 Filament Group; Licensed MIT */
;(function( $ ) {
	var div = document.createElement('div'),
		all = div.getElementsByTagName('i'),
		$doc = $( document.documentElement );

	div.innerHTML = '<!--[if lte IE 8]><i></i><![endif]-->';
	if( all[ 0 ] ) {
		$doc.addClass( 'ie-lte8' );
	}

	// Cut the mustard
	if( !( 'querySelector' in document ) ||
			( window.blackberry && !window.WebKitPoint ) ||
			window.operamini ) {
		return;
	} else {
		$doc.addClass( 'tablesaw-enhanced' );

		// DOM-ready auto-init of plugins.
		// Many plugins bind to an "enhance" event to init themselves on dom ready, or when new markup is inserted into the DOM
		$( function(){
			$( document ).trigger( "enhance.tablesaw" );
		});
	}

})( jQuery );
/*
* tablesaw: A set of plugins for responsive tables
* Stack and Column Toggle tables
* Copyright (c) 2013 Filament Group, Inc.
* MIT License
*/

if( typeof Tablesaw === "undefined" ) {
	Tablesaw = {
		i18n: {
			modes: [ 'Stack', 'Swipe', 'Toggle' ],
			columns: 'Col<span class=\"a11y-sm\">umn</span>s',
			columnBtnText: 'Columns',
			columnsDialogError: 'No eligible columns.',
			sort: 'Sort'
		}
	};
}
if( !Tablesaw.config ) {
	Tablesaw.config = {};
}

;(function( $ ) {
	var pluginName = "table",
		classes = {
			toolbar: "tablesaw-bar"
		},
		events = {
			create: "tablesawcreate",
			destroy: "tablesawdestroy",
			refresh: "tablesawrefresh"
		},
		defaultMode = "stack",
		initSelector = "table[data-tablesaw-mode],table[data-tablesaw-sortable]";

	var Table = function( element ) {
		if( !element ) {
			throw new Error( "Tablesaw requires an element." );
		}

		this.table = element;
		this.$table = $( element );

		this.mode = this.$table.attr( "data-tablesaw-mode" ) || defaultMode;

		this.init();
	};

	Table.prototype.init = function() {
		// assign an id if there is none
		if ( !this.$table.attr( "id" ) ) {
			this.$table.attr( "id", pluginName + "-" + Math.round( Math.random() * 10000 ) );
		}

		this.createToolbar();

		var colstart = this._initCells();

		this.$table.trigger( events.create, [ this, colstart ] );
	};

	Table.prototype._initCells = function() {
		var colstart,
			thrs = this.table.querySelectorAll( "thead tr" ),
			self = this;

		$( thrs ).each( function(){
			var coltally = 0;

			$( this ).children().each( function(){
				var span = parseInt( this.getAttribute( "colspan" ), 10 ),
					sel = ":nth-child(" + ( coltally + 1 ) + ")";

				colstart = coltally + 1;

				if( span ){
					for( var k = 0; k < span - 1; k++ ){
						coltally++;
						sel += ", :nth-child(" + ( coltally + 1 ) + ")";
					}
				}

				// Store "cells" data on header as a reference to all cells in the same column as this TH
				this.cells = self.$table.find("tr").not( $( thrs ).eq( 0 ) ).not( this ).children( sel );
				coltally++;
			});
		});

		return colstart;
	};

	Table.prototype.refresh = function() {
		this._initCells();

		this.$table.trigger( events.refresh );
	};

	Table.prototype.createToolbar = function() {
		// Insert the toolbar
		// TODO move this into a separate component
		var $toolbar = this.$table.prev( '.' + classes.toolbar );
		if( !$toolbar.length ) {
			$toolbar = $( '<div>' )
				.addClass( classes.toolbar )
				.insertBefore( this.$table );
		}
		this.$toolbar = $toolbar;

		if( this.mode ) {
			this.$toolbar.addClass( 'mode-' + this.mode );
		}
	};

	Table.prototype.destroy = function() {
		// Don’t remove the toolbar. Some of the table features are not yet destroy-friendly.
		this.$table.prev( '.' + classes.toolbar ).each(function() {
			this.className = this.className.replace( /\bmode\-\w*\b/gi, '' );
		});

		var tableId = this.$table.attr( 'id' );
		$( document ).unbind( "." + tableId );
		$( window ).unbind( "." + tableId );

		// other plugins
		this.$table.trigger( events.destroy, [ this ] );

		this.$table.removeAttr( 'data-tablesaw-mode' );

		this.$table.removeData( pluginName );
	};

	// Collection method.
	$.fn[ pluginName ] = function() {
		return this.each( function() {
			var $t = $( this );

			if( $t.data( pluginName ) ){
				return;
			}

			var table = new Table( this );
			$t.data( pluginName, table );
		});
	};

	$( document ).on( "enhance.tablesaw", function( e ) {
		$( e.target ).find( initSelector )[ pluginName ]();
	});

}( jQuery ));

;(function( win, $, undefined ){

	var classes = {
		stackTable: 'tablesaw-stack',
		cellLabels: 'tablesaw-cell-label',
		cellContentLabels: 'tablesaw-cell-content'
	};

	var data = {
		obj: 'tablesaw-stack'
	};

	var attrs = {
		labelless: 'data-tablesaw-no-labels',
		hideempty: 'data-tablesaw-hide-empty'
	};

	var Stack = function( element ) {

		this.$table = $( element );

		this.labelless = this.$table.is( '[' + attrs.labelless + ']' );
		this.hideempty = this.$table.is( '[' + attrs.hideempty + ']' );

		if( !this.labelless ) {
			// allHeaders references headers, plus all THs in the thead, which may include several rows, or not
			this.allHeaders = this.$table.find( "th" );
		}

		this.$table.data( data.obj, this );
	};

	Stack.prototype.init = function( colstart ) {
		this.$table.addClass( classes.stackTable );

		if( this.labelless ) {
			return;
		}

		// get headers in reverse order so that top-level headers are appended last
		var reverseHeaders = $( this.allHeaders );
		var hideempty = this.hideempty;
		
		// create the hide/show toggles
		reverseHeaders.each(function(){
			var $t = $( this ),
				$cells = $( this.cells ).filter(function() {
					return !$( this ).parent().is( "[" + attrs.labelless + "]" ) && ( !hideempty || !$( this ).is( ":empty" ) );
				}),
				hierarchyClass = $cells.not( this ).filter( "thead th" ).length && " tablesaw-cell-label-top",
				// TODO reduce coupling with sortable
				$sortableButton = $t.find( ".tablesaw-sortable-btn" ),
				html = $sortableButton.length ? $sortableButton.html() : $t.html();

			if( html !== "" ){
				if( hierarchyClass ){
					var iteration = parseInt( $( this ).attr( "colspan" ), 10 ),
						filter = "";

					if( iteration ){
						filter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";
					}
					$cells.filter( filter ).prepend( "<b class='" + classes.cellLabels + hierarchyClass + "'>" + html + "</b>"  );
				} else {
					$cells.wrapInner( "<span class='" + classes.cellContentLabels + "'></span>" );
					$cells.prepend( "<b class='" + classes.cellLabels + "'>" + html + "</b>"  );
				}
			}
		});
	};

	Stack.prototype.destroy = function() {
		this.$table.removeClass( classes.stackTable );
		this.$table.find( '.' + classes.cellLabels ).remove();
		this.$table.find( '.' + classes.cellContentLabels ).each(function() {
			$( this ).replaceWith( this.childNodes );
		});
	};

	// on tablecreate, init
	$( document ).on( "tablesawcreate", function( e, Tablesaw, colstart ){
		if( Tablesaw.mode === 'stack' ){
			var table = new Stack( Tablesaw.table );
			table.init( colstart );
		}

	} );

	$( document ).on( "tablesawdestroy", function( e, Tablesaw ){

		if( Tablesaw.mode === 'stack' ){
			$( Tablesaw.table ).data( data.obj ).destroy();
		}

	} );

}( this, jQuery ));
;(function( $ ) {
	var pluginName = "tablesawbtn",
		initSelector = ".btn",
		methods = {
			_create: function(){
				return $( this ).each(function() {
					$( this )
						.trigger( "beforecreate." + pluginName )
						[ pluginName ]( "_init" )
						.trigger( "create." + pluginName );
				});
			},
			_init: function(){
				var oEl = $( this ),
					sel = this.getElementsByTagName( "select" )[ 0 ];

				if( sel ) {
					$( this )
						.addClass( "btn-select" )
						[ pluginName ]( "_select", sel );
				}
				return oEl;
			},
			_select: function( sel ) {
				var update = function( oEl, sel ) {
					var opts = $( sel ).find( "option" ),
						label, el, children;

					opts.each(function() {
						var opt = this;
						if( opt.selected ) {
							label = document.createTextNode( opt.text );
						}
					});

					children = oEl.childNodes;
					if( opts.length > 0 ){
						for( var i = 0, l = children.length; i < l; i++ ) {
							el = children[ i ];

							if( el && el.nodeType === 3 ) {
								oEl.replaceChild( label, el );
							}
						}
					}
				};

				update( this, sel );
				$( this ).bind( "change refresh", function() {
					update( this, sel );
				});
			}
		};

	// Collection method.
	$.fn[ pluginName ] = function( arrg, a, b, c ) {
		return this.each(function() {

		// if it's a method
		if( arrg && typeof( arrg ) === "string" ){
			return $.fn[ pluginName ].prototype[ arrg ].call( this, a, b, c );
		}

		// don't re-init
		if( $( this ).data( pluginName + "active" ) ){
			return $( this );
		}

		// otherwise, init

		$( this ).data( pluginName + "active", true );
			$.fn[ pluginName ].prototype._create.call( this );
		});
	};

	// add methods
	$.extend( $.fn[ pluginName ].prototype, methods );

	$( document ).on( "enhance", function( e ) {
		$( initSelector, e.target )[ pluginName ]();
	});

}( jQuery ));
;(function( win, $, undefined ){

	var ColumnToggle = function( element ) {

		this.$table = $( element );

		this.classes = {
			columnToggleTable: 'tablesaw-columntoggle',
			columnBtnContain: 'tablesaw-columntoggle-btnwrap tablesaw-advance',
			columnBtn: 'tablesaw-columntoggle-btn tablesaw-nav-btn down',
			popup: 'tablesaw-columntoggle-popup',
			priorityPrefix: 'tablesaw-priority-',
			// TODO duplicate class, also in tables.js
			toolbar: 'tablesaw-bar'
		};

		// Expose headers and allHeaders properties on the widget
		// headers references the THs within the first TR in the table
		this.headers = this.$table.find( 'tr:first > th' );

		this.$table.data( 'tablesaw-coltoggle', this );
	};

	ColumnToggle.prototype.init = function() {

		var tableId,
			id,
			$menuButton,
			$popup,
			$menu,
			$btnContain,
			self = this;

		this.$table.addClass( this.classes.columnToggleTable );

		tableId = this.$table.attr( "id" );
		id = tableId + "-popup";
		$btnContain = $( "<div class='" + this.classes.columnBtnContain + "'></div>" );
		$menuButton = $( "<a href='#" + id + "' class='btn btn-micro " + this.classes.columnBtn +"' data-popup-link>" +
										"<span>" + Tablesaw.i18n.columnBtnText + "</span></a>" );
		$popup = $( "<div class='dialog-table-coltoggle " + this.classes.popup + "' id='" + id + "'></div>" );
		$menu = $( "<div class='btn-group'></div>" );

		var hasNonPersistentHeaders = false;
		$( this.headers ).not( "td" ).each( function() {
			var $this = $( this ),
				priority = $this.attr("data-tablesaw-priority"),
				$cells = $this.add( this.cells );

			if( priority && priority !== "persist" ) {
				$cells.addClass( self.classes.priorityPrefix + priority );

				$("<label><input type='checkbox' checked>" + $this.text() + "</label>" )
					.appendTo( $menu )
					.children( 0 )
					.data( "cells", $cells );

				hasNonPersistentHeaders = true;
			}
		});

		if( !hasNonPersistentHeaders ) {
			$menu.append( '<label>' + Tablesaw.i18n.columnsDialogError + '</label>' );
		}

		$menu.appendTo( $popup );

		// bind change event listeners to inputs - TODO: move to a private method?
		$menu.find( 'input[type="checkbox"]' ).on( "change", function(e) {
			var checked = e.target.checked;

			$( e.target ).data( "cells" )
				.toggleClass( "tablesaw-cell-hidden", !checked )
				.toggleClass( "tablesaw-cell-visible", checked );

			self.$table.trigger( 'tablesawcolumns' );
		});

		$menuButton.appendTo( $btnContain );
		$btnContain.appendTo( this.$table.prev( '.' + this.classes.toolbar ) );

		var closeTimeout;
		function openPopup() {
			$btnContain.addClass( 'visible' );
			$menuButton.removeClass( 'down' ).addClass( 'up' );

			$( document ).unbind( 'click.' + tableId, closePopup );

			window.clearTimeout( closeTimeout );
			closeTimeout = window.setTimeout(function() {
				$( document ).one( 'click.' + tableId, closePopup );
			}, 15 );
		}

		function closePopup( event ) {
			// Click came from inside the popup, ignore.
			if( event && $( event.target ).closest( "." + self.classes.popup ).length ) {
				return;
			}

			$( document ).unbind( 'click.' + tableId );
			$menuButton.removeClass( 'up' ).addClass( 'down' );
			$btnContain.removeClass( 'visible' );
		}

		$menuButton.on( "click.tablesaw", function( event ) {
			event.preventDefault();

			if( !$btnContain.is( ".visible" ) ) {
				openPopup();
			} else {
				closePopup();
			}
		});

		$popup.appendTo( $btnContain );

		this.$menu = $menu;

		$(window).on( "resize." + tableId, function(){
			self.refreshToggle();
		});

		this.refreshToggle();
	};

	ColumnToggle.prototype.refreshToggle = function() {
		this.$menu.find( "input" ).each( function() {
			var $this = $( this );

			this.checked = $this.data( "cells" ).eq( 0 ).css( "display" ) === "table-cell";
		});
	};

	ColumnToggle.prototype.refreshPriority = function(){
		var self = this;
		$(this.headers).not( "td" ).each( function() {
			var $this = $( this ),
				priority = $this.attr("data-tablesaw-priority"),
				$cells = $this.add( this.cells );

			if( priority && priority !== "persist" ) {
				$cells.addClass( self.classes.priorityPrefix + priority );
			}
		});
	};

	ColumnToggle.prototype.destroy = function() {
		// table toolbars, document and window .tableId events
		// removed in parent tables.js destroy method

		this.$table.removeClass( this.classes.columnToggleTable );
		this.$table.find( 'th, td' ).each(function() {
			var $cell = $( this );
			$cell.removeClass( 'tablesaw-cell-hidden' )
				.removeClass( 'tablesaw-cell-visible' );

			this.className = this.className.replace( /\bui\-table\-priority\-\d\b/g, '' );
		});
	};

	// on tablecreate, init
	$( document ).on( "tablesawcreate", function( e, Tablesaw ){

		if( Tablesaw.mode === 'columntoggle' ){
			var table = new ColumnToggle( Tablesaw.table );
			table.init();
		}

	} );

	$( document ).on( "tablesawdestroy", function( e, Tablesaw ){
		if( Tablesaw.mode === 'columntoggle' ){
			$( Tablesaw.table ).data( 'tablesaw-coltoggle' ).destroy();
		}
	} );

}( this, jQuery ));
;(function( win, $, undefined ){

	$.extend( Tablesaw.config, {
		swipe: {
			horizontalThreshold: 15,
			verticalThreshold: 30
		}
	});

	function createSwipeTable( $table ){

		var $btns = $( "<div class='tablesaw-advance'></div>" ),
			$prevBtn = $( "<a href='#' class='tablesaw-nav-btn btn btn-micro left' title='Previous Column'></a>" ).appendTo( $btns ),
			$nextBtn = $( "<a href='#' class='tablesaw-nav-btn btn btn-micro right' title='Next Column'></a>" ).appendTo( $btns ),
			hideBtn = 'disabled',
			persistWidths = 'tablesaw-fix-persist',
			$headerCells = $table.find( "thead th" ),
			$headerCellsNoPersist = $headerCells.not( '[data-tablesaw-priority="persist"]' ),
			headerWidths = [],
			$head = $( document.head || 'head' ),
			tableId = $table.attr( 'id' ),
			// TODO switch this to an nth-child feature test
			isIE8 = $( 'html' ).is( '.ie-lte8' );

		if( !$headerCells.length ) {
			throw new Error( "tablesaw swipe: no header cells found. Are you using <th> inside of <thead>?" );
		}

		// Calculate initial widths
		$table.css('width', 'auto');
		$headerCells.each(function() {
			headerWidths.push( $( this ).outerWidth() );
		});
		$table.css( 'width', '' );

		$btns.appendTo( $table.prev( '.tablesaw-bar' ) );

		$table.addClass( "tablesaw-swipe" );

		if( !tableId ) {
			tableId = 'tableswipe-' + Math.round( Math.random() * 10000 );
			$table.attr( 'id', tableId );
		}

		function $getCells( headerCell ) {
			return $( headerCell.cells ).add( headerCell );
		}

		function showColumn( headerCell ) {
			$getCells( headerCell ).removeClass( 'tablesaw-cell-hidden' );
		}

		function hideColumn( headerCell ) {
			$getCells( headerCell ).addClass( 'tablesaw-cell-hidden' );
		}

		function persistColumn( headerCell ) {
			$getCells( headerCell ).addClass( 'tablesaw-cell-persist' );
		}

		function isPersistent( headerCell ) {
			return $( headerCell ).is( '[data-tablesaw-priority="persist"]' );
		}

		function unmaintainWidths() {
			$table.removeClass( persistWidths );
			$( '#' + tableId + '-persist' ).remove();
		}

		function maintainWidths() {
			var prefix = '#' + tableId + '.tablesaw-swipe ',
				styles = [],
				tableWidth = $table.width(),
				hash = [],
				newHash;

			$headerCells.each(function( index ) {
				var width;
				if( isPersistent( this ) ) {
					width = $( this ).outerWidth();

					// Only save width on non-greedy columns (take up less than 75% of table width)
					if( width < tableWidth * 0.75 ) {
						hash.push( index + '-' + width );
						styles.push( prefix + ' .tablesaw-cell-persist:nth-child(' + ( index + 1 ) + ') { width: ' + width + 'px; }' );
					}
				}
			});
			newHash = hash.join( '_' );

			$table.addClass( persistWidths );

			var $style = $( '#' + tableId + '-persist' );
			// If style element not yet added OR if the widths have changed
			if( !$style.length || $style.data( 'hash' ) !== newHash ) {
				// Remove existing
				$style.remove();

				if( styles.length ) {
					$( '<style>' + styles.join( "\n" ) + '</style>' )
						.attr( 'id', tableId + '-persist' )
						.data( 'hash', newHash )
						.appendTo( $head );
				}
			}
		}

		function getNext(){
			var next = [],
				checkFound;

			$headerCellsNoPersist.each(function( i ) {
				var $t = $( this ),
					isHidden = $t.css( "display" ) === "none" || $t.is( ".tablesaw-cell-hidden" );

				if( !isHidden && !checkFound ) {
					checkFound = true;
					next[ 0 ] = i;
				} else if( isHidden && checkFound ) {
					next[ 1 ] = i;

					return false;
				}
			});

			return next;
		}

		function getPrev(){
			var next = getNext();
			return [ next[ 1 ] - 1 , next[ 0 ] - 1 ];
		}

		function nextpair( fwd ){
			return fwd ? getNext() : getPrev();
		}

		function canAdvance( pair ){
			return pair[ 1 ] > -1 && pair[ 1 ] < $headerCellsNoPersist.length;
		}

		function matchesMedia() {
			var matchMedia = $table.attr( "data-tablesaw-swipe-media" );
			return !matchMedia || ( "matchMedia" in win ) && win.matchMedia( matchMedia ).matches;
		}

		function fakeBreakpoints() {
			if( !matchesMedia() ) {
				return;
			}

			var extraPaddingPixels = 20,
				containerWidth = $table.parent().width(),
				persist = [],
				sum = 0,
				sums = [],
				visibleNonPersistantCount = $headerCells.length;

			$headerCells.each(function( index ) {
				var $t = $( this ),
					isPersist = $t.is( '[data-tablesaw-priority="persist"]' );

				persist.push( isPersist );

				sum += headerWidths[ index ] + ( isPersist ? 0 : extraPaddingPixels );
				sums.push( sum );

				// is persistent or is hidden
				if( isPersist || sum > containerWidth ) {
					visibleNonPersistantCount--;
				}
			});

			var needsNonPersistentColumn = visibleNonPersistantCount === 0;

			$headerCells.each(function( index ) {
				if( persist[ index ] ) {

					// for visual box-shadow
					persistColumn( this );
					return;
				}

				if( sums[ index ] <= containerWidth || needsNonPersistentColumn ) {
					needsNonPersistentColumn = false;
					showColumn( this );
				} else {
					hideColumn( this );
				}
			});

			if( !isIE8 ) {
				unmaintainWidths();
			}
			$table.trigger( 'tablesawcolumns' );
		}

		function advance( fwd ){
			var pair = nextpair( fwd );
			if( canAdvance( pair ) ){
				if( isNaN( pair[ 0 ] ) ){
					if( fwd ){
						pair[0] = 0;
					}
					else {
						pair[0] = $headerCellsNoPersist.length - 1;
					}
				}

				if( !isIE8 ) {
					maintainWidths();
				}

				hideColumn( $headerCellsNoPersist.get( pair[ 0 ] ) );
				showColumn( $headerCellsNoPersist.get( pair[ 1 ] ) );

				$table.trigger( 'tablesawcolumns' );
			}
		}

		$prevBtn.add( $nextBtn ).click(function( e ){
			advance( !!$( e.target ).closest( $nextBtn ).length );
			e.preventDefault();
		});

		function getCoord( event, key ) {
			return ( event.touches || event.originalEvent.touches )[ 0 ][ key ];
		}

		$table
			.bind( "touchstart.swipetoggle", function( e ){
				var originX = getCoord( e, 'pageX' ),
					originY = getCoord( e, 'pageY' ),
					x,
					y;

				$( win ).off( "resize", fakeBreakpoints );

				$( this )
					.bind( "touchmove", function( e ){
						x = getCoord( e, 'pageX' );
						y = getCoord( e, 'pageY' );
						var cfg = Tablesaw.config.swipe;
						if( Math.abs( x - originX ) > cfg.horizontalThreshold && Math.abs( y - originY ) < cfg.verticalThreshold ) {
							e.preventDefault();
						}
					})
					.bind( "touchend.swipetoggle", function(){
						var cfg = Tablesaw.config.swipe;
						if( Math.abs( y - originY ) < cfg.verticalThreshold ) {
							if( x - originX < -1 * cfg.horizontalThreshold ){
								advance( true );
							}
							if( x - originX > cfg.horizontalThreshold ){
								advance( false );
							}
						}

						window.setTimeout(function() {
							$( win ).on( "resize", fakeBreakpoints );
						}, 300);
						$( this ).unbind( "touchmove touchend" );
					});

			})
			.bind( "tablesawcolumns.swipetoggle", function(){
				$prevBtn[ canAdvance( getPrev() ) ? "removeClass" : "addClass" ]( hideBtn );
				$nextBtn[ canAdvance( getNext() ) ? "removeClass" : "addClass" ]( hideBtn );
			})
			.bind( "tablesawnext.swipetoggle", function(){
				advance( true );
			} )
			.bind( "tablesawprev.swipetoggle", function(){
				advance( false );
			} )
			.bind( "tablesawdestroy.swipetoggle", function(){
				var $t = $( this );

				$t.removeClass( 'tablesaw-swipe' );
				$t.prev( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
				$( win ).off( "resize", fakeBreakpoints );

				$t.unbind( ".swipetoggle" );
			});

		fakeBreakpoints();
		$( win ).on( "resize", fakeBreakpoints );
	}



	// on tablecreate, init
	$( document ).on( "tablesawcreate", function( e, Tablesaw ){

		if( Tablesaw.mode === 'swipe' ){
			createSwipeTable( Tablesaw.$table );
		}

	} );

}( this, jQuery ));

;(function( $ ) {
	function getSortValue( cell ) {
		return $.map( cell.childNodes, function( el ) {
				var $el = $( el );
				if( $el.is( 'input, select' ) ) {
					return $el.val();
				} else if( $el.hasClass( 'tablesaw-cell-label' ) ) {
					return;
				}
				return $.trim( $el.text() );
			}).join( '' );
	}

	var pluginName = "tablesaw-sortable",
		initSelector = "table[data-" + pluginName + "]",
		sortableSwitchSelector = "[data-" + pluginName + "-switch]",
		attrs = {
			defaultCol: "data-tablesaw-sortable-default-col"
		},
		classes = {
			head: pluginName + "-head",
			ascend: pluginName + "-ascending",
			descend: pluginName + "-descending",
			switcher: pluginName + "-switch",
			tableToolbar: 'tablesaw-toolbar',
			sortButton: pluginName + "-btn"
		},
		methods = {
			_create: function( o ){
				return $( this ).each(function() {
					var init = $( this ).data( "init" + pluginName );
					if( init ) {
						return false;
					}
					$( this )
						.data( "init"+ pluginName, true )
						.trigger( "beforecreate." + pluginName )
						[ pluginName ]( "_init" , o )
						.trigger( "create." + pluginName );
				});
			},
			_init: function(){
				var el = $( this ),
					heads,
					$switcher;

				var addClassToTable = function(){
						el.addClass( pluginName );
					},
					addClassToHeads = function( h ){
						$.each( h , function( i , v ){
							$( v ).addClass( classes.head );
						});
					},
					makeHeadsActionable = function( h , fn ){
						$.each( h , function( i , v ){
							var b = $( "<button class='" + classes.sortButton + "'/>" );
							b.bind( "click" , { col: v } , fn );
							$( v ).wrapInner( b );
						});
					},
					clearOthers = function( sibs ){
						$.each( sibs , function( i , v ){
							var col = $( v );
							col.removeAttr( attrs.defaultCol );
							col.removeClass( classes.ascend );
							col.removeClass( classes.descend );
						});
					},
					headsOnAction = function( e ){
						if( $( e.target ).is( 'a[href]' ) ) {
							return;
						}

						e.stopPropagation();
						var head = $( this ).parent(),
							v = e.data.col,
							newSortValue = heads.index( head );

						clearOthers( head.siblings() );
						if( head.hasClass( classes.descend ) ){
							el[ pluginName ]( "sortBy" , v , true);
							newSortValue += '_asc';
						} else {
							el[ pluginName ]( "sortBy" , v );
							newSortValue += '_desc';
						}
						if( $switcher ) {
							$switcher.find( 'select' ).val( newSortValue ).trigger( 'refresh' );
						}

						e.preventDefault();
					},
					handleDefault = function( heads ){
						$.each( heads , function( idx , el ){
							var $el = $( el );
							if( $el.is( "[" + attrs.defaultCol + "]" ) ){
								if( !$el.hasClass( classes.descend ) ) {
									$el.addClass( classes.ascend );
								}
							}
						});
					},
					addSwitcher = function( heads ){
						$switcher = $( '<div>' ).addClass( classes.switcher ).addClass( classes.tableToolbar ).html(function() {
							var html = [ '<label>' + Tablesaw.i18n.sort + ':' ];

							html.push( '<span class="btn btn-small">&#160;<select>' );
							heads.each(function( j ) {
								var $t = $( this ),
									isDefaultCol = $t.is( "[" + attrs.defaultCol + "]" ),
									isDescending = $t.hasClass( classes.descend ),
									isNumeric = false;

								// Check only the first three rows to see if the column is numbers.
								$( this.cells ).slice( 0, 3 ).each(function() {
									if( !isNaN( parseInt( getSortValue( this ), 10 ) ) ) {
										isNumeric = true;
										return false;
									}
								});

								html.push( '<option' + ( isDefaultCol && !isDescending ? ' selected' : '' ) + ' value="' + j + '_asc">' + $t.text() + ' ' + ( isNumeric ? '↑' : '(A-Z)' ) + '</option>' );
								html.push( '<option' + ( isDefaultCol && isDescending ? ' selected' : '' ) + ' value="' + j + '_desc">' + $t.text() + ' ' + ( isNumeric ? '↓' : '(Z-A)' ) + '</option>' );
							});
							html.push( '</select></span></label>' );

							return html.join('');
						});

						var $toolbar = el.prev( '.tablesaw-bar' ),
							$firstChild = $toolbar.children().eq( 0 );

						if( $firstChild.length ) {
							$switcher.insertBefore( $firstChild );
						} else {
							$switcher.appendTo( $toolbar );
						}
						$switcher.find( '.btn' ).tablesawbtn();
						$switcher.find( 'select' ).on( 'change', function() {
							var val = $( this ).val().split( '_' ),
								head = heads.eq( val[ 0 ] );

							clearOthers( head.siblings() );
							el[ pluginName ]( 'sortBy', head.get( 0 ), val[ 1 ] === 'asc' );
						});
					};

					addClassToTable();
					heads = el.find( "thead th[data-" + pluginName + "-col]" );
					addClassToHeads( heads );
					makeHeadsActionable( heads , headsOnAction );
					handleDefault( heads );

					if( el.is( sortableSwitchSelector ) ) {
						addSwitcher( heads, el.find('tbody tr:nth-child(-n+3)') );
					}
			},
			getColumnNumber: function( col ){
				return $( col ).prevAll().length;
			},
			getTableRows: function(){
				return $( this ).find( "tbody tr" );
			},
			sortRows: function( rows , colNum , ascending, col ){
				var cells, fn, sorted;
				var getCells = function( rows ){
						var cells = [];
						$.each( rows , function( i , r ){
							cells.push({
								cell: getSortValue( $( r ).children().get( colNum ) ),
								rowNum: i
							});
						});
						return cells;
					},
					getSortFxn = function( ascending, forceNumeric ){
						var fn,
							regex = /[^\-\+\d\.]/g;
						if( ascending ){
							fn = function( a , b ){
								if( forceNumeric || !isNaN( parseFloat( a.cell ) ) ) {
									return parseFloat( a.cell.replace( regex, '' ) ) - parseFloat( b.cell.replace( regex, '' ) );
								} else {
									return a.cell.toLowerCase() > b.cell.toLowerCase() ? 1 : -1;
								}
							};
						} else {
							fn = function( a , b ){
								if( forceNumeric || !isNaN( parseFloat( a.cell ) ) ) {
									return parseFloat( b.cell.replace( regex, '' ) ) - parseFloat( a.cell.replace( regex, '' ) );
								} else {
									return a.cell.toLowerCase() < b.cell.toLowerCase() ? 1 : -1;
								}
							};
						}
						return fn;
					},
					applyToRows = function( sorted , rows ){
						var newRows = [], i, l, cur;
						for( i = 0, l = sorted.length ; i < l ; i++ ){
							cur = sorted[ i ].rowNum;
							newRows.push( rows[cur] );
						}
						return newRows;
					};

				cells = getCells( rows );
				var customFn = $( col ).data( 'tablesaw-sort' );
				fn = ( customFn && typeof customFn === "function" ? customFn( ascending ) : false ) ||
					getSortFxn( ascending, $( col ).is( '[data-sortable-numeric]' ) );
				sorted = cells.sort( fn );
				rows = applyToRows( sorted , rows );
				return rows;
			},
			replaceTableRows: function( rows ){
				var el = $( this ),
					body = el.find( "tbody" );
				body.html( rows );
			},
			makeColDefault: function( col , a ){
				var c = $( col );
				c.attr( attrs.defaultCol , "true" );
				if( a ){
					c.removeClass( classes.descend );
					c.addClass( classes.ascend );
				} else {
					c.removeClass( classes.ascend );
					c.addClass( classes.descend );
				}
			},
			sortBy: function( col , ascending ){
				var el = $( this ), colNum, rows;

				colNum = el[ pluginName ]( "getColumnNumber" , col );
				rows = el[ pluginName ]( "getTableRows" );
				rows = el[ pluginName ]( "sortRows" , rows , colNum , ascending, col );
				el[ pluginName ]( "replaceTableRows" , rows );
				el[ pluginName ]( "makeColDefault" , col , ascending );
			}
		};

	// Collection method.
	$.fn[ pluginName ] = function( arrg ) {
		var args = Array.prototype.slice.call( arguments , 1),
			returnVal;

		// if it's a method
		if( arrg && typeof( arrg ) === "string" ){
			returnVal = $.fn[ pluginName ].prototype[ arrg ].apply( this[0], args );
			return (typeof returnVal !== "undefined")? returnVal:$(this);
		}
		// check init
		if( !$( this ).data( pluginName + "data" ) ){
			$( this ).data( pluginName + "active", true );
			$.fn[ pluginName ].prototype._create.call( this , arrg );
		}
		return $(this);
	};
	// add methods
	$.extend( $.fn[ pluginName ].prototype, methods );

	$( document ).on( "tablesawcreate", function( e, Tablesaw ) {
		if( Tablesaw.$table.is( initSelector ) ) {
			Tablesaw.$table[ pluginName ]();
		}
	});

}( jQuery ));

;(function( win, $, undefined ){

	var MM = {
		attr: {
			init: 'data-tablesaw-minimap'
		}
	};

	function createMiniMap( $table ){

		var $btns = $( '<div class="tablesaw-advance minimap">' ),
			$dotNav = $( '<ul class="tablesaw-advance-dots">' ).appendTo( $btns ),
			hideDot = 'tablesaw-advance-dots-hide',
			$headerCells = $table.find( 'thead th' );

		// populate dots
		$headerCells.each(function(){
			$dotNav.append( '<li><i></i></li>' );
		});

		$btns.appendTo( $table.prev( '.tablesaw-bar' ) );

		function showMinimap( $table ) {
			var mq = $table.attr( MM.attr.init );
			return !mq || win.matchMedia && win.matchMedia( mq ).matches;
		}

		function showHideNav(){
			if( !showMinimap( $table ) ) {
				$btns.hide();
				return;
			}
			$btns.show();

			// show/hide dots
			var dots = $dotNav.find( "li" ).removeClass( hideDot );
			$table.find( "thead th" ).each(function(i){
				if( $( this ).css( "display" ) === "none" ){
					dots.eq( i ).addClass( hideDot );
				}
			});
		}

		// run on init and resize
		showHideNav();
		$( win ).on( "resize", showHideNav );


		$table
			.bind( "tablesawcolumns.minimap", function(){
				showHideNav();
			})
			.bind( "tablesawdestroy.minimap", function(){
				var $t = $( this );

				$t.prev( '.tablesaw-bar' ).find( '.tablesaw-advance' ).remove();
				$( win ).off( "resize", showHideNav );

				$t.unbind( ".minimap" );
			});
	}



	// on tablecreate, init
	$( document ).on( "tablesawcreate", function( e, Tablesaw ){

		if( ( Tablesaw.mode === 'swipe' || Tablesaw.mode === 'columntoggle' ) && Tablesaw.$table.is( '[ ' + MM.attr.init + ']' ) ){
			createMiniMap( Tablesaw.$table );
		}

	} );

}( this, jQuery ));

;(function( win, $ ) {

	var S = {
		selectors: {
			init: 'table[data-tablesaw-mode-switch]'
		},
		attributes: {
			excludeMode: 'data-tablesaw-mode-exclude'
		},
		classes: {
			main: 'tablesaw-modeswitch',
			toolbar: 'tablesaw-toolbar'
		},
		modes: [ 'stack', 'swipe', 'columntoggle' ],
		init: function( table ) {
			var $table = $( table ),
				ignoreMode = $table.attr( S.attributes.excludeMode ),
				$toolbar = $table.prev( '.tablesaw-bar' ),
				modeVal = '',
				$switcher = $( '<div>' ).addClass( S.classes.main + ' ' + S.classes.toolbar ).html(function() {
					var html = [ '<label>' + Tablesaw.i18n.columns + ':' ],
						dataMode = $table.attr( 'data-tablesaw-mode' ),
						isSelected;

					html.push( '<span class="btn btn-small">&#160;<select>' );
					for( var j=0, k = S.modes.length; j<k; j++ ) {
						if( ignoreMode && ignoreMode.toLowerCase() === S.modes[ j ] ) {
							continue;
						}

						isSelected = dataMode === S.modes[ j ];

						if( isSelected ) {
							modeVal = S.modes[ j ];
						}

						html.push( '<option' +
							( isSelected ? ' selected' : '' ) +
							' value="' + S.modes[ j ] + '">' + Tablesaw.i18n.modes[ j ] + '</option>' );
					}
					html.push( '</select></span></label>' );

					return html.join('');
				});

			var $otherToolbarItems = $toolbar.find( '.tablesaw-advance' ).eq( 0 );
			if( $otherToolbarItems.length ) {
				$switcher.insertBefore( $otherToolbarItems );
			} else {
				$switcher.appendTo( $toolbar );
			}

			$switcher.find( '.btn' ).tablesawbtn();
			$switcher.find( 'select' ).bind( 'change', S.onModeChange );
		},
		onModeChange: function() {
			var $t = $( this ),
				$switcher = $t.closest( '.' + S.classes.main ),
				$table = $t.closest( '.tablesaw-bar' ).nextUntil( $table ).eq( 0 ),
				val = $t.val();

			$switcher.remove();
			$table.data( 'table' ).destroy();

			$table.attr( 'data-tablesaw-mode', val );
			$table.table();
		}
	};

	$( win.document ).on( "tablesawcreate", function( e, Tablesaw ) {
		if( Tablesaw.$table.is( S.selectors.init ) ) {
			S.init( Tablesaw.table );
		}
	});

})( this, jQuery );
/* Tooltipster v3.3.0 */;(function(e,t,n){function s(t,n){this.bodyOverflowX;this.callbacks={hide:[],show:[]};this.checkInterval=null;this.Content;this.$el=e(t);this.$elProxy;this.elProxyPosition;this.enabled=true;this.options=e.extend({},i,n);this.mouseIsOverProxy=false;this.namespace="tooltipster-"+Math.round(Math.random()*1e5);this.Status="hidden";this.timerHide=null;this.timerShow=null;this.$tooltip;this.options.iconTheme=this.options.iconTheme.replace(".","");this.options.theme=this.options.theme.replace(".","");this._init()}function o(t,n){var r=true;e.each(t,function(e,i){if(typeof n[e]==="undefined"||t[e]!==n[e]){r=false;return false}});return r}function f(){return!a&&u}function l(){var e=n.body||n.documentElement,t=e.style,r="transition";if(typeof t[r]=="string"){return true}v=["Moz","Webkit","Khtml","O","ms"],r=r.charAt(0).toUpperCase()+r.substr(1);for(var i=0;i<v.length;i++){if(typeof t[v[i]+r]=="string"){return true}}return false}var r="tooltipster",i={animation:"fade",arrow:true,arrowColor:"",autoClose:true,content:null,contentAsHTML:false,contentCloning:true,debug:true,delay:200,minWidth:0,maxWidth:null,functionInit:function(e,t){},functionBefore:function(e,t){t()},functionReady:function(e,t){},functionAfter:function(e){},hideOnClick:false,icon:"(?)",iconCloning:true,iconDesktop:false,iconTouch:false,iconTheme:"tooltipster-icon",interactive:false,interactiveTolerance:350,multiple:false,offsetX:0,offsetY:0,onlyOne:false,position:"top",positionTracker:false,positionTrackerCallback:function(e){if(this.option("trigger")=="hover"&&this.option("autoClose")){this.hide()}},restoration:"current",speed:350,timer:0,theme:"tooltipster-default",touchDevices:true,trigger:"hover",updateAnimation:true};s.prototype={_init:function(){var t=this;if(n.querySelector){var r=null;if(t.$el.data("tooltipster-initialTitle")===undefined){r=t.$el.attr("title");if(r===undefined)r=null;t.$el.data("tooltipster-initialTitle",r)}if(t.options.content!==null){t._content_set(t.options.content)}else{t._content_set(r)}var i=t.options.functionInit.call(t.$el,t.$el,t.Content);if(typeof i!=="undefined")t._content_set(i);t.$el.removeAttr("title").addClass("tooltipstered");if(!u&&t.options.iconDesktop||u&&t.options.iconTouch){if(typeof t.options.icon==="string"){t.$elProxy=e('<span class="'+t.options.iconTheme+'"></span>');t.$elProxy.text(t.options.icon)}else{if(t.options.iconCloning)t.$elProxy=t.options.icon.clone(true);else t.$elProxy=t.options.icon}t.$elProxy.insertAfter(t.$el)}else{t.$elProxy=t.$el}if(t.options.trigger=="hover"){t.$elProxy.on("mouseenter."+t.namespace,function(){if(!f()||t.options.touchDevices){t.mouseIsOverProxy=true;t._show()}}).on("mouseleave."+t.namespace,function(){if(!f()||t.options.touchDevices){t.mouseIsOverProxy=false}});if(u&&t.options.touchDevices){t.$elProxy.on("touchstart."+t.namespace,function(){t._showNow()})}}else if(t.options.trigger=="click"){t.$elProxy.on("click."+t.namespace,function(){if(!f()||t.options.touchDevices){t._show()}})}}},_show:function(){var e=this;if(e.Status!="shown"&&e.Status!="appearing"){if(e.options.delay){e.timerShow=setTimeout(function(){if(e.options.trigger=="click"||e.options.trigger=="hover"&&e.mouseIsOverProxy){e._showNow()}},e.options.delay)}else e._showNow()}},_showNow:function(n){var r=this;r.options.functionBefore.call(r.$el,r.$el,function(){if(r.enabled&&r.Content!==null){if(n)r.callbacks.show.push(n);r.callbacks.hide=[];clearTimeout(r.timerShow);r.timerShow=null;clearTimeout(r.timerHide);r.timerHide=null;if(r.options.onlyOne){e(".tooltipstered").not(r.$el).each(function(t,n){var r=e(n),i=r.data("tooltipster-ns");e.each(i,function(e,t){var n=r.data(t),i=n.status(),s=n.option("autoClose");if(i!=="hidden"&&i!=="disappearing"&&s){n.hide()}})})}var i=function(){r.Status="shown";e.each(r.callbacks.show,function(e,t){t.call(r.$el)});r.callbacks.show=[]};if(r.Status!=="hidden"){var s=0;if(r.Status==="disappearing"){r.Status="appearing";if(l()){r.$tooltip.clearQueue().removeClass("tooltipster-dying").addClass("tooltipster-"+r.options.animation+"-show");if(r.options.speed>0)r.$tooltip.delay(r.options.speed);r.$tooltip.queue(i)}else{r.$tooltip.stop().fadeIn(i)}}else if(r.Status==="shown"){i()}}else{r.Status="appearing";var s=r.options.speed;r.bodyOverflowX=e("body").css("overflow-x");e("body").css("overflow-x","hidden");var o="tooltipster-"+r.options.animation,a="-webkit-transition-duration: "+r.options.speed+"ms; -webkit-animation-duration: "+r.options.speed+"ms; -moz-transition-duration: "+r.options.speed+"ms; -moz-animation-duration: "+r.options.speed+"ms; -o-transition-duration: "+r.options.speed+"ms; -o-animation-duration: "+r.options.speed+"ms; -ms-transition-duration: "+r.options.speed+"ms; -ms-animation-duration: "+r.options.speed+"ms; transition-duration: "+r.options.speed+"ms; animation-duration: "+r.options.speed+"ms;",f=r.options.minWidth?"min-width:"+Math.round(r.options.minWidth)+"px;":"",c=r.options.maxWidth?"max-width:"+Math.round(r.options.maxWidth)+"px;":"",h=r.options.interactive?"pointer-events: auto;":"";r.$tooltip=e('<div class="tooltipster-base '+r.options.theme+'" style="'+f+" "+c+" "+h+" "+a+'"><div class="tooltipster-content"></div></div>');if(l())r.$tooltip.addClass(o);r._content_insert();r.$tooltip.appendTo("body");r.reposition();r.options.functionReady.call(r.$el,r.$el,r.$tooltip);if(l()){r.$tooltip.addClass(o+"-show");if(r.options.speed>0)r.$tooltip.delay(r.options.speed);r.$tooltip.queue(i)}else{r.$tooltip.css("display","none").fadeIn(r.options.speed,i)}r._interval_set();e(t).on("scroll."+r.namespace+" resize."+r.namespace,function(){r.reposition()});if(r.options.autoClose){e("body").off("."+r.namespace);if(r.options.trigger=="hover"){if(u){setTimeout(function(){e("body").on("touchstart."+r.namespace,function(){r.hide()})},0)}if(r.options.interactive){if(u){r.$tooltip.on("touchstart."+r.namespace,function(e){e.stopPropagation()})}var p=null;r.$elProxy.add(r.$tooltip).on("mouseleave."+r.namespace+"-autoClose",function(){clearTimeout(p);p=setTimeout(function(){r.hide()},r.options.interactiveTolerance)}).on("mouseenter."+r.namespace+"-autoClose",function(){clearTimeout(p)})}else{r.$elProxy.on("mouseleave."+r.namespace+"-autoClose",function(){r.hide()})}if(r.options.hideOnClick){r.$elProxy.on("click."+r.namespace+"-autoClose",function(){r.hide()})}}else if(r.options.trigger=="click"){setTimeout(function(){e("body").on("click."+r.namespace+" touchstart."+r.namespace,function(){r.hide()})},0);if(r.options.interactive){r.$tooltip.on("click."+r.namespace+" touchstart."+r.namespace,function(e){e.stopPropagation()})}}}}if(r.options.timer>0){r.timerHide=setTimeout(function(){r.timerHide=null;r.hide()},r.options.timer+s)}}})},_interval_set:function(){var t=this;t.checkInterval=setInterval(function(){if(e("body").find(t.$el).length===0||e("body").find(t.$elProxy).length===0||t.Status=="hidden"||e("body").find(t.$tooltip).length===0){if(t.Status=="shown"||t.Status=="appearing")t.hide();t._interval_cancel()}else{if(t.options.positionTracker){var n=t._repositionInfo(t.$elProxy),r=false;if(o(n.dimension,t.elProxyPosition.dimension)){if(t.$elProxy.css("position")==="fixed"){if(o(n.position,t.elProxyPosition.position))r=true}else{if(o(n.offset,t.elProxyPosition.offset))r=true}}if(!r){t.reposition();t.options.positionTrackerCallback.call(t,t.$el)}}}},200)},_interval_cancel:function(){clearInterval(this.checkInterval);this.checkInterval=null},_content_set:function(e){if(typeof e==="object"&&e!==null&&this.options.contentCloning){e=e.clone(true)}this.Content=e},_content_insert:function(){var e=this,t=this.$tooltip.find(".tooltipster-content");if(typeof e.Content==="string"&&!e.options.contentAsHTML){t.text(e.Content)}else{t.empty().append(e.Content)}},_update:function(e){var t=this;t._content_set(e);if(t.Content!==null){if(t.Status!=="hidden"){t._content_insert();t.reposition();if(t.options.updateAnimation){if(l()){t.$tooltip.css({width:"","-webkit-transition":"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms","-moz-transition":"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms","-o-transition":"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms","-ms-transition":"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms",transition:"all "+t.options.speed+"ms, width 0ms, height 0ms, left 0ms, top 0ms"}).addClass("tooltipster-content-changing");setTimeout(function(){if(t.Status!="hidden"){t.$tooltip.removeClass("tooltipster-content-changing");setTimeout(function(){if(t.Status!=="hidden"){t.$tooltip.css({"-webkit-transition":t.options.speed+"ms","-moz-transition":t.options.speed+"ms","-o-transition":t.options.speed+"ms","-ms-transition":t.options.speed+"ms",transition:t.options.speed+"ms"})}},t.options.speed)}},t.options.speed)}else{t.$tooltip.fadeTo(t.options.speed,.5,function(){if(t.Status!="hidden"){t.$tooltip.fadeTo(t.options.speed,1)}})}}}}else{t.hide()}},_repositionInfo:function(e){return{dimension:{height:e.outerHeight(false),width:e.outerWidth(false)},offset:e.offset(),position:{left:parseInt(e.css("left")),top:parseInt(e.css("top"))}}},hide:function(n){var r=this;if(n)r.callbacks.hide.push(n);r.callbacks.show=[];clearTimeout(r.timerShow);r.timerShow=null;clearTimeout(r.timerHide);r.timerHide=null;var i=function(){e.each(r.callbacks.hide,function(e,t){t.call(r.$el)});r.callbacks.hide=[]};if(r.Status=="shown"||r.Status=="appearing"){r.Status="disappearing";var s=function(){r.Status="hidden";if(typeof r.Content=="object"&&r.Content!==null){r.Content.detach()}r.$tooltip.remove();r.$tooltip=null;e(t).off("."+r.namespace);e("body").off("."+r.namespace).css("overflow-x",r.bodyOverflowX);e("body").off("."+r.namespace);r.$elProxy.off("."+r.namespace+"-autoClose");r.options.functionAfter.call(r.$el,r.$el);i()};if(l()){r.$tooltip.clearQueue().removeClass("tooltipster-"+r.options.animation+"-show").addClass("tooltipster-dying");if(r.options.speed>0)r.$tooltip.delay(r.options.speed);r.$tooltip.queue(s)}else{r.$tooltip.stop().fadeOut(r.options.speed,s)}}else if(r.Status=="hidden"){i()}return r},show:function(e){this._showNow(e);return this},update:function(e){return this.content(e)},content:function(e){if(typeof e==="undefined"){return this.Content}else{this._update(e);return this}},reposition:function(){var n=this;if(e("body").find(n.$tooltip).length!==0){n.$tooltip.css("width","");n.elProxyPosition=n._repositionInfo(n.$elProxy);var r=null,i=e(t).width(),s=n.elProxyPosition,o=n.$tooltip.outerWidth(false),u=n.$tooltip.innerWidth()+1,a=n.$tooltip.outerHeight(false);if(n.$elProxy.is("area")){var f=n.$elProxy.attr("shape"),l=n.$elProxy.parent().attr("name"),c=e('img[usemap="#'+l+'"]'),h=c.offset().left,p=c.offset().top,d=n.$elProxy.attr("coords")!==undefined?n.$elProxy.attr("coords").split(","):undefined;if(f=="circle"){var v=parseInt(d[0]),m=parseInt(d[1]),g=parseInt(d[2]);s.dimension.height=g*2;s.dimension.width=g*2;s.offset.top=p+m-g;s.offset.left=h+v-g}else if(f=="rect"){var v=parseInt(d[0]),m=parseInt(d[1]),y=parseInt(d[2]),b=parseInt(d[3]);s.dimension.height=b-m;s.dimension.width=y-v;s.offset.top=p+m;s.offset.left=h+v}else if(f=="poly"){var w=[],E=[],S=0,x=0,T=0,N=0,C="even";for(var k=0;k<d.length;k++){var L=parseInt(d[k]);if(C=="even"){if(L>T){T=L;if(k===0){S=T}}if(L<S){S=L}C="odd"}else{if(L>N){N=L;if(k==1){x=N}}if(L<x){x=L}C="even"}}s.dimension.height=N-x;s.dimension.width=T-S;s.offset.top=p+x;s.offset.left=h+S}else{s.dimension.height=c.outerHeight(false);s.dimension.width=c.outerWidth(false);s.offset.top=p;s.offset.left=h}}var A=0,O=0,M=0,_=parseInt(n.options.offsetY),D=parseInt(n.options.offsetX),P=n.options.position;function H(){var n=e(t).scrollLeft();if(A-n<0){r=A-n;A=n}if(A+o-n>i){r=A-(i+n-o);A=i+n-o}}function B(n,r){if(s.offset.top-e(t).scrollTop()-a-_-12<0&&r.indexOf("top")>-1){P=n}if(s.offset.top+s.dimension.height+a+12+_>e(t).scrollTop()+e(t).height()&&r.indexOf("bottom")>-1){P=n;M=s.offset.top-a-_-12}}if(P=="top"){var j=s.offset.left+o-(s.offset.left+s.dimension.width);A=s.offset.left+D-j/2;M=s.offset.top-a-_-12;H();B("bottom","top")}if(P=="top-left"){A=s.offset.left+D;M=s.offset.top-a-_-12;H();B("bottom-left","top-left")}if(P=="top-right"){A=s.offset.left+s.dimension.width+D-o;M=s.offset.top-a-_-12;H();B("bottom-right","top-right")}if(P=="bottom"){var j=s.offset.left+o-(s.offset.left+s.dimension.width);A=s.offset.left-j/2+D;M=s.offset.top+s.dimension.height+_+12;H();B("top","bottom")}if(P=="bottom-left"){A=s.offset.left+D;M=s.offset.top+s.dimension.height+_+12;H();B("top-left","bottom-left")}if(P=="bottom-right"){A=s.offset.left+s.dimension.width+D-o;M=s.offset.top+s.dimension.height+_+12;H();B("top-right","bottom-right")}if(P=="left"){A=s.offset.left-D-o-12;O=s.offset.left+D+s.dimension.width+12;var F=s.offset.top+a-(s.offset.top+s.dimension.height);M=s.offset.top-F/2-_;if(A<0&&O+o>i){var I=parseFloat(n.$tooltip.css("border-width"))*2,q=o+A-I;n.$tooltip.css("width",q+"px");a=n.$tooltip.outerHeight(false);A=s.offset.left-D-q-12-I;F=s.offset.top+a-(s.offset.top+s.dimension.height);M=s.offset.top-F/2-_}else if(A<0){A=s.offset.left+D+s.dimension.width+12;r="left"}}if(P=="right"){A=s.offset.left+D+s.dimension.width+12;O=s.offset.left-D-o-12;var F=s.offset.top+a-(s.offset.top+s.dimension.height);M=s.offset.top-F/2-_;if(A+o>i&&O<0){var I=parseFloat(n.$tooltip.css("border-width"))*2,q=i-A-I;n.$tooltip.css("width",q+"px");a=n.$tooltip.outerHeight(false);F=s.offset.top+a-(s.offset.top+s.dimension.height);M=s.offset.top-F/2-_}else if(A+o>i){A=s.offset.left-D-o-12;r="right"}}if(n.options.arrow){var R="tooltipster-arrow-"+P;if(n.options.arrowColor.length<1){var U=n.$tooltip.css("background-color")}else{var U=n.options.arrowColor}if(!r){r=""}else if(r=="left"){R="tooltipster-arrow-right";r=""}else if(r=="right"){R="tooltipster-arrow-left";r=""}else{r="left:"+Math.round(r)+"px;"}if(P=="top"||P=="top-left"||P=="top-right"){var z=parseFloat(n.$tooltip.css("border-bottom-width")),W=n.$tooltip.css("border-bottom-color")}else if(P=="bottom"||P=="bottom-left"||P=="bottom-right"){var z=parseFloat(n.$tooltip.css("border-top-width")),W=n.$tooltip.css("border-top-color")}else if(P=="left"){var z=parseFloat(n.$tooltip.css("border-right-width")),W=n.$tooltip.css("border-right-color")}else if(P=="right"){var z=parseFloat(n.$tooltip.css("border-left-width")),W=n.$tooltip.css("border-left-color")}else{var z=parseFloat(n.$tooltip.css("border-bottom-width")),W=n.$tooltip.css("border-bottom-color")}if(z>1){z++}var X="";if(z!==0){var V="",J="border-color: "+W+";";if(R.indexOf("bottom")!==-1){V="margin-top: -"+Math.round(z)+"px;"}else if(R.indexOf("top")!==-1){V="margin-bottom: -"+Math.round(z)+"px;"}else if(R.indexOf("left")!==-1){V="margin-right: -"+Math.round(z)+"px;"}else if(R.indexOf("right")!==-1){V="margin-left: -"+Math.round(z)+"px;"}X='<span class="tooltipster-arrow-border" style="'+V+" "+J+';"></span>'}n.$tooltip.find(".tooltipster-arrow").remove();var K='<div class="'+R+' tooltipster-arrow" style="'+r+'">'+X+'<span style="border-color:'+U+';"></span></div>';n.$tooltip.append(K)}n.$tooltip.css({top:Math.round(M)+"px",left:Math.round(A)+"px"})}return n},enable:function(){this.enabled=true;return this},disable:function(){this.hide();this.enabled=false;return this},destroy:function(){var t=this;t.hide();if(t.$el[0]!==t.$elProxy[0]){t.$elProxy.remove()}t.$el.removeData(t.namespace).off("."+t.namespace);var n=t.$el.data("tooltipster-ns");if(n.length===1){var r=null;if(t.options.restoration==="previous"){r=t.$el.data("tooltipster-initialTitle")}else if(t.options.restoration==="current"){r=typeof t.Content==="string"?t.Content:e("<div></div>").append(t.Content).html()}if(r){t.$el.attr("title",r)}t.$el.removeClass("tooltipstered").removeData("tooltipster-ns").removeData("tooltipster-initialTitle")}else{n=e.grep(n,function(e,n){return e!==t.namespace});t.$el.data("tooltipster-ns",n)}return t},elementIcon:function(){return this.$el[0]!==this.$elProxy[0]?this.$elProxy[0]:undefined},elementTooltip:function(){return this.$tooltip?this.$tooltip[0]:undefined},option:function(e,t){if(typeof t=="undefined")return this.options[e];else{this.options[e]=t;return this}},status:function(){return this.Status}};e.fn[r]=function(){var t=arguments;if(this.length===0){if(typeof t[0]==="string"){var n=true;switch(t[0]){case"setDefaults":e.extend(i,t[1]);break;default:n=false;break}if(n)return true;else return this}else{return this}}else{if(typeof t[0]==="string"){var r="#*$~&";this.each(function(){var n=e(this).data("tooltipster-ns"),i=n?e(this).data(n[0]):null;if(i){if(typeof i[t[0]]==="function"){var s=i[t[0]](t[1],t[2])}else{throw new Error('Unknown method .tooltipster("'+t[0]+'")')}if(s!==i){r=s;return false}}else{throw new Error("You called Tooltipster's \""+t[0]+'" method on an uninitialized element')}});return r!=="#*$~&"?r:this}else{var o=[],u=t[0]&&typeof t[0].multiple!=="undefined",a=u&&t[0].multiple||!u&&i.multiple,f=t[0]&&typeof t[0].debug!=="undefined",l=f&&t[0].debug||!f&&i.debug;this.each(function(){var n=false,r=e(this).data("tooltipster-ns"),i=null;if(!r){n=true}else if(a){n=true}else if(l){console.log('Tooltipster: one or more tooltips are already attached to this element: ignoring. Use the "multiple" option to attach more tooltips.')}if(n){i=new s(this,t[0]);if(!r)r=[];r.push(i.namespace);e(this).data("tooltipster-ns",r);e(this).data(i.namespace,i)}o.push(i)});if(a)return o;else return this}}};var u=!!("ontouchstart"in t);var a=false;e("body").one("mousemove",function(){a=true})})(jQuery,window,document);
(function ($) {

    'use strict';

    var dw, dh, rw, rh, lx, ly;

    var defaults = {

        // The text to display within the notice box while loading the zoom image.
        loadingNotice: 'Loading image',

        // The text to display within the notice box if an error occurs when loading the zoom image.
        errorNotice: 'The image could not be loaded',

        // The time (in milliseconds) to display the error notice.
        errorDuration: 2500,

        // Attribute to retrieve the zoom image URL from.
        linkAttribute: 'href',

        // Prevent clicks on the zoom image link.
        preventClicks: true,

        // Callback function to execute before the flyout is displayed.
        beforeShow: $.noop,

        // Callback function to execute before the flyout is removed.
        beforeHide: $.noop,

        // Callback function to execute when the flyout is displayed.
        onShow: $.noop,

        // Callback function to execute when the flyout is removed.
        onHide: $.noop,

        // Callback function to execute when the cursor is moved while over the image.
        onMove: $.noop

    };

    /**
     * EasyZoom
     * @constructor
     * @param {Object} target
     * @param {Object} options (Optional)
     */
    function EasyZoom(target, options) {
        this.$target = $(target);
        this.opts = $.extend({}, defaults, options, this.$target.data());

        this.isOpen === undefined && this._init();
    }

    /**
     * Init
     * @private
     */
    EasyZoom.prototype._init = function() {
        this.$link   = this.$target.find('a');
        this.$image  = this.$target.find('img');

        this.$flyout = $('<div class="easyzoom-flyout" />');
        this.$notice = $('<div class="easyzoom-notice" />');

        this.$target.on({
            'mousemove.easyzoom touchmove.easyzoom': $.proxy(this._onMove, this),
            'mouseleave.easyzoom touchend.easyzoom': $.proxy(this._onLeave, this),
            'mouseenter.easyzoom touchstart.easyzoom': $.proxy(this._onEnter, this)
        });

        this.opts.preventClicks && this.$target.on('click.easyzoom', function(e) {
            e.preventDefault();
        });
    };

    /**
     * Show
     * @param {MouseEvent|TouchEvent} e
     * @param {Boolean} testMouseOver (Optional)
     */
    EasyZoom.prototype.show = function(e, testMouseOver) {
        var w1, h1, w2, h2;
        var self = this;

        if (this.opts.beforeShow.call(this) === false) return;

        if (!this.isReady) {
            return this._loadImage(this.$link.attr(this.opts.linkAttribute), function() {
                if (self.isMouseOver || !testMouseOver) {
                    self.show(e);
                }
            });
        }

        this.$target.append(this.$flyout);

        w1 = this.$target.width();
        h1 = this.$target.height();

        w2 = this.$flyout.width();
        h2 = this.$flyout.height();

        dw = this.$zoom.width() - w2;
        dh = this.$zoom.height() - h2;

        rw = dw / w1;
        rh = dh / h1;

        this.isOpen = true;

        this.opts.onShow.call(this);

        e && this._move(e);
    };

    /**
     * On enter
     * @private
     * @param {Event} e
     */
    EasyZoom.prototype._onEnter = function(e) {
        var touches = e.originalEvent.touches;

        this.isMouseOver = true;

        if (!touches || touches.length == 1) {
            e.preventDefault();
            this.show(e, true);
        }
    };

    /**
     * On move
     * @private
     * @param {Event} e
     */
    EasyZoom.prototype._onMove = function(e) {
        if (!this.isOpen) return;

        e.preventDefault();
        this._move(e);
    };

    /**
     * On leave
     * @private
     */
    EasyZoom.prototype._onLeave = function() {
        this.isMouseOver = false;
        this.isOpen && this.hide();
    };

    /**
     * On load
     * @private
     * @param {Event} e
     */
    EasyZoom.prototype._onLoad = function(e) {
        // IE may fire a load event even on error so test the image dimensions
        if (!e.currentTarget.width) return;

        this.isReady = true;

        this.$notice.detach();
        this.$flyout.html(this.$zoom);
        this.$target.removeClass('is-loading').addClass('is-ready');

        e.data.call && e.data();
    };

    /**
     * On error
     * @private
     */
    EasyZoom.prototype._onError = function() {
        var self = this;

        this.$notice.text(this.opts.errorNotice);
        this.$target.removeClass('is-loading').addClass('is-error');

        this.detachNotice = setTimeout(function() {
            self.$notice.detach();
            self.detachNotice = null;
        }, this.opts.errorDuration);
    };

    /**
     * Load image
     * @private
     * @param {String} href
     * @param {Function} callback
     */
    EasyZoom.prototype._loadImage = function(href, callback) {
        var zoom = new Image;

        this.$target
            .addClass('is-loading')
            .append(this.$notice.text(this.opts.loadingNotice));

        this.$zoom = $(zoom)
            .on('error', $.proxy(this._onError, this))
            .on('load', callback, $.proxy(this._onLoad, this));

        zoom.style.position = 'absolute';
        zoom.src = href;
    };

    /**
     * Move
     * @private
     * @param {Event} e
     */
    EasyZoom.prototype._move = function(e) {

        if (e.type.indexOf('touch') === 0) {
            var touchlist = e.touches || e.originalEvent.touches;
            lx = touchlist[0].pageX;
            ly = touchlist[0].pageY;
        } else {
            lx = e.pageX || lx;
            ly = e.pageY || ly;
        }

        var offset  = this.$target.offset();
        var pt = ly - offset.top;
        var pl = lx - offset.left;
        var xt = Math.ceil(pt * rh);
        var xl = Math.ceil(pl * rw);

        // Close if outside
        if (xl < 0 || xt < 0 || xl > dw || xt > dh) {
            this.hide();
        } else {
            var top = xt * -1;
            var left = xl * -1;

            this.$zoom.css({
                top: top,
                left: left
            });

            this.opts.onMove.call(this, top, left);
        }

    };

    /**
     * Hide
     */
    EasyZoom.prototype.hide = function() {
        if (!this.isOpen) return;
        if (this.opts.beforeHide.call(this) === false) return;

        this.$flyout.detach();
        this.isOpen = false;

        this.opts.onHide.call(this);
    };

    /**
     * Swap
     * @param {String} standardSrc
     * @param {String} zoomHref
     * @param {String|Array} srcset (Optional)
     */
    EasyZoom.prototype.swap = function(standardSrc, zoomHref, srcset) {
        this.hide();
        this.isReady = false;

        this.detachNotice && clearTimeout(this.detachNotice);

        this.$notice.parent().length && this.$notice.detach();

        this.$target.removeClass('is-loading is-ready is-error');

        this.$image.attr({
            src: standardSrc,
            srcset: $.isArray(srcset) ? srcset.join() : srcset
        });

        this.$link.attr(this.opts.linkAttribute, zoomHref);
    };

    /**
     * Teardown
     */
    EasyZoom.prototype.teardown = function() {
        this.hide();

        this.$target
            .off('.easyzoom')
            .removeClass('is-loading is-ready is-error');

        this.detachNotice && clearTimeout(this.detachNotice);

        delete this.$link;
        delete this.$zoom;
        delete this.$image;
        delete this.$notice;
        delete this.$flyout;

        delete this.isOpen;
        delete this.isReady;
    };

    // jQuery plugin wrapper
    $.fn.easyZoom = function(options) {
        return this.each(function() {
            var api = $.data(this, 'easyZoom');

            if (!api) {
                $.data(this, 'easyZoom', new EasyZoom(this, options));
            } else if (api.isOpen === undefined) {
                api._init();
            }
        });
    };

    // AMD and CommonJS module compatibility
    if (typeof define === 'function' && define.amd){
        define(function() {
            return EasyZoom;
        });
    } else if (typeof module !== 'undefined' && module.exports) {
        module.exports = EasyZoom;
    }

})(jQuery);

/*! jQuery Validation Plugin - v1.17.0 - 7/29/2017
 * https://jqueryvalidation.org/
 * Copyright (c) 2017 Jörn Zaefferer; Licensed MIT */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.on("click.validate",":submit",function(b){c.submitButton=b.currentTarget,a(this).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(this).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.on("submit.validate",function(b){function d(){var d,e;return c.submitButton&&(c.settings.submitHandler||c.formSubmitted)&&(d=a("<input type='hidden'/>").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!c.settings.submitHandler||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(null!=j&&(!j.form&&j.hasAttribute("contenteditable")&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}}),a.extend(a.expr.pseudos||a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){var c=a(b).val();return null!==c&&!!a.trim(""+c)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){!this.form&&this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name"));var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0],this.name=d),!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type;return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=b.hasAttribute("contenteditable")?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);if("function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f){if(j=f.call(b,j),"string"!=typeof j)throw new TypeError("The normalizer should return a string value.");delete g.normalizer}for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=".  Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]},defaultMessage:function(b,c){"string"==typeof c&&(c={method:c});var d=this.findDefined(this.customMessage(b.name,c.method),this.customDataMessage(b,c.method),!this.settings.ignoreTitle&&b.title||void 0,a.validator.messages[c.method],"<strong>Warning: No message defined for "+b.name+"</strong>"),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,.\/:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[\/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e<=d},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var b,c={};return a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)}),a});
/*! jQuery Validation Plugin - v1.17.0 - 7/29/2017
 * https://jqueryvalidation.org/
 * Copyright (c) 2017 Jörn Zaefferer; Licensed MIT */
!function(a){"function"==typeof define&&define.amd?define(["jquery","./jquery.validate.min"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){return function(){function b(a){return a.replace(/<.[^<>]*?>/g," ").replace(/&nbsp;|&#160;/gi," ").replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g,"")}a.validator.addMethod("maxWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length<=d},a.validator.format("Please enter {0} words or less.")),a.validator.addMethod("minWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length>=d},a.validator.format("Please enter at least {0} words.")),a.validator.addMethod("rangeWords",function(a,c,d){var e=b(a),f=/\b\w+\b/g;return this.optional(c)||e.match(f).length>=d[0]&&e.match(f).length<=d[1]},a.validator.format("Please enter between {0} and {1} words."))}(),a.validator.addMethod("accept",function(b,c,d){var e,f,g,h="string"==typeof d?d.replace(/\s/g,""):"image/*",i=this.optional(c);if(i)return i;if("file"===a(c).attr("type")&&(h=h.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$\|]/g,"\\$&").replace(/,/g,"|").replace(/\/\*/g,"/.*"),c.files&&c.files.length))for(g=new RegExp(".?("+h+")$","i"),e=0;e<c.files.length;e++)if(f=c.files[e],!f.type.match(g))return!1;return!0},a.validator.format("Please enter a value with a valid mimetype.")),a.validator.addMethod("alphanumeric",function(a,b){return this.optional(b)||/^\w+$/i.test(a)},"Letters, numbers, and underscores only please"),a.validator.addMethod("bankaccountNL",function(a,b){if(this.optional(b))return!0;if(!/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(a))return!1;var c,d,e,f=a.replace(/ /g,""),g=0,h=f.length;for(c=0;c<h;c++)d=h-c,e=f.substring(c,c+1),g+=d*e;return g%11===0},"Please specify a valid bank account number"),a.validator.addMethod("bankorgiroaccountNL",function(b,c){return this.optional(c)||a.validator.methods.bankaccountNL.call(this,b,c)||a.validator.methods.giroaccountNL.call(this,b,c)},"Please specify a valid bank or giro account number"),a.validator.addMethod("bic",function(a,b){return this.optional(b)||/^([A-Z]{6}[A-Z2-9][A-NP-Z1-9])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test(a.toUpperCase())},"Please specify a valid BIC code"),a.validator.addMethod("cifES",function(a,b){"use strict";function c(a){return a%2===0}if(this.optional(b))return!0;var d,e,f,g,h=new RegExp(/^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/gi),i=a.substring(0,1),j=a.substring(1,8),k=a.substring(8,9),l=0,m=0,n=0;if(9!==a.length||!h.test(a))return!1;for(d=0;d<j.length;d++)e=parseInt(j[d],10),c(d)?(e*=2,n+=e<10?e:e-9):m+=e;return l=m+n,f=(10-l.toString().substr(-1)).toString(),f=parseInt(f,10)>9?"0":f,g="JABCDEFGHI".substr(f,1).toString(),i.match(/[ABEH]/)?k===f:i.match(/[KPQS]/)?k===g:k===f||k===g},"Please specify a valid CIF number."),a.validator.addMethod("cpfBR",function(a){if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var b,c,d,e,f=0;if(b=parseInt(a.substring(9,10),10),c=parseInt(a.substring(10,11),10),d=function(a,b){var c=10*a%11;return 10!==c&&11!==c||(c=0),c===b},""===a||"00000000000"===a||"11111111111"===a||"22222222222"===a||"33333333333"===a||"44444444444"===a||"55555555555"===a||"66666666666"===a||"77777777777"===a||"88888888888"===a||"99999999999"===a)return!1;for(e=1;e<=9;e++)f+=parseInt(a.substring(e-1,e),10)*(11-e);if(d(f,b)){for(f=0,e=1;e<=10;e++)f+=parseInt(a.substring(e-1,e),10)*(12-e);return d(f,c)}return!1},"Please specify a valid CPF number"),a.validator.addMethod("creditcard",function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},"Please enter a valid credit card number."),a.validator.addMethod("creditcardtypes",function(a,b,c){if(/[^0-9\-]+/.test(a))return!1;a=a.replace(/\D/g,"");var d=0;return c.mastercard&&(d|=1),c.visa&&(d|=2),c.amex&&(d|=4),c.dinersclub&&(d|=8),c.enroute&&(d|=16),c.discover&&(d|=32),c.jcb&&(d|=64),c.unknown&&(d|=128),c.all&&(d=255),1&d&&/^(5[12345])/.test(a)?16===a.length:2&d&&/^(4)/.test(a)?16===a.length:4&d&&/^(3[47])/.test(a)?15===a.length:8&d&&/^(3(0[012345]|[68]))/.test(a)?14===a.length:16&d&&/^(2(014|149))/.test(a)?15===a.length:32&d&&/^(6011)/.test(a)?16===a.length:64&d&&/^(3)/.test(a)?16===a.length:64&d&&/^(2131|1800)/.test(a)?15===a.length:!!(128&d)},"Please enter a valid credit card number."),a.validator.addMethod("currency",function(a,b,c){var d,e="string"==typeof c,f=e?c:c[0],g=!!e||c[1];return f=f.replace(/,/g,""),f=g?f+"]":f+"]?",d="^["+f+"([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$",d=new RegExp(d),this.optional(b)||d.test(a)},"Please specify a valid currency"),a.validator.addMethod("dateFA",function(a,b){return this.optional(b)||/^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(a)},a.validator.messages.date),a.validator.addMethod("dateITA",function(a,b){var c,d,e,f,g,h=!1,i=/^\d{1,2}\/\d{1,2}\/\d{4}$/;return i.test(a)?(c=a.split("/"),d=parseInt(c[0],10),e=parseInt(c[1],10),f=parseInt(c[2],10),g=new Date(Date.UTC(f,e-1,d,12,0,0,0)),h=g.getUTCFullYear()===f&&g.getUTCMonth()===e-1&&g.getUTCDate()===d):h=!1,this.optional(b)||h},a.validator.messages.date),a.validator.addMethod("dateNL",function(a,b){return this.optional(b)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(a)},a.validator.messages.date),a.validator.addMethod("extension",function(a,b,c){return c="string"==typeof c?c.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(b)||a.match(new RegExp("\\.("+c+")$","i"))},a.validator.format("Please enter a value with a valid extension.")),a.validator.addMethod("giroaccountNL",function(a,b){return this.optional(b)||/^[0-9]{1,7}$/.test(a)},"Please specify a valid giro account number"),a.validator.addMethod("iban",function(a,b){if(this.optional(b))return!0;var c,d,e,f,g,h,i,j,k,l=a.replace(/ /g,"").toUpperCase(),m="",n=!0,o="",p="",q=5;if(l.length<q)return!1;if(c=l.substring(0,2),h={AL:"\\d{8}[\\dA-Z]{16}",AD:"\\d{8}[\\dA-Z]{12}",AT:"\\d{16}",AZ:"[\\dA-Z]{4}\\d{20}",BE:"\\d{12}",BH:"[A-Z]{4}[\\dA-Z]{14}",BA:"\\d{16}",BR:"\\d{23}[A-Z][\\dA-Z]",BG:"[A-Z]{4}\\d{6}[\\dA-Z]{8}",CR:"\\d{17}",HR:"\\d{17}",CY:"\\d{8}[\\dA-Z]{16}",CZ:"\\d{20}",DK:"\\d{14}",DO:"[A-Z]{4}\\d{20}",EE:"\\d{16}",FO:"\\d{14}",FI:"\\d{14}",FR:"\\d{10}[\\dA-Z]{11}\\d{2}",GE:"[\\dA-Z]{2}\\d{16}",DE:"\\d{18}",GI:"[A-Z]{4}[\\dA-Z]{15}",GR:"\\d{7}[\\dA-Z]{16}",GL:"\\d{14}",GT:"[\\dA-Z]{4}[\\dA-Z]{20}",HU:"\\d{24}",IS:"\\d{22}",IE:"[\\dA-Z]{4}\\d{14}",IL:"\\d{19}",IT:"[A-Z]\\d{10}[\\dA-Z]{12}",KZ:"\\d{3}[\\dA-Z]{13}",KW:"[A-Z]{4}[\\dA-Z]{22}",LV:"[A-Z]{4}[\\dA-Z]{13}",LB:"\\d{4}[\\dA-Z]{20}",LI:"\\d{5}[\\dA-Z]{12}",LT:"\\d{16}",LU:"\\d{3}[\\dA-Z]{13}",MK:"\\d{3}[\\dA-Z]{10}\\d{2}",MT:"[A-Z]{4}\\d{5}[\\dA-Z]{18}",MR:"\\d{23}",MU:"[A-Z]{4}\\d{19}[A-Z]{3}",MC:"\\d{10}[\\dA-Z]{11}\\d{2}",MD:"[\\dA-Z]{2}\\d{18}",ME:"\\d{18}",NL:"[A-Z]{4}\\d{10}",NO:"\\d{11}",PK:"[\\dA-Z]{4}\\d{16}",PS:"[\\dA-Z]{4}\\d{21}",PL:"\\d{24}",PT:"\\d{21}",RO:"[A-Z]{4}[\\dA-Z]{16}",SM:"[A-Z]\\d{10}[\\dA-Z]{12}",SA:"\\d{2}[\\dA-Z]{18}",RS:"\\d{18}",SK:"\\d{20}",SI:"\\d{15}",ES:"\\d{20}",SE:"\\d{20}",CH:"\\d{5}[\\dA-Z]{12}",TN:"\\d{20}",TR:"\\d{5}[\\dA-Z]{17}",AE:"\\d{3}\\d{16}",GB:"[A-Z]{4}\\d{14}",VG:"[\\dA-Z]{4}\\d{16}"},g=h[c],"undefined"!=typeof g&&(i=new RegExp("^[A-Z]{2}\\d{2}"+g+"$",""),!i.test(l)))return!1;for(d=l.substring(4,l.length)+l.substring(0,4),j=0;j<d.length;j++)e=d.charAt(j),"0"!==e&&(n=!1),n||(m+="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(e));for(k=0;k<m.length;k++)f=m.charAt(k),p=""+o+f,o=p%97;return 1===o},"Please specify a valid IBAN"),a.validator.addMethod("integer",function(a,b){return this.optional(b)||/^-?\d+$/.test(a)},"A positive or negative non-decimal number please"),a.validator.addMethod("ipv4",function(a,b){return this.optional(b)||/^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(a)},"Please enter a valid IP v4 address."),a.validator.addMethod("ipv6",function(a,b){return this.optional(b)||/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(a)},"Please enter a valid IP v6 address."),a.validator.addMethod("lettersonly",function(a,b){return this.optional(b)||/^[a-z]+$/i.test(a)},"Letters only please"),a.validator.addMethod("letterswithbasicpunc",function(a,b){return this.optional(b)||/^[a-z\-.,()'"\s]+$/i.test(a)},"Letters or punctuation only please"),a.validator.addMethod("mobileNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid mobile number"),a.validator.addMethod("mobileUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("netmask",function(a,b){return this.optional(b)||/^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(254|252|248|240|224|192|128|0)/i.test(a)},"Please enter a valid netmask."),a.validator.addMethod("nieES",function(a,b){"use strict";if(this.optional(b))return!0;var c,d=new RegExp(/^[MXYZ]{1}[0-9]{7,8}[TRWAGMYFPDXBNJZSQVHLCKET]{1}$/gi),e="TRWAGMYFPDXBNJZSQVHLCKET",f=a.substr(a.length-1).toUpperCase();return a=a.toString().toUpperCase(),!(a.length>10||a.length<9||!d.test(a))&&(a=a.replace(/^[X]/,"0").replace(/^[Y]/,"1").replace(/^[Z]/,"2"),c=9===a.length?a.substr(0,8):a.substr(0,9),e.charAt(parseInt(c,10)%23)===f)},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a,b){"use strict";return!!this.optional(b)||(a=a.toUpperCase(),!!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")&&(/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):!!/^[KLM]{1}/.test(a)&&a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,1)%23)))},"Please specify a valid NIF number."),a.validator.addMethod("nipPL",function(a){"use strict";if(a=a.replace(/[^0-9]/g,""),10!==a.length)return!1;for(var b=[6,5,7,2,3,4,5,6,7],c=0,d=0;d<9;d++)c+=b[d]*a[d];var e=c%11,f=10===e?0:e;return f===parseInt(a[9],10)},"Please specify a valid NIP number."),a.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return!!this.optional(b)||("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ] *\d[ABCEGHJKLMNPRSTVWXYZ]\d$/i.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=!e&&"undefined"!=typeof c.caseSensitive&&c.caseSensitive,g=!e&&"undefined"!=typeof c.includeTerritories&&c.includeTerritories,h=!e&&"undefined"!=typeof c.includeMilitary&&c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;b<17;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c<h.length;c++)if(d.toUpperCase()===h[c]){d=i[c],d*=e,isNaN(g)&&8===c&&(g=h[c]);break}}else d*=e;k+=d}return f=k%11,10===f&&(f="X"),f===g},"The specified vehicle identification number (VIN) is invalid."),a.validator.addMethod("zipcodeUS",function(a,b){return this.optional(b)||/^\d{5}(-\d{4})?$/.test(a)},"The specified US ZIP Code is invalid"),a.validator.addMethod("ziprange",function(a,b){return this.optional(b)||/^90[2-5]\d\{2\}-\d{4}$/.test(a)},"Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx"),a});
/*!@license Copyright 2013, Heinrich Goebl, License: MIT, see https://github.com/hgoebl/mobile-detect.js*/
!function(a,b){a(function(){"use strict";function a(a,b){return null!=a&&null!=b&&a.toLowerCase()===b.toLowerCase()}function c(a,b){var c,d,e=a.length;if(!e||!b)return!1;for(c=b.toLowerCase(),d=0;d<e;++d)if(c===a[d].toLowerCase())return!0;return!1}function d(a){for(var b in a)h.call(a,b)&&(a[b]=new RegExp(a[b],"i"))}function e(a,b){this.ua=a||"",this._cache={},this.maxPhoneWidth=b||600}var f={};f.mobileDetectRules={phones:{iPhone:"\\biPhone\\b|\\biPod\\b",BlackBerry:"BlackBerry|\\bBB10\\b|rim[0-9]+",HTC:"HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\\bEVO\\b|T-Mobile G1|Z520m",Nexus:"Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6",Dell:"Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\\b001DL\\b|\\b101DL\\b|\\bGS01\\b",Motorola:"Motorola|DROIDX|DROID BIONIC|\\bDroid\\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\\bMoto E\\b",Samsung:"\\bSamsung\\b|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F",LG:"\\bLG\\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323)",Sony:"SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533",Asus:"Asus.*Galaxy|PadFone.*Mobile",NokiaLumia:"Lumia [0-9]{3,4}",Micromax:"Micromax.*\\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\\b",Palm:"PalmSource|Palm",Vertu:"Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature",Pantech:"PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790",Fly:"IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250",Wiko:"KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM",iMobile:"i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)",SimValley:"\\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\\b",Wolfgang:"AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q",Alcatel:"Alcatel",Nintendo:"Nintendo 3DS",Amoi:"Amoi",INQ:"INQ",GenericPhone:"Tapatalk|PDA;|SAGEM|\\bmmp\\b|pocket|\\bpsp\\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\\bwap\\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser"},tablets:{iPad:"iPad|iPad.*Mobile",NexusTablet:"Android.*Nexus[\\s]+(7|9|10)",SamsungTablet:"SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y|SM-T280",Kindle:"Kindle|Silk.*Accelerated|Android.*\\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI)\\b",SurfaceTablet:"Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)",HPTablet:"HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10",AsusTablet:"^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\\bK00F\\b|\\bK00C\\b|\\bK00E\\b|\\bK00L\\b|TX201LA|ME176C|ME102A|\\bM80TA\\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\\bME70C\\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z",BlackBerryTablet:"PlayBook|RIM Tablet",HTCtablet:"HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410",MotorolaTablet:"xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617",NookTablet:"Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2",AcerTablet:"Android.*; \\b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\\b|W3-810|\\bA3-A10\\b|\\bA3-A11\\b|\\bA3-A20\\b|\\bA3-A30",ToshibaTablet:"Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO",LGTablet:"\\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\\b",FujitsuTablet:"Android.*\\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\\b",PrestigioTablet:"PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002",LenovoTablet:"Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)",DellTablet:"Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7",YarvikTablet:"Android.*\\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\\b",MedionTablet:"Android.*\\bOYO\\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB",ArnovaTablet:"97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2",IntensoTablet:"INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004",IRUTablet:"M702pro",MegafonTablet:"MegaFon V9|\\bZTE V9\\b|Android.*\\bMT7A\\b",EbodaTablet:"E-Boda (Supreme|Impresspeed|Izzycomm|Essential)",AllViewTablet:"Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)",ArchosTablet:"\\b(101G9|80G9|A101IT)\\b|Qilive 97R|Archos5|\\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\\b",AinolTablet:"NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark",NokiaLumiaTablet:"Lumia 2520",SonyTablet:"Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP612|SOT31",PhilipsTablet:"\\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\\b",CubeTablet:"Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT",CobyTablet:"MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010",MIDTablet:"M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10",MSITablet:"MSI \\b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\\b",SMiTTablet:"Android.*(\\bMID\\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)",RockChipTablet:"Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A",FlyTablet:"IQ310|Fly Vision",bqTablet:"Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris [E|M]10)|Maxwell.*Lite|Maxwell.*Plus",HuaweiTablet:"MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim",NecTablet:"\\bN-06D|\\bN-08D",PantechTablet:"Pantech.*P4100",BronchoTablet:"Broncho.*(N701|N708|N802|a710)",VersusTablet:"TOUCHPAD.*[78910]|\\bTOUCHTAB\\b",ZyncTablet:"z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900",PositivoTablet:"TB07STA|TB10STA|TB07FTA|TB10FTA",NabiTablet:"Android.*\\bNabi",KoboTablet:"Kobo Touch|\\bK080\\b|\\bVox\\b Build|\\bArc\\b Build",DanewTablet:"DSlide.*\\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\\b",TexetTablet:"NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE",PlaystationTablet:"Playstation.*(Portable|Vita)",TrekstorTablet:"ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab",PyleAudioTablet:"\\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\\b",AdvanTablet:"Android.* \\b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\\b ",DanyTechTablet:"Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1",GalapadTablet:"Android.*\\bG1\\b",MicromaxTablet:"Funbook|Micromax.*\\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\\b",KarbonnTablet:"Android.*\\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\\b",AllFineTablet:"Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide",PROSCANTablet:"\\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\\b",YONESTablet:"BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026",ChangJiaTablet:"TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503",GUTablet:"TX-A1301|TX-M9002|Q702|kf026",PointOfViewTablet:"TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10",OvermaxTablet:"OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)",HCLTablet:"HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync",DPSTablet:"DPS Dream 9|DPS Dual 7",VistureTablet:"V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10",CrestaTablet:"CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989",MediatekTablet:"\\bMT8125|MT8389|MT8135|MT8377\\b",ConcordeTablet:"Concorde([ ]+)?Tab|ConCorde ReadMan",GoCleverTablet:"GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042",ModecomTablet:"FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003",VoninoTablet:"\\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\\bQ8\\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\\b",ECSTablet:"V07OT2|TM105A|S10OT1|TR10CS1",StorexTablet:"eZee[_']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab",VodafoneTablet:"SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497",EssentielBTablet:"Smart[ ']?TAB[ ]+?[0-9]+|Family[ ']?TAB2",RossMoorTablet:"RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711",iMobileTablet:"i-mobile i-note",TolinoTablet:"tolino tab [0-9.]+|tolino shine",AudioSonicTablet:"\\bC-22Q|T7-QC|T-17B|T-17P\\b",AMPETablet:"Android.* A78 ",SkkTablet:"Android.* (SKYPAD|PHOENIX|CYCLOPS)",TecnoTablet:"TECNO P9",JXDTablet:"Android.* \\b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\\b",iJoyTablet:"Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)",FX2Tablet:"FX2 PAD7|FX2 PAD10",XoroTablet:"KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151",ViewsonicTablet:"ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a",OdysTablet:"LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\\bXELIO\\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10",CaptivaTablet:"CAPTIVA PAD",IconbitTablet:"NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S",TeclastTablet:"T98 4G|\\bP80\\b|\\bX90HD\\b|X98 Air|X98 Air 3G|\\bX89\\b|P80 3G|\\bX80h\\b|P98 Air|\\bX89HD\\b|P98 3G|\\bP90HD\\b|P89 3G|X98 3G|\\bP70h\\b|P79HD 3G|G18d 3G|\\bP79HD\\b|\\bP89s\\b|\\bA88\\b|\\bP10HD\\b|\\bP19HD\\b|G18 3G|\\bP78HD\\b|\\bA78\\b|\\bP75\\b|G17s 3G|G17h 3G|\\bP85t\\b|\\bP90\\b|\\bP11\\b|\\bP98t\\b|\\bP98HD\\b|\\bG18d\\b|\\bP85s\\b|\\bP11HD\\b|\\bP88s\\b|\\bA80HD\\b|\\bA80se\\b|\\bA10h\\b|\\bP89\\b|\\bP78s\\b|\\bG18\\b|\\bP85\\b|\\bA70h\\b|\\bA70\\b|\\bG17\\b|\\bP18\\b|\\bA80s\\b|\\bA11s\\b|\\bP88HD\\b|\\bA80h\\b|\\bP76s\\b|\\bP76h\\b|\\bP98\\b|\\bA10HD\\b|\\bP78\\b|\\bP88\\b|\\bA11\\b|\\bA10t\\b|\\bP76a\\b|\\bP76t\\b|\\bP76e\\b|\\bP85HD\\b|\\bP85a\\b|\\bP86\\b|\\bP75HD\\b|\\bP76v\\b|\\bA12\\b|\\bP75a\\b|\\bA15\\b|\\bP76Ti\\b|\\bP81HD\\b|\\bA10\\b|\\bT760VE\\b|\\bT720HD\\b|\\bP76\\b|\\bP73\\b|\\bP71\\b|\\bP72\\b|\\bT720SE\\b|\\bC520Ti\\b|\\bT760\\b|\\bT720VE\\b|T720-3GE|T720-WiFi",OndaTablet:"\\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\\b[\\s]+",JaytechTablet:"TPC-PA762",BlaupunktTablet:"Endeavour 800NG|Endeavour 1010",DigmaTablet:"\\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\\b",EvolioTablet:"ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\\bEvotab\\b|\\bNeura\\b",LavaTablet:"QPAD E704|\\bIvoryS\\b|E-TAB IVORY|\\bE-TAB\\b",AocTablet:"MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712",MpmanTablet:"MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\\bMPG7\\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010",CelkonTablet:"CT695|CT888|CT[\\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\\bCT-1\\b",WolderTablet:"miTab \\b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\\b",MiTablet:"\\bMI PAD\\b|\\bHM NOTE 1W\\b",NibiruTablet:"Nibiru M1|Nibiru Jupiter One",NexoTablet:"NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI",LeaderTablet:"TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100",UbislateTablet:"UbiSlate[\\s]?7C",PocketBookTablet:"Pocketbook",KocasoTablet:"\\b(TB-1207)\\b",HisenseTablet:"\\b(F5281|E2371)\\b",Hudl:"Hudl HT7S3|Hudl 2",TelstraTablet:"T-Hub2",GenericTablet:"Android.*\\b97D\\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\\bA7EB\\b|CatNova8|A1_07|CT704|CT1002|\\bM721\\b|rk30sdk|\\bEVOTAB\\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\\bM6pro\\b|CT1020W|arc 10HD|\\bTP750\\b"},oss:{AndroidOS:"Android",BlackBerryOS:"blackberry|\\bBB10\\b|rim tablet os",PalmOS:"PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino",SymbianOS:"Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\\bS60\\b",WindowsMobileOS:"Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;",WindowsPhoneOS:"Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;",iOS:"\\biPhone.*Mobile|\\biPod|\\biPad",MeeGoOS:"MeeGo",MaemoOS:"Maemo",JavaOS:"J2ME/|\\bMIDP\\b|\\bCLDC\\b",webOS:"webOS|hpwOS",badaOS:"\\bBada\\b",BREWOS:"BREW"},uas:{Chrome:"\\bCrMo\\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?",Dolfin:"\\bDolfin\\b",Opera:"Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+",Skyfire:"Skyfire",Edge:"Mobile Safari/[.0-9]* Edge",IE:"IEMobile|MSIEMobile",Firefox:"fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS",Bolt:"bolt",TeaShark:"teashark",Blazer:"Blazer",Safari:"Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari",UCBrowser:"UC.*Browser|UCWEB",baiduboxapp:"baiduboxapp",baidubrowser:"baidubrowser",DiigoBrowser:"DiigoBrowser",Puffin:"Puffin",Mercury:"\\bMercury\\b",ObigoBrowser:"Obigo",NetFront:"NF-Browser",GenericBrowser:"NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger",PaleMoon:"Android.*PaleMoon|Mobile.*PaleMoon"},props:{Mobile:"Mobile/[VER]",Build:"Build/[VER]",Version:"Version/[VER]",VendorID:"VendorID/[VER]",iPad:"iPad.*CPU[a-z ]+[VER]",iPhone:"iPhone.*CPU[a-z ]+[VER]",iPod:"iPod.*CPU[a-z ]+[VER]",Kindle:"Kindle/[VER]",Chrome:["Chrome/[VER]","CriOS/[VER]","CrMo/[VER]"],Coast:["Coast/[VER]"],Dolfin:"Dolfin/[VER]",Firefox:["Firefox/[VER]","FxiOS/[VER]"],Fennec:"Fennec/[VER]",Edge:"Edge/[VER]",IE:["IEMobile/[VER];","IEMobile [VER]","MSIE [VER];","Trident/[0-9.]+;.*rv:[VER]"],NetFront:"NetFront/[VER]",NokiaBrowser:"NokiaBrowser/[VER]",Opera:[" OPR/[VER]","Opera Mini/[VER]","Version/[VER]"],"Opera Mini":"Opera Mini/[VER]","Opera Mobi":"Version/[VER]","UC Browser":"UC Browser[VER]",MQQBrowser:"MQQBrowser/[VER]",MicroMessenger:"MicroMessenger/[VER]",baiduboxapp:"baiduboxapp/[VER]",baidubrowser:"baidubrowser/[VER]",SamsungBrowser:"SamsungBrowser/[VER]",Iron:"Iron/[VER]",Safari:["Version/[VER]","Safari/[VER]"],Skyfire:"Skyfire/[VER]",Tizen:"Tizen/[VER]",Webkit:"webkit[ /][VER]",PaleMoon:"PaleMoon/[VER]",Gecko:"Gecko/[VER]",Trident:"Trident/[VER]",Presto:"Presto/[VER]",Goanna:"Goanna/[VER]",iOS:" \\bi?OS\\b [VER][ ;]{1}",Android:"Android [VER]",BlackBerry:["BlackBerry[\\w]+/[VER]","BlackBerry.*Version/[VER]","Version/[VER]"],BREW:"BREW [VER]",Java:"Java/[VER]","Windows Phone OS":["Windows Phone OS [VER]","Windows Phone [VER]"],"Windows Phone":"Windows Phone [VER]","Windows CE":"Windows CE/[VER]","Windows NT":"Windows NT [VER]",Symbian:["SymbianOS/[VER]","Symbian/[VER]"],webOS:["webOS/[VER]","hpwOS/[VER];"]},utils:{Bot:"Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom",MobileBot:"Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2",DesktopMode:"WPDesktop",TV:"SonyDTV|HbbTV",WebKit:"(webkit)[ /]([\\w.]+)",Console:"\\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\\b",Watch:"SM-V700"}},f.detectMobileBrowsers={fullPattern:/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i,shortPattern:/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i,tabletPattern:/android|ipad|playbook|silk/i};var g,h=Object.prototype.hasOwnProperty;return f.FALLBACK_PHONE="UnknownPhone",f.FALLBACK_TABLET="UnknownTablet",f.FALLBACK_MOBILE="UnknownMobile",g="isArray"in Array?Array.isArray:function(a){return"[object Array]"===Object.prototype.toString.call(a)},function(){var a,b,c,e,i,j,k=f.mobileDetectRules;for(a in k.props)if(h.call(k.props,a)){for(b=k.props[a],g(b)||(b=[b]),i=b.length,e=0;e<i;++e)c=b[e],j=c.indexOf("[VER]"),j>=0&&(c=c.substring(0,j)+"([\\w._\\+]+)"+c.substring(j+5)),b[e]=new RegExp(c,"i");k.props[a]=b}d(k.oss),d(k.phones),d(k.tablets),d(k.uas),d(k.utils),k.oss0={WindowsPhoneOS:k.oss.WindowsPhoneOS,WindowsMobileOS:k.oss.WindowsMobileOS}}(),f.findMatch=function(a,b){for(var c in a)if(h.call(a,c)&&a[c].test(b))return c;return null},f.findMatches=function(a,b){var c=[];for(var d in a)h.call(a,d)&&a[d].test(b)&&c.push(d);return c},f.getVersionStr=function(a,b){var c,d,e,g,i=f.mobileDetectRules.props;if(h.call(i,a))for(c=i[a],e=c.length,d=0;d<e;++d)if(g=c[d].exec(b),null!==g)return g[1];return null},f.getVersion=function(a,b){var c=f.getVersionStr(a,b);return c?f.prepareVersionNo(c):NaN},f.prepareVersionNo=function(a){var b;return b=a.split(/[a-z._ \/\-]/i),1===b.length&&(a=b[0]),b.length>1&&(a=b[0]+".",b.shift(),a+=b.join("")),Number(a)},f.isMobileFallback=function(a){return f.detectMobileBrowsers.fullPattern.test(a)||f.detectMobileBrowsers.shortPattern.test(a.substr(0,4))},f.isTabletFallback=function(a){return f.detectMobileBrowsers.tabletPattern.test(a)},f.prepareDetectionCache=function(a,c,d){if(a.mobile===b){var g,h,i;return(h=f.findMatch(f.mobileDetectRules.tablets,c))?(a.mobile=a.tablet=h,void(a.phone=null)):(g=f.findMatch(f.mobileDetectRules.phones,c))?(a.mobile=a.phone=g,void(a.tablet=null)):void(f.isMobileFallback(c)?(i=e.isPhoneSized(d),i===b?(a.mobile=f.FALLBACK_MOBILE,a.tablet=a.phone=null):i?(a.mobile=a.phone=f.FALLBACK_PHONE,a.tablet=null):(a.mobile=a.tablet=f.FALLBACK_TABLET,a.phone=null)):f.isTabletFallback(c)?(a.mobile=a.tablet=f.FALLBACK_TABLET,a.phone=null):a.mobile=a.tablet=a.phone=null)}},f.mobileGrade=function(a){var b=null!==a.mobile();return a.os("iOS")&&a.version("iPad")>=4.3||a.os("iOS")&&a.version("iPhone")>=3.1||a.os("iOS")&&a.version("iPod")>=3.1||a.version("Android")>2.1&&a.is("Webkit")||a.version("Windows Phone OS")>=7||a.is("BlackBerry")&&a.version("BlackBerry")>=6||a.match("Playbook.*Tablet")||a.version("webOS")>=1.4&&a.match("Palm|Pre|Pixi")||a.match("hp.*TouchPad")||a.is("Firefox")&&a.version("Firefox")>=12||a.is("Chrome")&&a.is("AndroidOS")&&a.version("Android")>=4||a.is("Skyfire")&&a.version("Skyfire")>=4.1&&a.is("AndroidOS")&&a.version("Android")>=2.3||a.is("Opera")&&a.version("Opera Mobi")>11&&a.is("AndroidOS")||a.is("MeeGoOS")||a.is("Tizen")||a.is("Dolfin")&&a.version("Bada")>=2||(a.is("UC Browser")||a.is("Dolfin"))&&a.version("Android")>=2.3||a.match("Kindle Fire")||a.is("Kindle")&&a.version("Kindle")>=3||a.is("AndroidOS")&&a.is("NookTablet")||a.version("Chrome")>=11&&!b||a.version("Safari")>=5&&!b||a.version("Firefox")>=4&&!b||a.version("MSIE")>=7&&!b||a.version("Opera")>=10&&!b?"A":a.os("iOS")&&a.version("iPad")<4.3||a.os("iOS")&&a.version("iPhone")<3.1||a.os("iOS")&&a.version("iPod")<3.1||a.is("Blackberry")&&a.version("BlackBerry")>=5&&a.version("BlackBerry")<6||a.version("Opera Mini")>=5&&a.version("Opera Mini")<=6.5&&(a.version("Android")>=2.3||a.is("iOS"))||a.match("NokiaN8|NokiaC7|N97.*Series60|Symbian/3")||a.version("Opera Mobi")>=11&&a.is("SymbianOS")?"B":(a.version("BlackBerry")<5||a.match("MSIEMobile|Windows CE.*Mobile")||a.version("Windows Mobile")<=5.2,"C")},f.detectOS=function(a){return f.findMatch(f.mobileDetectRules.oss0,a)||f.findMatch(f.mobileDetectRules.oss,a)},f.getDeviceSmallerSide=function(){return window.screen.width<window.screen.height?window.screen.width:window.screen.height},e.prototype={constructor:e,mobile:function(){return f.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.mobile},phone:function(){return f.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.phone},tablet:function(){return f.prepareDetectionCache(this._cache,this.ua,this.maxPhoneWidth),this._cache.tablet},userAgent:function(){return this._cache.userAgent===b&&(this._cache.userAgent=f.findMatch(f.mobileDetectRules.uas,this.ua)),this._cache.userAgent},userAgents:function(){return this._cache.userAgents===b&&(this._cache.userAgents=f.findMatches(f.mobileDetectRules.uas,this.ua)),this._cache.userAgents},os:function(){return this._cache.os===b&&(this._cache.os=f.detectOS(this.ua)),this._cache.os},version:function(a){return f.getVersion(a,this.ua)},versionStr:function(a){return f.getVersionStr(a,this.ua)},is:function(b){return c(this.userAgents(),b)||a(b,this.os())||a(b,this.phone())||a(b,this.tablet())||c(f.findMatches(f.mobileDetectRules.utils,this.ua),b)},match:function(a){return a instanceof RegExp||(a=new RegExp(a,"i")),a.test(this.ua)},isPhoneSized:function(a){return e.isPhoneSized(a||this.maxPhoneWidth)},mobileGrade:function(){return this._cache.grade===b&&(this._cache.grade=f.mobileGrade(this)),this._cache.grade}},"undefined"!=typeof window&&window.screen?e.isPhoneSized=function(a){return a<0?b:f.getDeviceSmallerSide()<=a}:e.isPhoneSized=function(){},e._impl=f,e.version="1.3.5 2016-11-14",e})}(function(a){if("undefined"!=typeof module&&module.exports)return function(a){module.exports=a()};if("function"==typeof define&&define.amd)return define;if("undefined"!=typeof window)return function(a){window.MobileDetect=a()};throw new Error("unknown environment")}());var EVO=window.EVO||{};EVO.Config=$.extend(!0,{debug:!1,chatbot:{regex:/Chatbot/},sitemap:{scrollToSiteMap:!0,animation:{toogleDuration:300,scrollDuration:500}},navi:{animation:{duration:250}},slider:{animation:{type:'slide',slideshowSpeed:12000}},contactPerson:{animation:{duration:250}},login:{mehrwert:{authUrl:'typo3conf/ext/bb_contentobject/Resources/Public/Scripts/LoginMehrWert.php',loginUrl:'https://evo-ag.plusservices.de/110?external-token=',notAvailableMessage:'Service ist zur Zeit nicht verfügbar.'}},maps:{region:'de',center:{lat:50.111018,lng:8.743881},marker:'fileadmin/evo/assets/img/png/maps-marker.png',styles:[{"featureType":"administrative.locality","elementType":"all","stylers":[{"hue":"#2c2e33"},{"saturation":7},{"lightness":19},{"visibility":"on"}]},{"featureType":"landscape","elementType":"all","stylers":[{"hue":"#ffffff"},{"saturation":-100},{"lightness":100},{"visibility":"simplified"}]},{"featureType":"landscape.man_made","elementType":"geometry.fill","stylers":[{"lightness":"-4"},{"color":"#f6f6f6"}]},{"featureType":"poi","elementType":"all","stylers":[{"hue":"#ffffff"},{"saturation":-100},{"lightness":100},{"visibility":"off"}]},{"featureType":"poi.business","elementType":"labels","stylers":[{"visibility":"on"}]},{"featureType":"poi.business","elementType":"labels.text.fill","stylers":[{"color":"#494948"}]},{"featureType":"poi.business","elementType":"labels.text.stroke","stylers":[{"visibility":"on"}]},{"featureType":"poi.business","elementType":"labels.icon","stylers":[{"visibility":"on"}]},{"featureType":"road","elementType":"geometry","stylers":[{"hue":"#bbc0c4"},{"saturation":-93},{"lightness":31},{"visibility":"simplified"}]},{"featureType":"road","elementType":"geometry.fill","stylers":[{"lightness":"0"},{"color":"#d3d3d3"}]},{"featureType":"road","elementType":"labels","stylers":[{"hue":"#bbc0c4"},{"saturation":-93},{"lightness":31},{"visibility":"on"}]},{"featureType":"road.arterial","elementType":"geometry.fill","stylers":[{"color":"#e7ecf4"}]},{"featureType":"road.arterial","elementType":"labels","stylers":[{"hue":"#bbc0c4"},{"saturation":-93},{"lightness":-2},{"visibility":"simplified"}]},{"featureType":"road.local","elementType":"geometry","stylers":[{"hue":"#e9ebed"},{"saturation":-90},{"lightness":-8},{"visibility":"simplified"}]},{"featureType":"road.local","elementType":"geometry.fill","stylers":[{"lightness":"100"}]},{"featureType":"transit","elementType":"all","stylers":[{"hue":"#e9ebed"},{"saturation":10},{"lightness":69},{"visibility":"on"}]},{"featureType":"water","elementType":"all","stylers":[{"hue":"#e9ebed"},{"saturation":-78},{"lightness":67},{"visibility":"simplified"}]},{"featureType":"water","elementType":"geometry.fill","stylers":[{"color":"#89a0ca"}]},{"featureType":"water","elementType":"labels.text.fill","stylers":[{"lightness":"100"}]}]},kiz:{autocomplete:{types:['geocode'],componentRestrictions:{country:'de'}},icons:{closestLocation:'fileadmin/evo/assets/img/png/map-marker_rot.png',location:'fileadmin/evo/assets/img/png/map-marker_blau.png',myLocation:'fileadmin/evo/assets/img/png/standort_rot.png',tierpark:'fileadmin/evo/assets/img/png/tierpark_map-marker_blau.png',hotspot:'fileadmin/evo/assets/img/png/map-marker_hotspot.png'}},form:{animation:{errorDuration:300}},userType:{cookieName:'evo_user_type',idPrivatKunden:'pk',idFirmenKunden:'fk'},serviceLascheMobile:{animation:{duration:250}},cookieWarning:{cookieName:'evo_cookie_warning',animation:{duration:250}},terminalCookie:{name:'evo2016',value:'terminal-evo-ag'},faq:{searchMinChar:3,highlightClass:'highlight',url:'index.php'},imageEnlarger:{enlargerClass:"fancybox",lb:{overlayOpacity:'0.7',overlayColor:'#FFFFFF',autoScale:!1,autoDimensions:!0,padding:0,transitionIn:'fade',transitionOut:'fade',scrolling:'no',centerOnScroll:!0}},popup:{cookies:{showOnNextSessionPopup:"showOnNextSessionPopupImage",showPopup:"showPopupImage",showLaterPopup:"showLaterPopupImage",completedPopup:"completedPopupImage"}},promoPopup:{popupClass:"promoPopup",cookie:"promoPopupHide"},tools:{ust:1.16,strom:{privatkundeKWH:[1600,2900,3500,4500,5500],firmenkundeKWH:[5000,20000,40000,60000,80000],privatkundeMax:99999,firmenkundeMax:99999,errorPrivatkundeMax:'Ab einem Jahresverbrauch von 100.000 kWh Strom unterbreiten wir Ihnen gerne ein individuelles Angebot. Bitte wenden Sie sich dafür an unsere Firmenkundenberater. Die Kontaktdaten finden Sie hier:<br><a class="button-arrow-left" href="/service-und-beratung/firmenkunden/kontakt">Zur Berater-Suche</a>',errorFirmenkundeMax:'Ab einem Jahresverbrauch von 100.000 kWh Strom unterbreiten wir Ihnen gerne ein individuelles Angebot. Bitte wenden Sie sich dafür an unsere Firmenkundenberater. Die Kontaktdaten finden Sie hier:<br><a class="button-arrow-left" href="/service-und-beratung/firmenkunden/kontakt">Zur Berater-Suche</a>',inputFormatPk:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:1},inputFormatFk:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:1}},gas:{privatkundeKWH:[10000,14000,20000,30000,36000],firmenkundeKWH:[20000,90000,160000,230000,300000],privatkundeMax:299999,firmenkundeMax:299999,errorPrivatkundeMax:'Ab einem Jahresverbrauch von 300.000 kWh Erdgas unterbreiten wir Ihnen gerne ein individuelles Angebot. Bitte wenden Sie sich dafür an unsere Firmenkundenberater. Die Kontaktdaten finden Sie hier:<br><a class="button-arrow-left" href="/service-und-beratung/firmenkunden/kontakt">Zur Berater-Suche</a>',errorFirmenkundeMax:'Ab einem Jahresverbrauch von 300.000 kWh Erdgas unterbreiten wir Ihnen gerne ein individuelles Angebot. Bitte wenden Sie sich dafür an unsere Firmenkundenberater. Die Kontaktdaten finden Sie hier:<br><a class="button-arrow-left" href="/service-und-beratung/firmenkunden/kontakt">Zur Berater-Suche</a>',inputFormatPk:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:1,maxValue:1000000,defaultValue:4000},inputFormatFk:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:1,defaultValue:20000},sliderPk:{range:{min:[20],max:[200]},pips:{mode:'values',density:5,values:[20,40,60,80,100,120,140,160,180,200],stepped:!0},animate:!0,start:20,connect:"lower",step:20},sliderFk:{range:{min:[100],max:[1500]},pips:{mode:'values',density:7.5,values:[100,300,500,700,900,1100,1300,1500],stepped:!0},animate:!0,start:100,connect:"lower",step:100}},fernwaerme_v1:{inputFormatGrundpreis:{symbol:' kW',symbolLeft:!1,thousendSep:'.',minValue:1,defaultValue:25},inputFormatVerbrauchspreis:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:1,defaultValue:60000},alwaysCompareWith:"wahltarif",messungUndAbrechnung:{preis:{netto:{"_200":84.84,"_201":152.71}},range:{"_200":"bis 200 kW Anschlussleistung","_201":"über 200 kW Anschlussleistung"}},entgeltEmissionen:{preis:{netto:{"_0":0.0012}}},tarife:{komfort:{name:"EVO&nbsp;Komfort",maxAnschlusswert:45,preis:{verbrauchspreis:{netto:{"_0":0.0596}},grundpreis:{netto:{"_0":27.15}}}},direkt:{name:"EVO&nbsp;Direkt",maxAnschlusswert:0,preis:{verbrauchspreis:{netto:{"_100000":0.0417,"_600000":0.0408,"_2000000":0.0378,"_2000001":0.0338}},grundpreis:{netto:{"_25":61.47,"_525":50.20,"_1925":45.08,"_1926":40.98}}}},wahltarif:{name:"EVO WärmeSelekt",maxAnschlusswert:0,preis:{verbrauchspreis:{netto:{"_50000":0.0367,"_550000":0.0358,"_1950000":0.0334,"_1950001":0.0298}},grundpreis:{netto:{"_25":68.91,"_275":53.68,"_1675":55.65,"_1676":45.94}}}}}},fernwaerme_v2:{inputFormatGrundpreis:{symbol:' kW',symbolLeft:!1,thousendSep:'.',minValue:1,defaultValue:25},inputFormatVerbrauchspreis:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:1,defaultValue:30000},error:{tarifauswaehlen:"Bitte wählen Sie zuerst Ihren aktuellen&nbsp;Tarif&nbsp;aus.",komfort:{maxAnschlusswert:"Der von Ihnen angegebene Anschlusswert (über 45kW) ist mit dem von Ihnen gewählten Tarif nicht buchbar. Bitte wählen Sie einen anderen Tarif."}},alwaysCompareWith:"wahltarif",messungUndAbrechnung:{preis:{netto:{"_200":84.84,"_201":152.71},neu:{netto:{"_200":84.84,"_201":152.71}}},range:{"_200":"bis 200 kW Anschlussleistung","_201":"über 200 kW Anschlussleistung"}},entgeltEmissionen:{preis:{netto:{"_0":0.0012},neu:{netto:{"_0":0.00243}}}},tarife:{komfort:{key:"komfort",name:"EVO&nbsp;Komfort",maxAnschlusswert:45,preis:{verbrauchspreis:{netto:{"_0":0.0596},neu:{netto:{"_0":0.064}}},grundpreis:{netto:{"_0":27.15},neu:{netto:{"_0":27.48}}}}},direkt:{key:"direkt",name:"EVO&nbsp;Direkt",maxAnschlusswert:0,preis:{verbrauchspreis:{netto:{"_100000":0.0417,"_600000":0.0408,"_2000000":0.0378,"_2000001":0.0338},neu:{netto:{"_100000":0.0448,"_600000":0.0438,"_2000000":0.0406,"_2000001":0.0363}}},grundpreis:{netto:{"_25":61.47,"_525":50.20,"_1925":45.08,"_1926":40.98},neu:{netto:{"_25":62.23,"_525":50.82,"_1925":45.64,"_1926":41.49}}}}},wahltarif:{key:"wahltarif",name:"EVO&nbsp;Selekt",maxAnschlusswert:0,preis:{verbrauchspreis:{netto:{"_50000":0.0367,"_550000":0.0358,"_1950000":0.0334,"_1950001":0.0298},neu:{netto:{"_50000":0.0394,"_550000":0.0384,"_1950000":0.0359,"_1950001":0.032}}},grundpreis:{netto:{"_25":68.91,"_275":53.68,"_1675":55.65,"_1676":45.94},neu:{netto:{"_25":69.76,"_275":54.35,"_1675":56.34,"_1676":46.51}}}}}}},fernwaerme_v3:{inputFormatGrundpreis:{symbol:' kW',symbolLeft:!1,thousendSep:'.',minValue:1,defaultValue:25},inputFormatVerbrauchspreis:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:1,defaultValue:30000},error:{tarifauswaehlen:"Bitte wählen Sie zuerst Ihren aktuellen&nbsp;Tarif&nbsp;aus.",komfort:{maxAnschlusswert:"Der von Ihnen angegebene Anschlusswert (über 45kW) ist mit dem von Ihnen gewählten Tarif nicht buchbar. Bitte wählen Sie einen anderen Tarif."},komfort2021:{maxAnschlusswert:"Der von Ihnen angegebene Anschlusswert (über 45kW) ist mit dem von Ihnen gewählten Tarif nicht buchbar. Bitte wählen Sie einen anderen Tarif."}},alwaysCompareWith:"wahltarif",messungUndAbrechnung:{preis:{netto:{"_200":84.84,"_201":152.71},neu:{netto:{"_200":84.84,"_201":152.71}}},range:{"_200":"bis 200 kW Anschlussleistung","_201":"über 200 kW Anschlussleistung"}},entgeltEmissionen:{preis:{netto:{"_0":0.00591},neu:{netto:{"_0":0.00591}}}},tarife:{komfort:{key:"komfort",name:"EVO&nbsp;Komfort",maxAnschlusswert:45,preis:{verbrauchspreis:{netto:{"_0":0.0663},neu:{netto:{"_0":0.0663}}},grundpreis:{netto:{"_0":28.01},neu:{netto:{"_0":28.01}}}}},komfort2021:{key:"komfort2021",name:"EVO&nbsp;Komfort&nbsp;2021",maxAnschlusswert:45,preis:{verbrauchspreis:{netto:{"_0":0.0629},neu:{netto:{"_0":0.0629}}},grundpreis:{netto:{"_0":28.01},neu:{netto:{"_0":28.01}}}}},direkt:{key:"direkt",name:"EVO&nbsp;Direkt",maxAnschlusswert:0,preis:{verbrauchspreis:{netto:{"_100000":0.0464,"_600000":0.0453,"_2000000":0.0420,"_2000001":0.0376},neu:{netto:{"_100000":0.0464,"_600000":0.0453,"_2000000":0.0420,"_2000001":0.0376}}},grundpreis:{netto:{"_25":63.42,"_525":51.79,"_1925":46.51,"_1926":42.28},neu:{netto:{"_25":63.42,"_525":51.79,"_1925":46.51,"_1926":42.28}}}}},wahltarif:{key:"wahltarif",name:"EVO&nbsp;Selekt",maxAnschlusswert:0,preis:{verbrauchspreis:{netto:{"_50000":0.0408,"_550000":0.0398,"_1950000":0.0371,"_1950001":0.0332},neu:{netto:{"_50000":0.0408,"_550000":0.0398,"_1950000":0.0371,"_1950001":0.0332}}},grundpreis:{netto:{"_25":71.09,"_275":55.38,"_1675":57.41,"_1676":47.39},neu:{netto:{"_25":71.09,"_275":55.38,"_1675":57.41,"_1676":47.39}}}}}}},stromheizung:{inputFormatHTkWh:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:0,defaultValue:2500},inputFormatNTkWh:{symbol:' kWh',symbolLeft:!1,thousendSep:'.',minValue:0,defaultValue:7500},error:{plz:"Dieser Tarif ist für das gewählte PLZ-Gebiet leider nicht verfügbar.",plzEmpty:"Bitte geben Sie Ihre PLZ ein."},plz:["63065","63067","63069","63075","63071","63073","63110","63150","63179","63500","63512","63533","63128"],preis:{verbrauchspreis:{ht:{netto:0.2352},nt:{netto:0.1805}},grundpreis:{netto:93.00}}},autocomplete:{url:'index.php',searchMinChar:3},cookie:{USER_TYPE:'evo_user_type',GAS_DATA_PK:'evo-tarifrechner-gas-data-pk',STROM_DATA_PK:'evo-tarifrechner-strom-data-pk',GAS_DATA_FK:'evo-tarifrechner-gas-data-fk',STROM_DATA_FK:'evo-tarifrechner-strom-data-fk'}},tracking:{tools:{art:{category:"Tarifrechner",action:"Art"},tarifBerechnen:{category:"Tarifrechner",action:"Tarif berechnen"},ueberleitungEVON:{category:"Tarifrechner",action:"Überleitung zu EVON wurde angezeigt"}}},fuelCalc:{kmOptions:{defaultValue:25000,minValue:1,maxValue:999999,thousendSep:'.',symbolLeft:!1,symbol:' km'},yearsOptions:{defaultValue:4,minValue:1,maxValue:99,symbolLeft:!1,symbol:' Jahre'},naturalGasUsageOptions:{defaultValue:6,minValue:1,maxValue:99,symbolLeft:!1,decimal:1,symbol:' kg',thousendSep:'.',decimalSep:','},roz95UsageOptions:{defaultValue:9,minValue:1,maxValue:99,symbolLeft:!1,decimal:1,thousendSep:'.',decimalSep:',',symbol:' l'},dieselUsageOptions:{defaultValue:7.8,minValue:1,maxValue:99,symbolLeft:!1,decimal:1,thousendSep:'.',decimalSep:',',symbol:' l'},naturalGasPriceOptions:{defaultValue:1.11,minValue:1,maxValue:99,symbolLeft:!1,decimal:2,thousendSep:'.',decimalSep:',',symbol:' EUR'},roz95PriceOptions:{defaultValue:1.45,minValue:1,maxValue:99,symbolLeft:!1,decimal:2,thousendSep:'.',decimalSep:',',symbol:' EUR'},dieselPriceOptions:{defaultValue:1.19,minValue:1,maxValue:99,symbolLeft:!1,decimal:2,thousendSep:'.',decimalSep:',',symbol:' EUR'},compareValuesOptions:{decimal:1,thousendSep:'.',decimalSep:',',symbol:''},resultFuelCostsOptions:{thousendSep:'.',symbol:' EUR',symbolLeft:!1},teaserBoxOptions:{thousendSep:'.',decimalSep:',',symbol:' Euro',symbolLeft:!1,decimal:2},teaserBoxSavingsOptions:{thousendSep:'.',decimalSep:',',symbol:' EUR',symbolLeft:!1,decimal:2},compareValues:[[3.3,4.3,5.0],[3.7,4.8,5.5],[4.0,5.2,6.0],[4.3,5.6,6.5],[4.7,6.1,7.0],[5.0,6.5,7.5],[5.3,6.9,8.0],[5.7,7.4,8.5],[6.0,7.8,9.0],[6.3,8.2,9.5],[6.7,8.7,10.0],[7.3,9.5,11.0],[8.0,10.4,12.0],[8.7,11.3,13.0],[9.3,12.1,14.0],[10,13.0,15.0]]},calendar:{daysOfTheWeek:['Mo','Di','Mi','Do','Fr','Sa','So'],weekOffset:0,showAdjacentMonths:!0,adjacentDaysChangeMonth:!1},customerCallback:{url:'//schnittstelle.inopla.de/customer/314/callback.php',animation:{duration:250}},compareTable:{next:"Nächsten Tarif",prev:"Vorherigen Tarif"},validation:{borderColorOnError:'',errorElementClass:'error-element-class',errorMessageClass:'error-message-class',scrollToTopOnError:!1},warningStrip:{show:!1,message:"",cookie:{cookieName:"warning_strip",cookieExpires:1},animation:{duration:250}},toolbar:{cookie:{cookieName:"show_toolbar",cookieExpires:365},scrollOffset:800},exitPopup:{cookies:{show:'show-exit-cookie'},cookieExpires:{show:0},sensitivityMouse:30,sensitivityTouch:6000},codeOverlay:{cookies:{show:'show-code-overlay-'},cookieExpires:{show:0},codesUrl:'fileadmin/evo/overlayCodes/',name:''},customerService:{apiUrl:"https://evochat.azurewebsites.net/generateAnswer",categories:["smartmeter","kundenwerben","energiesparen","evodigital","vertrag","ihranliegen"],categorieParam:'kategorie'}},EVO.Config);var EVO=window.EVO||{};EVO.UserType=(function($){var _$b,_$toolConfig;function _init(){_$b=$(document.body);_$toolConfig=_$b.find('.tools-config')}
function setType(isFK){if(window.CookieConsent&&window.CookieConsent.consent.preferences===!0){$.cookie(EVO.Config.userType.cookieName,null);$.cookie(EVO.Config.userType.cookieName,isFK?EVO.Config.userType.idFirmenKunden:EVO.Config.userType.idPrivatKunden,{useLocalStorage:!1,expires:365,path:"/"})}}
function getType(){var userType=$.cookie(EVO.Config.userType.cookieName),tempUserType=_$toolConfig.data("config-overwrite-usertype-temporary");if(tempUserType){userType=tempUserType}
return userType}
$(_init);return{setType:setType,getType:getType}})(jQuery);var EVO=window.EVO||{};EVO.Debug=(function($){var _$b,_showText='SHOW GRID',_hideText='HIDE GRID';function _init(){_$b=$(document.body);if(EVO.Config.debug){_addGrid();_$b.append('<div class="toggleGrid">'+_showText+'</div>');_$b.on('click','.toggleGrid',_toogleGrid)}}
function _toogleGrid(e){var $t=$(e.currentTarget),$grid=_$b.find('#grid'),isVisible=$grid.is(':visible');if(isVisible){$grid.hide();$t.text(_showText)}else{$grid.show();$t.text(_hideText)}}
function _addGrid(){_$b.append('<div id="grid"></div>')}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Utils=(function(){function _init(){_arrayForEachFallback();_arrayFilterFallback();_arrayIndexOfFallback()}
function _arrayIndexOfFallback(){if(!Array.prototype.indexOf){Array.prototype.indexOf=function(elt){var len=this.length>>>0;var from=Number(arguments[1])||0;from=(from<0)?Math.ceil(from):Math.floor(from);if(from<0){from+=len}
for(;from<len;from++){if(from in this&&this[from]===elt){return from}}
return-1}}}
function _arrayForEachFallback(){if(!('forEach' in Array.prototype)){Array.prototype.forEach=function(action,that){for(var i=0,n=this.length;i<n;i++){if(i in this){action.call(that,this[i],i,this)}}}}}
function numberFormat(n,decSep,tSep,prec,nan){n=parseFloat(n);if(isNaN(n)){return typeof nan!=='undefined'?nan:''}
var sign='';if(n<0){n=-n;sign='-'}
n=isNaN(prec)||prec<0?n.toString(10):n.toFixed(prec);var nParts=n.split('.');for(var i=nParts[0].length-3;i>0;i-=3){nParts[0]=nParts[0].substr(0,i)+tSep+nParts[0].substr(i)}
return sign+nParts.join(decSep)}
function _arrayFilterFallback(){if(!Array.prototype.filter){Array.prototype.filter=function(fun){if(this===void 0||this===null){throw new TypeError()}
var t=Object(this);var len=t.length>>>0;if(typeof fun!=="function"){throw new TypeError()}
var res=[];var thisp=arguments[1];for(var i=0;i<len;i++){if(i in t){var val=t[i];if(fun.call(thisp,val,i,t)){res.push(val)}}}
return res}}}
function log(){if(EVO.Config.debug&&window.console&&window.console.log){window.console.log.apply(window.console,arguments)}}
function whichTransitionEvent(){var t;var el=document.createElement('fakeelement');var transitions={'transition':'transitionend','OTransition':'oTransitionEnd','MozTransition':'transitionend','WebkitTransition':'webkitTransitionEnd'};for(t in transitions){if(el.style[t]!==undefined){return transitions[t]}}}
function canTransform(){var prefixes='transform WebkitTransform MozTransform OTransform msTransform'.split(' ');var div=document.createElement('div');for(var i=0;i<prefixes.length;i++){if(div&&div.style[prefixes[i]]!==undefined){return!0}}
return!1}
function canTransition(){var event=whichTransitionEvent();return event?!0:!1}
function escapeRegExp(string){return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1")}
function findClosest(array,value){var minDelta=null;var minIndex=null;value+=0.5;for(var i=0;i<array.length;i++){var delta=Math.abs(array[i]-value);if(minDelta===null||delta<minDelta){minDelta=delta;minIndex=i}else if(delta===minDelta){return[array[minIndex],array[i]]}else{return{idx:i-1,value:array[i-1]}}}
return{idx:minIndex,value:array[minIndex]}}
function appendUrlParams($url,params){var origin=$url[0].origin,pathname=$url[0].pathname,search=$url[0].search,hash=$url[0].hash;if(!$url[0].origin){origin=$url[0].protocol+"//"+$url[0].hostname+($url[0].port?':'+$url[0].port:'')}
search+=search.indexOf('?')===-1?"?":"&";$.each(params,function(key,val){search+=key+"="+val+"&"});search=search.slice(0,-1);return origin+pathname+search+hash}
function getURLparams(){var url=window.location.search.substring(1),params=url.split('&'),result=[],i,p;if(params[0]===""&&params.length===1){return!1}
for(i=0;i<params.length;i++){p=params[i].split('=');result[decodeURIComponent(p[0])]=decodeURIComponent(p[1])}
return result}
function getURLparamsObject(){var url=window.location.search.substring(1),params=url.split('&'),result={},i,p;if(params[0]===""&&params.length===1){return!1}
for(i=0;i<params.length;i++){p=params[i].split('=');result[decodeURIComponent(p[0])]=decodeURIComponent(p[1])}
return result}
function resizeFancyboxIFrame(widthOffset,heightOffset){widthOffset=widthOffset===undefined?0:widthOffset;heightOffset=heightOffset===undefined?0:heightOffset;var height=$('#fancybox-frame').contents().find('body').height()+heightOffset,width=$('#fancybox-frame').contents().find('body').width()+widthOffset;$('#fancybox-content, #fancybox-wrap').height(height);$('#fancybox-content, #fancybox-wrap').width(width);$.fancybox.center()}
$(_init);return{log:log,whichTransitionEvent:whichTransitionEvent,canTransition:canTransition,canTransform:canTransform,escapeRegExp:escapeRegExp,findClosest:findClosest,numberFormat:numberFormat,getURLparams:getURLparams,getURLparamsObject:getURLparamsObject,appendUrlParams:appendUrlParams,resizeFancyboxIFrame:resizeFancyboxIFrame}})();var EVO=window.EVO||{};EVO.Core=(function($){var _$b;function _init(){_addFastClick();_$b=$(document.body);_placeholder();_svgFallback();_checkTerminal();$(window).resize(_.debounce(function(){_fixTablesaw()},500));_fixTablesaw();_scrollToAnchor()}
function _fixImagewrap(){var $cur,$img,width,$caption;_$b.find('.csc-textpic-imagewrap.floatimage').each(function(){$cur=$(this);$img=$cur.find('img');width=$img.width();$caption=$cur.find('.csc-textpic-caption');$caption.css('max-width',width)})}
function _fixTablesaw(){$('.tablesaw-nav-btn.right').trigger('click');window.setTimeout(function(){$('.tablesaw-nav-btn.left').trigger('click')},0)}
function _addFastClick(){FastClick.attach(document.body)}
function _placeholder(){$('input, textarea').placeholder()}
function _isSVGSupported(){return(window.SVGSVGElement)?!0:!1}
function _svgFallback(){if(!_isSVGSupported()){_$b.addClass('no-svg');$("img[src$='.svg']").each(function(){var $t=$(this),fallback=$t.attr('data-fallback');$t.attr('src',fallback)})}}
function _checkTerminal(){if($.cookie(EVO.Config.terminalCookie.name)===EVO.Config.terminalCookie.value){$(_$b).find('a[target="_blank"], form[target="_blank"]').removeAttr('target')}}
function _scrollToAnchor(){_$b.find(".scroll-to-anchor").on("click",function(e){e.preventDefault();var url=$(e.currentTarget).attr("href"),hash=url.substring(url.indexOf("#")+1),$anchor=_$b.find('a[name="'+hash+'"]');if($anchor.length){$anchor.velocity('scroll')}})}
$(_init);$(window).load(_fixImagewrap)})(jQuery);var EVO=window.EVO||{};EVO.MatchMediaQuery=(function($){var _$b,_$mq,_$mqMobile,_$mqTableP,_$mqTableL,_$mqDesktop,_$w,_$aside,_curState='';function _init(){_$b=$(document.body);_$w=$(window);_$aside=_$b.find('aside');_$b.append('<div class="mq"></div>');_$mq=_$b.find('.mq');_$mq.append('<div class="mq-mobile"></div>');_$mq.append('<div class="mq-tablet-p"></div>');_$mq.append('<div class="mq-tablet-l"></div>');_$mq.append('<div class="mq-desktop"></div>');_$mqMobile=_$b.find('.mq-mobile');_$mqTableP=_$b.find('.mq-tablet-p');_$mqTableL=_$b.find('.mq-tablet-l');_$mqDesktop=_$b.find('.mq-desktop')}
function _onResize(){if(_$mqMobile.is(':visible')){_curState='mobile'}else if(_$mqTableL.is(':visible')){_curState='tablet-l'}else if(_$mqTableP.is(':visible')){_curState='tablet-p'}else{_curState='desktop'}}
function getState(){_onResize();return _curState}
$(_init);return{getState:getState}})(jQuery);var EVO=window.EVO||{};EVO.Sitemap=(function($){var _$b,_$hb,_$sitemap;function _init(){_$b=$(document.body);_$hb=$("html, body");_$sitemap=_$b.find('#sitemap');_$b.on('click','footer a.siteMapLink',_toggle);_setClass()}
function _setClass(){var i=1;_$sitemap.find('.col-sitemap').each(function(){var $t=$(this),idx=$t.index()+1;$t.addClass('col-sitemap-'+i).removeClass('col-sitemap');i++;if(idx%4===0){i=1}})}
function _toggle(e){e.preventDefault();var isOpen=_$sitemap.hasClass('open'),sitemapTop=$('a.siteMapLink').position().top,$t=$(e.currentTarget);if(!isOpen){$t.addClass('button-close');_$sitemap.velocity('slideDown',{duration:EVO.Config.sitemap.animation.toogleDuration,complete:function(){_$sitemap.addClass('open');if(EVO.Config.sitemap.scrollToSiteMap){_$hb.animate({scrollTop:sitemapTop},EVO.Config.sitemap.animation.scrollDuration)}}})}else{$t.removeClass('button-close');_$sitemap.velocity('slideUp',{duration:EVO.Config.sitemap.animation.toogleDuration,complete:function(){_$sitemap.removeClass('open')}})}}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Teaser=(function($){var _$b,_$w,_$aside,publicFunctions;function _init(){_$b=$(document.body);_$w=$(window);_$aside=_$b.find('aside');_$w.on('resize',publicFunctions.onResize);_$b.on('click','.moreInfo a',_showAction);publicFunctions.addClass()}
function _initLoad(){publicFunctions.onResize()}
function getAside(){return _$aside}
function onResize(){var curMediaQueryState=EVO.MatchMediaQuery.getState();publicFunctions.reset();_$aside.find('.teaser.even').each(function(){var $target=$(this),$targetTeaserInner=$target.find('.teaserInner:not(.bottom)'),$next=$target.next(),$nextTeaserInner=$next.find('.teaserInner:not(.bottom)'),targetH=$targetTeaserInner.height(),nextH=$nextTeaserInner.height(),newH=Math.max(targetH,nextH),isTypeA=$target.hasClass('type-a'),isTypeB=$target.hasClass('type-b');if(isTypeA){if(curMediaQueryState==='tablet-l'||curMediaQueryState==='desktop'){$targetTeaserInner.height(newH);$nextTeaserInner.height(newH)}}else if(isTypeB){if(curMediaQueryState==='tablet-l'||curMediaQueryState==='tablet-p'){$targetTeaserInner.height(newH);$nextTeaserInner.height(newH)}}
var selector=curMediaQueryState==='tablet-p'?'.teaser.type-c.even, .teaser.type-e.even, .teaser.type-f.even':'.teaser.type-c.pos-1, .teaser.type-e.pos-1, .teaser.type-f.pos-1';_$aside.find(selector).each(function(){$target=$(this);publicFunctions.resizeElement($target,'.teaserInner:not(.bottom)');publicFunctions.resizeElement($target,'.teaserInner.bottom')})});publicFunctions.resizeTeaser()}
function resizeElement($target,elementSelector){var curMediaQueryState=EVO.MatchMediaQuery.getState(),$targetTeaserInner=$target.find(elementSelector),$next=$target.next(),$nextTeaserInner=$next.find(elementSelector),$nextNextTeaserInner=$next.next().find(elementSelector),targetH=$targetTeaserInner.height(),nextH=$nextTeaserInner.height(),newH=Math.max(targetH,nextH);if(curMediaQueryState==='tablet-p'){$targetTeaserInner.height(newH);$nextTeaserInner.height(newH)}else if(curMediaQueryState==='desktop'||curMediaQueryState==='tablet-l'){newH=Math.max(targetH,nextH,$nextNextTeaserInner.height());$targetTeaserInner.height(newH);$nextTeaserInner.height(newH);$nextNextTeaserInner.height(newH)}}
function reset(){_$aside.find('.teaser .teaserInner').attr('style','')}
function addClass(){var i;_$aside.find('div.teaser:odd').addClass('odd');_$aside.find('div.teaser:even').addClass('even');_$aside.find('div.teaser.type-c, div.teaser.type-d, div.teaser.type-e, div.teaser.type-f').each(function(j){var idx=$(this).index()+1;if(idx===1){i=1}
$(this).addClass('pos-'+i);i++;if(idx%3===0){i=1}})}
function resizeTeaser(){var i,$container=$('.teaserCont'),$infoValues=$container.find('.hiddenMoreInfo'),minHeight=0,isElVisible,$teaserInnerTop=$container.find('.teaserInner.top'),teaserInnerTopHeight=0,$el;for(i=0;i<$teaserInnerTop.length;++i){$el=$($teaserInnerTop.find('p').get(i));$el.css('height','auto');teaserInnerTopHeight=Math.max(teaserInnerTopHeight,$el.height())}
$teaserInnerTop.find('p').css('height',teaserInnerTopHeight);for(i=0;i<$infoValues.length;++i){$el=$($infoValues.get(i));isElVisible=$el.hasClass('open');if(!isElVisible){$el.show()}
$el.css('height','auto');minHeight=Math.max(minHeight,$el.height());if(!isElVisible){$el.hide()}}
$infoValues.css('height',minHeight)}
function _showAction(e){e.preventDefault();var $t=$(e.currentTarget),$wrapper=$t.closest('.teaser'),$infoValue=$wrapper.find('.hiddenMoreInfo'),isOpen=$infoValue.hasClass('open');publicFunctions.resizeTeaser();if(!isOpen){$infoValue.velocity('slideDown',{duration:150});$infoValue.addClass('open');$t.addClass('active');$t.text('Weniger anzeigen')}else{$infoValue.velocity('slideUp',{duration:150});$infoValue.removeClass('open');$t.removeClass('active');$t.text('Mehr erfahren')}}
$(_init);$(window).load(_initLoad);publicFunctions={onResize:onResize,resizeElement:resizeElement,reset:reset,resizeTeaser:resizeTeaser,getAside:getAside,addClass:addClass};return publicFunctions})(jQuery);var EVO=window.EVO||{};EVO.SearchInput=(function($){var _$b,_$w,_$searchField,_$btnToggleSearch,_$header,_isOpen=!1,_lock=!1,_lastMediaQueryState;function _init(){_$b=$(document.body);_$w=$(window);_$header=_$b.find('header');_$searchField=_$b.find('.searchInput');_$btnToggleSearch=_$b.find('.button-header-search');_$btnToggleSearch.on('click',_toggleSearch);_$searchField.on('click','.submit',_submit).on('keyup keypress','#tx_kesearch_pi1',_checkSubmit);_$w.on('resize',_onResize)}
function _checkSubmit(e){var code=e.keyCode||e.which;if(code===13){_submit(e)}}
function _submit(e){var form=$(e.currentTarget).closest('form'),$id=form.find('input:hidden[name=id]');if($id.val().length===0){form.find('input:hidden[name=id]').val(EVO.UserType.getType()===EVO.Config.userType.idFirmenKunden?'227':'327')}
form.submit()}
function _toggleSearch(e){e.preventDefault();if(!_lock){if(!_isOpen){_open()}else{close()}}}
function _open(withoutAnimation){_lock=!0;var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState==='tablet-p'||curMediaQueryState==='mobile'){EVO.Navi.close(!0);_$header.addClass('searchOpen');if(curMediaQueryState==='mobile'){if(EVO.ServiceLascheMobile){EVO.ServiceLascheMobile.close(!0)}}}
if(!withoutAnimation){_$searchField.velocity('slideDown',{duration:EVO.Config.navi.animation.duration,complete:function(){_isOpen=!0;_lock=!1}})}else{_$searchField.show();_isOpen=!0;_lock=!1}
_$btnToggleSearch.addClass('active');_lastMediaQueryState=curMediaQueryState}
function close(withoutAnimation){_lock=!0;if(!withoutAnimation){_$searchField.velocity('slideUp',{duration:EVO.Config.navi.animation.duration,complete:function(){_isOpen=!1;_lock=!1;_$header.removeClass('searchOpen')}})}else{_$searchField.hide();_isOpen=!1;_lock=!1;_$header.removeClass('searchOpen')}
_$btnToggleSearch.removeClass('active')}
function _onResize(){}
$(_init);return{close:close}})(jQuery);var EVO=window.EVO||{};EVO.Navi=(function($){var _$b,_$w,_$nav,_$header,_$btnShowMobileNavi,_btnShowMobileNaviBottom,_isOpen=!1,_lock=!1,_lastMediaQueryState,_ignoreMouseLeave;function _init(){_$b=$(document.body);_$w=$(window);_$nav=_$b.find('.navInner');if(_$nav.length===0)return;_$header=_$b.find('header');_$btnShowMobileNavi=_$b.find('.button-header-navi-mobile');_btnShowMobileNaviBottom=_$b.find('.button-header-navi-mobile.bottom');_$w.on('resize',_onResize);_$btnShowMobileNavi.on('click',_toggleNavi);_onResize();_$nav.on('mouseenter','ul.level1 > li',_onMouseEnter);_$nav.on('mouseleave','ul.level1 > li',_onMouseLeave);_$nav.on('click','.main ul.level1 > li > a, .main ul.level2 > li > a',_openNextLevel);_$nav.find('ul > li:last-child').addClass('lastChild');_$nav.find('li').each(function(){var $ul=$(this).find('>ul');if($ul&&$ul.length){$(this).addClass('hasSub')}});window.addEventListener('CookiebotOnAccept',function(e){if(window.Cookiebot&&window.Cookiebot.consent.preferences){if(!_$b.hasClass('fk')&&!_$b.hasClass('pk')){if(EVO.UserType){if(!EVO.UserType.getType()){EVO.UserType.setType(!1)}}}else{if(_$b.hasClass('fk')){EVO.UserType.setType(!0)}else{EVO.UserType.setType(!1)}}}},!1);if(!_$b.hasClass('fk')&&!_$b.hasClass('pk')){if(EVO.UserType){if(!EVO.UserType.getType()){_openPK()}else if(EVO.UserType.getType()==='fk'){_openFK()}else if(EVO.UserType.getType()==='pk'){_openPK()}}}else{if(_$b.hasClass('fk')){_openFK()}else{_openPK()}}
_$b.on('click','li.pk a',_onSelectPK).on('click','li.fk a',_onSelectFK)}
function _openDefault(){var type=EVO.UserType?EVO.UserType.getType():'';if(type===EVO.Config.userType.idFirmenKunden){_openFK()}else if(type===EVO.Config.userType.idPrivatKunden){_openPK()}}
function _onSelectPK(){EVO.UserType.setType(!1)}
function _onSelectFK(){EVO.UserType.setType(!0)}
function _openPK(){_$nav.find('.pk').addClass('open');_$nav.find('.fk').removeClass('open');_$nav.find('.pk ul.level3').show();_$nav.find('.fk ul.level3').hide()}
function _openFK(){_$nav.find('.fk').addClass('open');_$nav.find('.pk').removeClass('open');_$nav.find('.fk ul.level3').show();_$nav.find('.pk ul.level3').hide()}
function _onMouseEnter(e){var curMediaQueryState=EVO.MatchMediaQuery.getState(),$t;if(curMediaQueryState==='desktop'||curMediaQueryState==='tablet-l'){if(_ignoreMouseLeave){_onMouseLeave()}
$t=$(e.currentTarget);$t.addClass('open');_openDefault()}}
function _onMouseLeave(e){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState==='desktop'||curMediaQueryState==='tablet-l'){if(!_ignoreMouseLeave){var $t=$(e.currentTarget);$t.removeClass('open')}else{if(!e){_$nav.find('ul.level1 > li.open').removeClass('open')}}}
_$nav.find('.level2').css('min-height',0)}
function _openNextLevel(e){e.preventDefault();var curMediaQueryState=EVO.MatchMediaQuery.getState(),$t=$(e.currentTarget),href=$t.attr('href'),$wrapperLi=$t.closest('li'),isOpen=$wrapperLi.hasClass('open'),isFirstLevel=$wrapperLi.closest('ul').hasClass('level1'),$nextLevel,$prevLi,$openLi,hasSub=$wrapperLi.hasClass('hasSub'),desktopTabletlViewOnTouch=BB.Mobile.isMobile&&(curMediaQueryState==='desktop'||curMediaQueryState==='tablet-l'),baseHref=$('base').attr('href'),r=new RegExp('^(?:[a-z]+:)?//','i');if(!BB.Mobile.isMobile&&isFirstLevel&&(curMediaQueryState==='desktop'||curMediaQueryState==='tablet-l')){window.location=r.test(href)?href:baseHref+href;return!1}
if(!hasSub){window.location=r.test(href)?href:baseHref+href;return!1}
if(curMediaQueryState==='desktop'||curMediaQueryState==='tablet-l'){_ignoreMouseLeave=!0;window.setTimeout(function(){_ignoreMouseLeave=!1},0);$wrapperLi.closest('ul.level2').css('min-height',$wrapperLi.closest('ul').height())}
$nextLevel=$wrapperLi.find('> ul');$prevLi=$nextLevel.closest('li').closest('ul');$openLi=$prevLi.find('>li.open');if(isOpen){$wrapperLi.removeClass('open');$nextLevel.velocity('slideUp',{duration:isFirstLevel&&desktopTabletlViewOnTouch?0:EVO.Config.navi.animation.duration,complete:function(){}})}else{$wrapperLi.addClass('open');$nextLevel.velocity('slideDown',{duration:isFirstLevel&&desktopTabletlViewOnTouch?0:EVO.Config.navi.animation.duration,complete:function(){}});$openLi.find('>ul').velocity('slideUp',{duration:isFirstLevel&&desktopTabletlViewOnTouch?0:EVO.Config.navi.animation.duration});$openLi.removeClass('open')}
if(isFirstLevel){_openDefault()}}
function _toggleNavi(e){e.preventDefault();if(!_lock){if(!_isOpen){_open()}else{close()}}}
function _open(withoutAnimation){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState==='tablet-p'||curMediaQueryState==='mobile'){EVO.SearchInput.close(!0);if(curMediaQueryState==='mobile'){if(EVO.ServiceLascheMobile){EVO.ServiceLascheMobile.close(!0)}}}
_btnShowMobileNaviBottom.show();if(!withoutAnimation){_lock=!0;_$nav.velocity('slideDown',{duration:EVO.Config.navi.animation.duration,complete:function(){_isOpen=!0;_lock=!1}})}else{_$nav.show(0,function(){_lock=!1;_isOpen=!0})}
_$header.css('z-index',800);if(EVO.ServiceLascheDesktopTablet){EVO.ServiceLascheDesktopTablet.close()}
_$header.addClass('naviOpen');_$btnShowMobileNavi.addClass('active')}
function close(withoutAnimation,callback){_btnShowMobileNaviBottom.hide();if(!withoutAnimation){_lock=!0;_$nav.velocity('slideUp',{duration:EVO.Config.navi.animation.duration,complete:function(){_isOpen=!1;_lock=!1;_$header.css('z-index','auto');if(callback){callback()}}})}else{_$nav.hide(0,function(){_isOpen=!1;_lock=!1;_$header.css('z-index','auto')})}
_$header.removeClass('naviOpen');_$btnShowMobileNavi.removeClass('active')}
function _onResize(){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState==='tablet-p'||curMediaQueryState==='mobile'){if(_lastMediaQueryState!=='tablet-p'&&_lastMediaQueryState!=='mobile'){close(!0)}}else{if(!_isOpen){_open(!0)}
_$nav.find('ul').attr('style','');_$nav.find('.open').removeClass('open');_btnShowMobileNaviBottom.hide();_subNaviDirection();_$header.css('z-index','auto')}
_lastMediaQueryState=curMediaQueryState}
function _subNaviDirection(){_$nav.find('ul.reverse').removeClass('reverse');var $lastLi=_$nav.find('ul.level1 > li:last'),$lastUl=$lastLi.find('>ul'),offsetLeft=$lastLi.offset().left,outerWidth=$lastUl.outerWidth(!0);if(_$w.width()<(offsetLeft+outerWidth)){$lastUl.addClass('reverse')}}
$(_init);return{close:close}})(jQuery);var EVO=window.EVO||{};EVO.NaviSidebar=(function($){var _$b,_$w,_$nav,offset;function _init(){_$b=$(document.body);_$w=$(window);_$nav=_$b.find('.sidebar-menu');if(_$nav.length===0)return;offset=_$nav.offset().top+(_$nav.height()/2);_$w.on('scroll',_onScroll);_$nav.on('click','a',_onClick);_$b.on('click','a[href*="#c"]',_onClick)}
function _onScroll(){if(window.pageYOffset>=offset){_$nav.width(_$nav.width());_$nav.addClass('sticky')}else{_$nav.width('auto');_$nav.removeClass('sticky')}}
function _onClick(e){var href=$(e.currentTarget).attr('href').split('#');var pathname=window.location.pathname.substr(1);if(href[0]!==''&&href[0]!==pathname)return;e.preventDefault();if(_$b.find('#'+href[1]).length){_$b.find('#'+href[1]).velocity('scroll',{duration:500,offset:-40,easing:'ease-in-out'})}}
$(_init);return{}})(jQuery);var EVO=window.EVO||{};EVO.Footer=(function($){var _$b,_$w,_$toolbar,_$footer,_$footerMiddle,_$footerBottom,_$toggleButton,_$toggleContent,_curMediaQueryState;function _init(){_$w=$(window);_$b=$(document.body);_$toolbar=$(".toolbar");_$toggleButton=_$toolbar.find('.toggle-button');_$toggleContent=_$toolbar.find('.toggle-content');_$toolbar.lastHeight=0;_$footer=_$b.find('footer');_$footerMiddle=_$footer.find('.footerMiddle');_$footerBottom=_$footer.find('.footerBottom');_$w.on('resize',_onWindowResize);_onWindowResize();_initEvents()}
function _initEvents(){if(EVO.MatchMediaQuery.getState()==='mobile'){if(!_checkCookie()){_$w.on('scroll',_onScroll)}else{_$toggleButton.addClass("closed")}
_$b.on("click",".toggle-button.closed",function(e){_showToolbar(e);_showToolbarHeader()});_$b.on("click",".toggle-button.close",function(){_$toggleButton.removeClass("close").addClass("closed");_hideToolbarHeader()})}
_$b.on("click",_hideToolbar);_$toolbar.not(".disabled").on("click focus",".toolbar-trigger",_showToolbar)}
function _onScroll(){var offsetTop=_$toolbar.offset().top;if(offsetTop&&offsetTop>=EVO.Config.toolbar.scrollOffset&&!_checkCookie()){_showToolbarHeader()}}
function _onWindowResize(){_curMediaQueryState=EVO.MatchMediaQuery.getState();var fMiddleHeight,fBottomHeight,newHeight;_reset();if(_curMediaQueryState==='tablet-l'||_curMediaQueryState==='desktop'){fMiddleHeight=_$footerMiddle.height();fBottomHeight=_$footerBottom.height();newHeight=Math.max(fMiddleHeight,fBottomHeight);_$footerMiddle.height(newHeight);_$footerBottom.height(newHeight)}
if(_$toolbar.length>0){if(_$toolbar.is(":visible")&&!_$toolbar.hasClass("open")){_$toolbar.lastHeight=_$toolbar.outerHeight();_$footer.css("margin-bottom",_$toolbar.lastHeight)}else{if(_curMediaQueryState==="mobile"){_$footer.css("margin-bottom",0)}else{_$footer.css("margin-bottom",_$toolbar.lastHeight)}}}}
function _showToolbarHeader(){if(!_$toggleContent.hasClass("header-visible")){_$toggleButton.addClass("close").removeClass("closed");_$toggleContent.velocity('slideDown',{duration:150});_$toggleContent.addClass("header-visible")}}
function _hideToolbarHeader(){if(_$toggleContent.hasClass("header-visible")){_$toggleContent.velocity('slideUp',{duration:150});_$toggleContent.removeClass("header-visible");_setCookie(EVO.Config.toolbar.cookie.cookieName,!0,EVO.Config.toolbar.cookie.cookieExpires)}}
function _showToolbar(e){var $t=$(e.currentTarget),$toolbar=$t.parents('.toolbar');if(!$toolbar.hasClass('open')){$toolbar.find('.tabCont').velocity('slideDown',{duration:150});$toolbar.find('.toolbar-content').velocity('slideDown',{duration:150});$toolbar.addClass('open')}}
function _hideToolbar(e){var $t=$(e.target),$toolbarParent=$t.parents('.toolbar'),$toolbar=$('.toolbar');if($toolbarParent.length===0&&$toolbar.hasClass('open')){$toolbar.find('.tabCont').velocity('slideUp',{duration:150});$toolbar.find('.toolbar-content').velocity('slideUp',{duration:150});$toolbar.removeClass('open')}}
function _checkCookie(){return $.cookie(EVO.Config.toolbar.cookie.cookieName,{useLocalStorage:!1})==="true"?!0:!1}
function _setCookie(cookieName,value,expires){$.cookie(cookieName,value,{useLocalStorage:!1,expires:expires,path:"/"})}
function _reset(){_$footerMiddle.attr('style','');_$footerBottom.attr('style','')}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Accordion=(function($){var _$b,_$accordion;function _init(){_$b=$(document.body);_$accordion=_$b.find('.accordion');_$accordion.find('dd:last').addClass('last');_$accordion.bbAccordion({selectorHead:'dt',selectorContent:'dd',singleOpened:!1})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.CampaignMotive=(function($){var _$b,_$w,_$articleWide;function _init(){_$b=$(document.body);_$w=$(window);_$articleWide=_$b.find('article.campaignMotive');_$w.on('resize',_calcMotiveHeight);_calcMotiveHeight()}
function _calcMotiveHeight(){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState==='tablet-l'||curMediaQueryState==='desktop'){_$articleWide.each(function(){var $this=$(this),$content=$this.find('.content'),$motive=$this.find('.motive');$motive.find('.inner').height($content.height())})}else{_$articleWide.find('.motive .inner').attr('style','')}}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Slider=(function($){var _$b,_$slider,_$sliderTypeA;function _init(){_$b=$(document.body);_$slider=_$b.find('.slider');_$sliderTypeA=_$b.find('.slider-opinions');_create();_createSliderOpinions()}
function _create(){_$slider.flexslider({animation:EVO.Config.slider.animation.type,directionNav:!1,slideshowSpeed:EVO.Config.slider.animation.slideshowSpeed,before:function(){$('.flexslider .slides').removeClass('end')},end:function(){$('.flexslider .slides').addClass('end')}})}
function _createSliderOpinions(){_$sliderTypeA.each(function(){var $slider=$(this);if($slider.find('.slides-container').length<=1){$slider.find('.slides-container').addClass('full-width');$slider.find('.slides li').show()}else{$slider.flexslider({animation:EVO.Config.slider.animation.type,slideshowSpeed:EVO.Config.slider.animation.slideshowSpeed,controlNav:!1,directionNav:!0,prevText:'',nextText:'',smoothHeight:!0})}})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.FaultReport=(function($){var _$b,_$w,_$faultReport,_txt,_timeoutId,_base={width:2100,time:40000};function _init(){_$b=$(document.body);_$w=$(window);_$faultReport=_$b.find('#faultReport').eq(0);_txt=_$faultReport.find('.txt');_$w.on('resize',_onResize);if(_$faultReport&&_$faultReport.length){_stop();_start()}}
function _onResize(){_stop();window.clearTimeout(_timeoutId);_timeoutId=window.setTimeout(function(){_start()},250)}
function _start(){_txt.css('left',_txt.outerWidth());_txt.velocity({left:-(_txt.outerWidth()+150)},{easing:'linear',duration:_getAniTime(_txt.outerWidth()),complete:function(){_txt.css('left',0);_start()}})}
function _stop(){_txt.css('left',_$faultReport.find('.txt').outerWidth());_txt.velocity("stop")}
function _getAniTime(w){return _base.time*(w/_base.width)}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Maps=(function($){var _$b,_$w,_$map;function _init(){_$b=$(document.body);_$map=_$b.find('.map');if(_$map&&_$map.length){_$map.each(function(){var $t=$(this),$gm=$t.find('.gm'),lat=$gm.attr('data-lat'),lng=$gm.attr('data-lng');_initMap($t.find('.gm').get(0),lat,lng)})}}
function _initMap(cont,lat,lng){var gm=new google.maps.Map(cont,{center:new google.maps.LatLng(lat,lng),zoom:15,streetViewControl:!1,mapTypeControl:!1,scrollwheel:!1,styles:EVO.Config.maps.styles});_addMarker(gm,lat,lng)}
function _addMarker(gm,lat,lng){var marker=new google.maps.Marker({position:new google.maps.LatLng(lat,lng),map:gm,icon:EVO.Config.maps.marker})}
$(window).load(_init)})(jQuery);var EVO=window.EVO||{};EVO.ImageGallery=(function($){var _$b;function _init(){_$b=$(document.body);_$b.find('.gallery').each(function(){var $t=$(this),$canvas=$t.find('.flexslider.canvas'),_$thumbnails=$t.find('.flexslider.thumbnails'),_$canvasDesktop=$canvas.clone().addClass('desktop'),_$thumbnailsDesktop=_$thumbnails.clone().addClass('desktop');_$canvasDesktop.insertAfter(_$thumbnails).after(_$thumbnailsDesktop);_create({canvas:$canvas,thumbnails:_$thumbnails,canvasDesktop:_$canvasDesktop,thumbnailsDesktop:_$thumbnailsDesktop})})}
function _create(options){options.thumbnails.flexslider({animation:"slide",controlNav:!1,animationLoop:!1,slideshow:!1,itemWidth:58,asNavFor:options.canvas,prevText:'',nextText:''});options.canvas.flexslider({animation:"slide",controlNav:!1,animationLoop:!1,slideshow:!1,sync:options.thumbnails,prevText:'',nextText:''});options.thumbnailsDesktop.flexslider({animation:"slide",controlNav:!1,animationLoop:!1,slideshow:!1,itemWidth:76,asNavFor:options.canvasDesktop,prevText:'',nextText:''});options.canvasDesktop.flexslider({animation:"fade",controlNav:!1,animationLoop:!1,slideshow:!1,sync:options.thumbnailsDesktop,prevText:'',nextText:''})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.ImageEnlarger=(function($){var _$b,_$w,_pictures;function _init(){_$b=$('body');_$w=$(window);_pictures=_$b.find('a[rel=group], a.'+EVO.Config.imageEnlarger.enlargerClass);_$w.on('resize',_resize);_resize()}
function _resize(){var _curMediaQueryState=EVO.MatchMediaQuery.getState();if(_curMediaQueryState!=='desktop'){_pictures.off('click.fb');_pictures.on('click',function(e){e.preventDefault()})}else{_pictures.fancybox(EVO.Config.imageEnlarger.lb)}}
$(_init);return{init:_init,resize:_resize}})(jQuery);var EVO=window.EVO||{};EVO.Breadcrumbs=(function($){var _$b,_$w,_$breadcrumb;function _init(){_$b=$(document.body);_$w=$(window);_$breadcrumb=_$b.find('.breadcrumb');_$breadcrumb.find('.scroller > ul > li:last').addClass('last');if(!BB.Mobile.hasTouch){_$breadcrumb.find('.level2 ul').each(function(){if($(this).children().length>1){$(this).closest('li').addClass('show-sub')}})}else{_$breadcrumb.find('.level2 ul').closest('li').addClass('show-sub')}
if(BB.Mobile.isMobile||BB.Mobile.isTablet){_$b.on('click',_closeAll);$(window).on('scroll',_closeAll);_$breadcrumb.on('click.touchdevice','.level1 li',_toggleNextLevel).on('click.touchdevice','.level2 li a',_changePage)}else{_$breadcrumb.on('mouseover mouseout','li',_toggleNextLevel)}}
function _changePage(e){window.location=$(e.currentTarget).attr('href')}
function _closeAll(){var $nextLevel=_$breadcrumb.find('.level2');$nextLevel.hide();$nextLevel.attr('style','');$nextLevel.data('isActive',!1);$nextLevel.find('.arrow').attr('style','')}
function _toggleNextLevel(e){var $t=$(e.currentTarget),eType=e.type,$li=$t.closest('li'),$nextLevel=$li.find('.level2'),$arrow=$nextLevel.find('.arrow'),arrowWidth,targetWidth,nextLevelLeft,nextLevelRight,nextLevelWidth,newLeft,diff,isFirstClick,arrowPos=0;_$breadcrumb.find('.level2').hide();_$breadcrumb.find('.level2').attr('style','');_$breadcrumb.find('.level2').not($nextLevel).data('isActive',!1);if(eType==='click'){e.preventDefault();e.stopPropagation();if(!$nextLevel.data('isActive')){$nextLevel.data('isActive',!0);isFirstClick=!0}else{isFirstClick=!1}}
if($nextLevel&&$nextLevel.length&&$li.hasClass('show-sub')){if(eType==='mouseover'||isFirstClick){$nextLevel.show();nextLevelLeft=$nextLevel.offset().left;nextLevelWidth=$nextLevel.outerWidth();nextLevelRight=nextLevelWidth+nextLevelLeft;arrowWidth=$arrow.outerWidth();targetWidth=$t.outerWidth();if(nextLevelLeft<0){newLeft=0;$nextLevel.css('margin',0);arrowPos=(targetWidth-arrowWidth)/2;$arrow.css('left',arrowPos)}else if(nextLevelRight>$(window).width()){$nextLevel.css('margin',0);diff=nextLevelRight-$(window).width();newLeft=parseInt($nextLevel.css('left'),10)-diff-($nextLevel.outerWidth()/2);arrowPos=((targetWidth-arrowWidth)/2)+(($nextLevel.outerWidth()/2)+diff);$arrow.css('left',arrowPos)}
$nextLevel.css('left',newLeft)}else{$nextLevel.hide();$nextLevel.attr('style','');$nextLevel.data('isActive',!1);$nextLevel.find('.arrow').attr('style','')}}}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.FormRueckruf=(function($){var _$f=null,_$fieldsToValidate=null,_$formDatum,_$formDatumSelected,_$formZeit,_$formZeitSelected;function _init(){_$f=$('#kontakt_lp_rueckruf');_$formDatum=$('#rueckrufdatum');_$formZeit=$('#rueckrufzeit');_$formDatumSelected=$('#selectedRueckrufdatum');_$formZeitSelected=$('#selectedRueckrufzeit');_fillOptionDatum();_fillOptionZeit()}
function _fillOptionDatum(){var today=new Date();var tag='';var daten=[];var i;var wochentag=["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag"];var feiertag=["14.04.2017","17.04.2017","01.05.2017","25.05.2017","05.06.2017","15.06.2017","03.10.2017","31.10.2017","25.12.2017","26.12.2017","01.01.2018","30.03.2018","02.04.2018","01.05.2018","10.05.2018","21.05.2018","31.05.2018","03.10.2018","25.12.2018","26.12.2018","01.01.2019","19.04.2019","22.04.2019","01.05.2019","30.05.2019","10.06.2019","20.06.2019","03.10.2019","25.12.2019","26.12.2019"];var lastday=new Date(today.getTime()+1296000000);var stundenzahl=today.getTime()-today.setHours(0,0,0);var callToday=stundenzahl<52200000&&today.getDay()!==0&&today.getDay()!==6;if(!callToday){today=new Date(today.getTime()+86400000)}
while(today.getDate()!==lastday.getDate()){tag=(today.getDate()+100).toString().substr(1)+'.'+(today.getMonth()+101).toString().substr(1)+'.'+today.getFullYear();if(today.getDay()!==0&&today.getDay()!==6&&$.inArray(tag,feiertag)===-1){daten.push(''+wochentag[today.getDay()]+',  '+tag)}
today=new Date(today.getTime()+86400000)}
for(i=0;i<daten.length;i++){if(_$formDatumSelected.val()===daten[i]){$('<option/>').attr('value',daten[i]).attr('selected','selected').text(daten[i]).appendTo(_$formDatum)}else{$('<option/>').attr('value',daten[i]).text(daten[i]).appendTo(_$formDatum)}}
_$formDatum.change($.proxy(_fillOptionZeit,this))}
function _fillOptionZeit(){var datumSelected=jQuery('#rueckrufdatum :selected');var today=new Date();var daten=[];var stunde=today.getHours();var minute=today.getMinutes();var stundenzahl=today.getTime()-today.setHours(0,0,0);var i;var callToday=stundenzahl>28800000&&stundenzahl<52200000&&today.getDay()!==0&&today.getDay()!==6;if(datumSelected.index()!==0){if(minute>30){stunde+=1}
if(datumSelected.index()!==1||!callToday){_$formZeit.html('');for(i=8;i<=15;i++){daten.push('zwischen '+i+':00 und '+(i+1)+':00 Uhr')}}else{_$formZeit.html('');daten.push(window.unescape('sofort (in den n%E4chsten 30 Min.)'));for(i=stunde+1;i<=15;i++){daten.push('zwischen '+i+':00 und '+(i+1)+':00 Uhr')}}
for(i=0;i<daten.length;i++){if(_$formZeitSelected.val()===daten[i]){jQuery('<option/>').attr('value',daten[i]).attr('selected','selected').text(daten[i]).appendTo(_$formZeit)}else{jQuery('<option/>').attr('value',daten[i]).text(daten[i]).appendTo(_$formZeit)}}}else{_$formZeit.html('')}}
$(_init);return{_init:_init}})(jQuery);var EVO=window.EVO||{};EVO.Form=(function($){var _$b,_$formSolarkampagne,_$formHeizungsangebot,_$formKickersKidsCamp,_$verbrauchJahresstromverbauch,_$verbrauchJahresstromverbauchHidden,_$dachneigungInput;function _init(){_$b=$(document.body);_$b.on('click','form  a.submit',_doSubmit).on('click','input[data-date-picker]',_showDatePicker).on('keyup keydown','input[data-date-picker]',function(){return!1}).on('focus','form .error input, form .error textarea, form input.error',_removeError).on('change','form .error .radioGroup, form .error .checkBox, form .error select',_removeError).on('keyup input','form .plz_heizungsangebot',_changePLZ).on('click','form .personButtons a',_changePersonInput).on('click','form .dachneigungButtons a',_changeDachneigungInput).on('focus','form [name ^="newsletter"][name $="[email]"]',_openNewsletterTerms).on('click','form .show-next-fieldset',_changeFieldset);_initRadioCheck();_initDatepicker();_$formSolarkampagne=_$b.find('#solarkampagne');_$formHeizungsangebot=_$b.find('#heizungsangebot');_$formKickersKidsCamp=_$b.find('#kickers_kids_camp');if(_$formSolarkampagne.length){_$verbrauchJahresstromverbauch=_$b.find('input#verbrauch_jahresstromverbauch');_$verbrauchJahresstromverbauchHidden=_$b.find('input#verbrauch_jahresstromverbauch_hidden');_$dachneigungInput=_$b.find('input#dachneigung');_$verbrauchJahresstromverbauch.bbFormat(EVO.Config.tools.strom.inputFormatPk);_$verbrauchJahresstromverbauch.on('bbFormatChangeEvent',_changeStromVerbrauchInput);_onFillSolarkampagneForm()}
if(_$formHeizungsangebot.length){_$formHeizungsangebot.on("click",".step1 label",function(){_$formHeizungsangebot.removeClass("angebotTrue angebotFalse").addClass($(this).attr("for"))})}
if(_$formKickersKidsCamp.length){var $allergien=_$formKickersKidsCamp.find('#allergien_text').closest('.row'),$medikamente=_$formKickersKidsCamp.find('#medikamente_text').closest('.row');$allergien.hide();$medikamente.hide();_$formKickersKidsCamp.on("change","#allergien, #medikamente",function(e){var $target=$(e.currentTarget).attr('id')==='allergien'?$allergien:$medikamente;if($(e.currentTarget).val()==='1'){$target.show()}else{$target.hide()}})}
_initFieldsetStep();_initValidate()}
function _changePLZ(e){var validPLZs=formConfig.validPlz.split(',');var errorMsg='';var input=e;if(EVO.ValidationOptions.heizungsangebot&&EVO.ValidationOptions.heizungsangebot.messages['heizungsangebot[plz_allgemein]']){errorMsg=EVO.ValidationOptions.heizungsangebot.messages['heizungsangebot[plz_allgemein]'].plzValid}
if(e.currentTarget){input=e.currentTarget}
if(input.value.length<5){$('.submit').prop('disabled',!0);return}
if(input.value.length===5&&validPLZs.indexOf(input.value.substring(0,2))>-1){$('.submit').prop('disabled',!1);$(input).closest('.row').removeClass('error');$(".address_feError").html('')}else{$('.submit').prop('disabled',!0);$(input).closest('.row').addClass('error');$(".address_feError").html('<label id="plz_allgemein-error" class="error" for="plz_allgemein">'+errorMsg+'</label>')}}
function _initFieldsetStep(){var $form=$('form #step').closest("form"),$fieldsets,fieldsetSelector,prevFieldsetSelector,$fieldsetToShow,page;$form.each(function(){$fieldsets=$(this).find("fieldset");fieldsetSelector=$(this).find("#step").val();prevFieldsetSelector=$(this).find("#backstep").val();if(!fieldsetSelector){page=$fieldsets.first().data("page")}
if(fieldsetSelector){$fieldsetToShow=$(this).find('[data-step='+fieldsetSelector+']');if($fieldsetToShow){page=$fieldsetToShow.data("page");$fieldsets.hide();$fieldsetToShow.show();$fieldsetToShow.find(".prev-fieldset-button").attr('data-show-next-fieldset',prevFieldsetSelector)}}
if(page){EVO.Tracking.virtualPage(page)}})}
function _initValidate(){var $formsToValidate=$(".formToValidate"),$options,id;$formsToValidate.each(function(){id=$(this).attr("id");$options=EVO.ValidationOptions[id];if($options){$options=$.extend(!0,{focusInvalid:!1,invalidHandler:function(form,validator){if(!validator.numberOfInvalids())
return;$(validator.errorList[0].element).velocity('scroll',{offset:-30})},highlight:function(element,errorClass){$(element).closest(".row").addClass(errorClass)},unhighlight:function(element,errorClass){if($(element).hasClass('plz_heizungsangebot')){_changePLZ(element);return}
$(element).closest(".row").removeClass(errorClass)}},$options);$(this).validate($options)}})}
function _openNewsletterTerms(e){$(e.currentTarget).closest('form').find('[name ^="newsletter"][name $="[newsletter]"], [name ^="newsletter"][name $="[newsletter_fk]"]').closest('.row').slideDown(500)}
function _changeFieldset(e){var $ct=$(e.currentTarget);if($ct.is('label')){e.preventDefault();$ct.find('input[type="radio"]').prop("checked",!0)}else{e.preventDefault()}
var $form=$ct.closest('form'),$currentFieldset=$ct.closest('fieldset'),currentFieldsetSelector=$currentFieldset.attr('data-step'),targetFieldsetSelector=$ct.attr('data-show-next-fieldset'),$targetFieldset=$form.find('[data-step='+targetFieldsetSelector+']'),$stepInputForBackend=$form.find("#step"),$stepBackInputForBackend=$form.find("#backstep"),$prevFieldsetButton=$targetFieldset.find(".prev-fieldset-button"),page;if(!$ct.hasClass("prev-fieldset-button")){if($form.valid()){$stepInputForBackend.val($targetFieldset.data("step"));$stepBackInputForBackend.val(currentFieldsetSelector);$currentFieldset.velocity('slideUp');$targetFieldset.velocity('slideDown',function(){$targetFieldset.velocity('scroll')});page=$targetFieldset.data("page");$prevFieldsetButton.attr('data-show-next-fieldset',currentFieldsetSelector)}}else{$stepInputForBackend.val($targetFieldset.data("step"));$currentFieldset.velocity('slideUp');$targetFieldset.velocity('slideDown',function(){$targetFieldset.velocity('scroll')});page=$targetFieldset.data("page")}
if(page){EVO.Tracking.virtualPage(page)}}
function _onFillSolarkampagneForm(){var closestValue=EVO.Utils.findClosest(EVO.Config.tools.strom.privatkundeKWH,parseInt(_$verbrauchJahresstromverbauchHidden.val(),10)),$personButtons=_$formSolarkampagne.find('.personButtons a'),$dachneigungButton=_$formSolarkampagne.find('.dachneigungButtons a[data-src="'+_$dachneigungInput.val()+'"]');if(_$verbrauchJahresstromverbauchHidden.val()===''){$personButtons.eq(0).trigger('click')}else{$personButtons.eq(closestValue.idx).addClass('active');_$verbrauchJahresstromverbauch.bbFormat({value:_$verbrauchJahresstromverbauchHidden.val()})}
$dachneigungButton.addClass('active')}
function _changeDachneigungInput(e){e.preventDefault();var $t=$(e.currentTarget),$src=$t.attr('data-src'),$input=_$b.find('input#dachneigung'),$wrapper=$t.closest('form'),$buttons=$wrapper.find('.dachneigungButtons a');$buttons.removeClass('active');$t.addClass('active');$input.val($src).trigger('focusin')}
function _changeStromVerbrauchInput(e){var value=e.bbValue,$t=$(e.currentTarget),$wrapper=$t.closest('form'),$buttons=$wrapper.find('.personButtons a'),closestValue=EVO.Utils.findClosest(EVO.Config.tools.strom.privatkundeKWH,value);$buttons.removeClass('active');$buttons.eq(closestValue.idx).addClass('active');_$b.find('input#verbrauch_jahresstromverbauch_hidden').val(value)}
function _changePersonInput(e){e.preventDefault();var $t=$(e.currentTarget),$wrapper=$t.closest('.personButtons'),$other=$wrapper.find('a').not($t),idx=$t.index();$t.addClass('active');$other.removeClass('active');var $input=_$b.find('input#verbrauch_jahresstromverbauch');$input.bbFormat({value:EVO.Config.tools.strom.privatkundeKWH[idx]});_$b.find('input#verbrauch_jahresstromverbauch_hidden').val(EVO.Config.tools.strom.privatkundeKWH[idx])}
function _showDatePicker(e){var $t=$(e.currentTarget),$datepicker=$t.closest('.input').find('.datepicker');$datepicker.show()}
function _initRadioCheck(){_$b.find('.radioGroup, .checkBox').bbRadioCheck()}
function _initDatepicker(){_$b.find('input[data-date-picker]').each(function(){if(!$(this).data('init')){EVO.Datepicker.create($(this).closest('.input'));$(this).data('init',!0)}})}
function _removeError(e){var $t=$(e.currentTarget),$row=$t.closest('.row'),$errorMsg=$row.find('.errorMsg');$row.removeClass('error');$t.removeClass('error');if($errorMsg&&$errorMsg.length){$errorMsg.velocity('slideUp',{duration:EVO.Config.form.animation.errorDuration,complete:function(){}})}}
function _doSubmit(e){e.preventDefault();var $t=$(e.currentTarget),$form=$t.closest('form'),$submit=$form.find('input[type="submit"]'),$loadingAni=$form.find('.loading_ajax-submit');if($submit&&$submit.length){$loadingAni.addClass('show');$submit.trigger('click')}}
function submitCallback(data,textStatus){_initRadioCheck();_initDatepicker();if(_$b.find('.error').length>0){_$b.find('.error').each(function(){$(this).closest('form').find('.flyout').css('display','block')})}
$('.flyout').on('click',function(event){$(event.currentTarget).css('display','block')});EVO.FormRueckruf._init();var callbackEvent=jQuery.Event("submitAjaxFormCallback",{customData:data,textStatus:textStatus});$(document).trigger(callbackEvent)}
$(_init);return{submitCallback:submitCallback}})(jQuery);var EVO=window.EVO||{};EVO.ServiceLascheDesktopTablet=(function($){var _$b,_$w,_$serviceLascheDesktopTablet,_$serviceLascheButtons,_$serviceLascheCont,_$closeButton,_$inner,_isOpen=!1,_marginTopServiceLasche,_lastMediaQueryState,_closeBtbHeight=0;function _init(){_$b=$(document.body);_$w=$(window);if(!_$b.hasClass('external')){_$serviceLascheDesktopTablet=_$b.find('#serviceLascheDesktopTablet');if(_$serviceLascheDesktopTablet.length===0)return;_$serviceLascheButtons=_$serviceLascheDesktopTablet.find('.buttons');_$serviceLascheCont=_$serviceLascheDesktopTablet.find('div.cont');_$closeButton=_$serviceLascheCont.find('.button-close-service-lasche');_$inner=_$serviceLascheCont.find('.inner');_$serviceLascheCont.show();_closeBtbHeight=_$closeButton.outerHeight(!0);_$serviceLascheCont.hide();_$serviceLascheButtons.on('click','.buttonHolder a:not(".active")',_open).on('click','.buttonHolder a.active',close);_doCenter();_$serviceLascheCont.on('click','a.button-close-service-lasche',close);_$serviceLascheButtons.find('.buttonHolder a:first-child').addClass('first');_$serviceLascheCont.on('tabChange','.tabs',function(){_centerCont()});_$w.on('resize',_onResize);_onResize()}}
function _onResize(){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState!==_lastMediaQueryState){close(null,!0)}
_lastMediaQueryState=curMediaQueryState;_centerCont()}
function close(e,noAni){if(e){e.preventDefault()}
if(_isOpen){_isOpen=!1;_$serviceLascheButtons.find('.buttonHolder > a').attr('style','');_doCenter();if(!noAni){_$serviceLascheCont.velocity('fadeOut',{duration:150,complete:function(){_$serviceLascheButtons.find('.buttonHolder a.active').removeClass('active');_$serviceLascheButtons.removeClass('open')}})}else{_$serviceLascheCont.hide();_$serviceLascheButtons.find('.buttonHolder a.active').removeClass('active');_$serviceLascheButtons.removeClass('open')}}}
function _open(e){e.preventDefault();var $t=$(e.currentTarget),idx=$t.index(),canTransition=EVO.Utils.canTransition(),delay=0;_$serviceLascheButtons.find('.buttonHolder a.active').removeClass('active');_$serviceLascheButtons.addClass('open');_$inner.children('div').hide();_$inner.children('div').eq(idx).show();$t.addClass('active');if(canTransition){if(!_isOpen){delay=200}}
window.setTimeout(function(){_$serviceLascheCont.velocity('fadeIn',{duration:150});_$serviceLascheButtons.find('.buttonHolder > a').css('border-left',0);_doCenter();_centerCont();_isOpen=!0},delay)}
function open(idx){var canTransition=EVO.Utils.canTransition(),delay=0;_$serviceLascheButtons.find('.buttonHolder a.active').removeClass('active');_$serviceLascheButtons.addClass('open');_$inner.children('div').hide();_$inner.children('div').eq(idx).show();if(canTransition){if(!_isOpen){delay=200}}
window.setTimeout(function(){_$serviceLascheCont.velocity('fadeIn',{duration:150});_$serviceLascheButtons.find('.buttonHolder > a').css('border-left',0);_doCenter();_centerCont();_isOpen=!0},delay)}
function _centerCont(){var top,innerBorderWidth=parseInt(_$inner.css('border-left-width'),10),closeButtonBorderWidth=parseInt(_$closeButton.css('border-left-width'),10);_$closeButton.removeClass('showBorder');_$inner.css('max-height',$(window).height()-(40*2)).css('min-height',_$serviceLascheButtons.height());top=_$serviceLascheButtons.position().top+((_$serviceLascheButtons.height()-_$serviceLascheCont.height())/2);if(!EVO.Utils.canTransform()){top=top+_marginTopServiceLasche}
if($(window).height()<=(_$serviceLascheButtons.height()+_closeBtbHeight)){top=_closeBtbHeight-(closeButtonBorderWidth*2);_$inner.css('min-height',$(window).height()-_closeBtbHeight-innerBorderWidth).css('max-height',$(window).height()-_closeBtbHeight-innerBorderWidth);_$closeButton.addClass('showBorder')}
_$serviceLascheCont.css('top',top);$('#userlikePopup').css('top',top)}
function _doCenter(){if(!EVO.Utils.canTransform()){_marginTopServiceLasche=-(_$serviceLascheButtons.height()/2);_$serviceLascheButtons.css('margin-top',_marginTopServiceLasche)}}
function hide(){close();_$serviceLascheButtons.addClass("hide")}
function show(){if(_$serviceLascheDesktopTablet.length>0){_$serviceLascheButtons.removeClass("hide")}}
$(_init);return{close:close,open:open,hide:hide,show:show}})(jQuery);var EVO=window.EVO||{};EVO.ServiceLascheMobile=(function($){var _$b,_$w,_$btn,_$serviceLascheMobile,_$serviceLascheDesktopTablet,_$serviceLascheMobileButtons,_$serviceLascheMobileInner,_$serviceLascheMobileCloseButton,_$serviceLascheMobileCont,_lastMediaQueryState;function _init(){_$b=$(document.body);_$w=$(window);_$btn=_$b.find('a.button-header-service-lasche, a.button-header-inner');_$serviceLascheMobile=_$b.find('#serviceLascheMobile');_$serviceLascheDesktopTablet=_$b.find('#serviceLascheDesktopTablet');_copyServiceLascheContent();_$serviceLascheMobileButtons=_$serviceLascheMobile.find(".buttonHolder a");_$serviceLascheMobileInner=_$serviceLascheMobile.find(".inner > div");_$serviceLascheMobileCloseButton=_$serviceLascheMobile.find(".button-close-service-lasche").addClass("bottom").text("");_$serviceLascheMobileCont=_$serviceLascheMobile.find(".cont");_$serviceLascheMobileCloseButton.on('click',function(e){var $t=_$serviceLascheMobileButtons.filter(".active");if($t.hasClass("login")){close()}else{_closeInner($t.index())}});_$serviceLascheMobile.on('click','.buttonHolder a:not(".active")',_toogleInner).on('click','.buttonHolder a.active',_toogleInner);_$b.on('click','a.button-header-service-lasche',_toogle).on('click','a.button-header-inner',_toogleInner);_$w.on('resize',_onResize);_onResize()}
function _toogleInner(e){e.preventDefault();var $t=$(e.currentTarget),isActive=$t.hasClass('active'),data=$t.data("button"),idx=data?_$serviceLascheMobileButtons.filter("."+data).index():$t.index();if(isActive){if(data){close()}
_closeInner(idx)}else{if(data){_$serviceLascheMobile.find(".buttonHolder").hide();_open($t,!0)}
_openInner(idx)}}
function _openInner(idx){var $t=_$serviceLascheMobileButtons.eq(idx);_$serviceLascheMobileButtons.removeClass('active');$t.addClass("active");_$serviceLascheMobileInner.not(_$serviceLascheMobileInner.eq(idx)).hide();_$serviceLascheMobileInner.eq(idx).show();_$serviceLascheMobileCont.velocity('slideDown',{duration:EVO.Config.serviceLascheMobile.animation.duration,complete:function(){_$serviceLascheMobileCloseButton.show()}})}
function _closeInner(idx,withoutAnimation){var $t=_$serviceLascheMobileButtons;if(idx){$t=_$serviceLascheMobileButtons.eq(idx)}
$t.removeClass("active");if(!withoutAnimation){_$serviceLascheMobileCont.velocity('slideUp',{duration:EVO.Config.serviceLascheMobile.animation.duration,complete:function(){_$serviceLascheMobileInner.hide();_$serviceLascheMobileCloseButton.hide()}})}else{_$serviceLascheMobileCont.hide();_$serviceLascheMobileInner.hide();_$serviceLascheMobileCloseButton.hide()}}
function _copyServiceLascheContent(){_$serviceLascheMobile.append(_$serviceLascheDesktopTablet.html());_$serviceLascheMobile.find(".cont").removeAttr("style");_$serviceLascheMobile.find(".inner").removeAttr("style")}
function _onResize(){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState!==_lastMediaQueryState){if(curMediaQueryState!=='mobile'){close(!0)}}
_lastMediaQueryState=curMediaQueryState}
function _toogle(e){e.preventDefault();var $t=$(e.currentTarget),isActive=$t.hasClass('active');if(isActive){close()}else{_$serviceLascheMobile.find(".buttonHolder").show();_open($t)}}
function _open($btn,withoutAnimation){_closeInner(null,!0);close(!0);$btn.addClass('active');EVO.Navi.close(!0);EVO.SearchInput.close(!0);if(!withoutAnimation){_$serviceLascheMobile.velocity('slideDown',{duration:EVO.Config.serviceLascheMobile.animation.duration,complete:function(){}})}else{_$serviceLascheMobile.show()}}
function close(withoutAnimation){_$btn.removeClass('active');if(!withoutAnimation){_$serviceLascheMobile.velocity('slideUp',{duration:EVO.Config.serviceLascheMobile.animation.duration,complete:function(){}})}else{_$serviceLascheMobile.hide()}}
$(_init);return{close:close}})(jQuery);var EVO=window.EVO||{};EVO.Chat=(function($){var _$b,_$w,_$serviceLasche,_$serviceLascheChatPanel,_$spinner,_$online,_$offline,_$chatButton,_$userlikeButton,_chatState,_$chatOperator,_$chatbotActive=!1;function _init(){_$b=$(document.body);_$w=$(window);_$serviceLasche=_$b.find('#serviceLascheDesktopTablet, #serviceLascheMobile');if(_$serviceLasche.length===0||_$serviceLasche.find('a.chat').length===0)return;_$serviceLascheChatPanel=_$serviceLasche.find('.inner > div:nth-child(2)');_$spinner=_$serviceLascheChatPanel.find('.spinner');_$online=_$serviceLascheChatPanel.find('.online');_$offline=_$serviceLascheChatPanel.find('.offline');_$userlikeButton=_$b.find('#userlikeCustomTab');_$chatButton=_$serviceLascheChatPanel.find('.startChat');_$online.hide();_$offline.hide();_$chatButton.on('click',onChatButtonClick);if(!_$b.hasClass('external')){window.userlikeReady=function(){_chatState=userlikeChatState()}}}
function onChatButtonClick(event){event.preventDefault();EVO.ServiceLascheDesktopTablet.close();_$userlikeButton.click();return!1}
window.userlikeButtonHandler=function(online){if(!_$offline||!_$spinner||!_$online)return;if(online){_$offline.hide();_$spinner.hide();_$online.show()}else{_$spinner.hide();_$online.hide();_$offline.show()}};window.userlikeTrackingEvent=function(event_name,global_ctx,session_ctx){var operator="Live-Chat";if(session_ctx.operator_name!==undefined&&event_name!=="proactive_offer"){if(_$chatOperator===undefined||_$chatOperator!==session_ctx.operator_name){_$chatOperator=session_ctx.operator_name;if(_$chatbotActive){EVO.Tracking.trackEvent("Chat","Wechsel zu",operator)}
if(_$chatOperator.match(EVO.Config.chatbot.regex)&&!_$chatbotActive){operator="Chatbot";_$chatbotActive=!0}
EVO.Tracking.trackEvent("Chat","Art",operator)}}};$(_init);return{userlikeButtonHandler:userlikeButtonHandler}})(jQuery);var EVO=window.EVO||{};EVO.Tabs=(function($){var _$b,_$tabs;function _init(){_$b=$(document.body);_$tabs=_$b.find('.tabs');var _$tools=_$b.find('.tools .tabs .tabNav');_$tabs.on('click','.tabNav a',_onClickTab);if(_$tools.length>0&&window.location.hash.indexOf('erdgas')>0){_$tabs.find('.tabNav a:nth-child(2)').trigger('click')}else{_$tabs.find('.tabNav a:first-child').trigger('click')}}
function _onClickTab(e){e.preventDefault();var $t=$(e.currentTarget),idx=$t.index(),$wrapper=$t.closest('.tabs'),$cont=$wrapper.find('.tabCont > div').hide(),$ifTool=$t.parents('.tools').length,$ifToolbar=$t.parents('.toolbar').length;if($ifTool&&!$ifToolbar){if($t.hasClass('icon-gas')){if($('.tabNav').is(':visible')){if(window.location.hash&&window.location.hash.indexOf('erdgas')===-1){window.location.hash=window.location.hash+'&erdgas'}
if(window.location.hash&&window.location.hash.indexOf('&')===-1&&window.location.hash.indexOf('erdgas')===-1){window.location.hash=window.location.hash+'erdgas'}
if(window.location.hash===''){window.location.hash='erdgas'}}}else{removeHashFromUrl()}}
$wrapper.find('.tabNav a').removeClass('active');$t.addClass('active');$cont.eq(idx).show(0,function(){$wrapper.trigger('tabChange')})}
function removeHashFromUrl(){var uri=window.location.toString();if(window.location.hash==='#erdgas'){if(uri.indexOf('#')>0){var clean_uri=uri.substring(0,uri.indexOf('#'));window.history.replaceState({},document.title,clean_uri)}}else{if(window.location.hash.indexOf('&erdgas')>0){window.location.hash=window.location.hash.replace('&erdgas','')}
if(window.location.hash.indexOf('erdgas')>0){window.location.hash=window.location.hash.replace('erdgas','')}}}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.FAQ=(function($){var _$b,_$faq,_$resultCont,_$listCont,_$autocomplete,_data,_result,_suggestions,_highlightData,_totalEntries,_showCount=!0,_defaultIsRendered=!1,_hasResult=!0;function _init(){_$b=$(document.body);_$faq=_$b.find('.faqCont');if(!_$faq||_$faq.length===0){return}
_$faq.hide();_$resultCont=_$faq.find('.result');_$listCont=_$faq.find('.list');_$autocomplete=_$faq.find('.autocomplete');_$b.on('click',function(){EVO.Autocomplete.hide(_$autocomplete)});_$faq.on('click','input.search',function(e){e.stopPropagation()});_$faq.on('click','.accordion.nested > dt[data-category-id]',function(e){if($(e.currentTarget).hasClass('bbAccordion-open')){$.address.parameter('c',$(this).attr('data-category-id'));$.address.parameter('sc','no');$.address.parameter('q','no')}else{$.address.parameter('c','no');$.address.parameter('sc','no');$.address.parameter('q','no')}
$.address.update()});_$faq.on('click','.accordion.nested .accordion dt[data-subcategory-id]',function(e){if($(e.currentTarget).hasClass('bbAccordion-open')){$.address.parameter('sc',$(this).attr('data-subcategory-id'));$.address.parameter('q','no')}else{$.address.parameter('sc','no');$.address.parameter('q','no')}
$.address.update()});_$faq.on('click','.accordion.nested .accordion dt[data-frage-id]',function(e){if($(e.currentTarget).hasClass('bbAccordion-open')){$.address.parameter('q',$(this).attr('data-frage-id'))}else{$.address.parameter('q','no')}
$.address.update()});_$faq.on('submit','form',function(e){e.preventDefault()}).on('focus keyup afterAutocomplete','input.search',_doSearch).on('click','a.submit',function(e){e.preventDefault()});_showCount=_$faq.find('#showCount').val()==='1';_load()}
function _load(){if(!EVO.Config.debug){var contentUid=jQuery('#contentUid').val();$.ajax({type:'POST',url:EVO.Config.faq.url,cache:!1,data:{'tx_bbfaq_jsonfaqfeed[controller]':'Entries','tx_bbfaq_jsonfaqfeed[action]':'jsonFeed','tx_bbfaq_jsonfaqfeed[contentUid]':contentUid||'','type':'1412063867'},success:_onSuccessLoad})}else{$.ajax({url:EVO.Config.faq.url,dataType:'json',success:_onSuccessLoad})}}
function _onSuccessLoad(d){var parameterC=$.address.parameter('c'),parameterSC=$.address.parameter('sc'),parameterQ=$.address.parameter('q'),lastParameterC,lastParameterSC,lastParameterQ;_data={categories:!EVO.Config.debug?$.parseJSON(d):d};_$faq.show();_renderSearchResult();triggerClickCategory(parameterC);triggerClickSubCategory(parameterSC);tiggerClickQuestion(parameterQ);$('a.faqLink').address();$.address.change(function(){if(typeof e!=='function'){parameterC=$.address.parameter('c');parameterSC=$.address.parameter('sc');parameterQ=$.address.parameter('q');if(lastParameterC!==parameterC||lastParameterSC!==parameterSC||lastParameterQ!==parameterQ){if(lastParameterC!==parameterC){triggerClickCategory(parameterC)}
if(lastParameterSC!==parameterSC){triggerClickSubCategory(parameterSC)}
if(lastParameterQ!==parameterQ){tiggerClickQuestion(parameterQ)}}
lastParameterC=parameterC;lastParameterSC=parameterSC;lastParameterQ=parameterQ}});var $faqDataId;if(parameterQ&&parameterQ!=='no'){$faqDataId=$('dt[data-frage-id="'+parameterQ+'"]')}else if(parameterSC&&parameterSC!=='no'){$faqDataId=$('dt[data-subcategory-id="'+parameterSC+'"]')}else if(parameterC&&parameterC!=='no'){$faqDataId=$('dt[data-category-id="'+parameterC+'"]')}
function faqScroll(){if($faqDataId){$faqDataId.velocity('scroll',{duration:800,delay:500})}}
faqScroll()}
function triggerClickCategory(parameterC){var $curCategory=_$faq.find('dt[data-category-id="'+parameterC+'"]');if($curCategory&&$curCategory.length){$curCategory.addClass('bbAccordion-open');$curCategory.next().show()}}
function triggerClickSubCategory(parameterSC){var $curSubCategory=_$faq.find('dt[data-subcategory-id="'+parameterSC+'"]');if($curSubCategory&&$curSubCategory.length){$curSubCategory.addClass('bbAccordion-open');$curSubCategory.next().show()}}
function tiggerClickQuestion(parameterQ){var $curQuestion=_$faq.find('dt[data-frage-id="'+parameterQ+'"]');if($curQuestion&&$curQuestion.length){$curQuestion.addClass('bbAccordion-open');$curQuestion.next().show()}}
function _doSearch(e){var $t=$(e.currentTarget),searchTxt=$t.val();_onSearching(searchTxt)}
function _buildmarkup(d){var i,l,cur,curSub,curFrage,j,ll,k,lll,subEntries=0,c='';_totalEntries=0;c+='<dl class="accordion nested clear">';for(i=0,l=d.categories.length;i<l;i++){subEntries=0;cur=d.categories[i];if(cur.subMenu){for(k=0,lll=Object.keys(cur.subMenu).length;k<lll;k++){subEntries+=cur.subMenu[Object.keys(cur.subMenu)[k]].fragen.length;_totalEntries+=cur.subMenu[Object.keys(cur.subMenu)[k]].fragen.length}
if(_showCount){c+='<dt data-category-id="'+cur.id+'">'+cur.menu+' ('+subEntries+')</dt>'}else{c+='<dt data-category-id="'+cur.id+'">'+cur.menu+'</dt>'}
c+='<dd><div class="inner sub">';c+='<dl class="accordion nested sub">';for(k=0,lll=Object.keys(cur.subMenu).length;k<lll;k++){curSub=cur.subMenu[Object.keys(cur.subMenu)[k]];c+='<dt data-subcategory-id="'+curSub.id+'">'+curSub.menu+'</dt>';c+='<dd><div class="inner">';if(curSub.fragen.length){c+='<dl class="accordion">';for(j=0,ll=curSub.fragen.length;j<ll;j++){curFrage=curSub.fragen[j];c+='<dt data-frage-id="'+curFrage.id+'">'+curFrage.frage+'</dt>';c+='<dd><div class="inner">'+curFrage.antwort+'</div></dd>'}
c+='</dl>'}
c+='</div></dd>'}
c+='</dl>';c+='</div></dd>'}else{if(cur.fragen.length){_totalEntries+=cur.fragen.length;if(_showCount){c+='<dt data-category-id="'+cur.id+'">'+cur.menu+' ('+cur.fragen.length+')</dt>'}else{c+='<dt data-category-id="'+cur.id+'">'+cur.menu+'</dt>'}
c+='<dd><div class="inner">';if(cur.fragen.length){c+='<dl class="accordion">';for(j=0,ll=cur.fragen.length;j<ll;j++){curFrage=cur.fragen[j];c+='<dt data-frage-id="'+curFrage.id+'">'+curFrage.frage+'</dt>';c+='<dd><div class="inner">'+curFrage.antwort+'</div></dd>'}
c+='</dl>'}
c+='</div></dd>'}}}
c+='</dl>';return c}
function _render(){_$resultCont.html(_buildmarkup(_data));_$resultCont.find('.accordion').bbAccordion({'selectorHead':'dt','selectorContent':'dd',singleOpened:!1});_defaultIsRendered=!0}
function _renderSearchResult(searchTxt){if(searchTxt&&(searchTxt.length>=EVO.Config.faq.searchMinChar)){_hasResult=!0;_$resultCont.html(_buildmarkup(_highlightData));_$resultCont.find('.accordion').bbAccordion({'selectorHead':'dt','selectorContent':'dd',singleOpened:!1});_defaultIsRendered=!1}else{if(_hasResult){_render();_hasResult=!1}}
_renderAutoComplete(searchTxt);_$faq.find('.resultCount').text(_totalEntries)}
function _renderAutoComplete(searchTxt){if(_suggestions&&_suggestions.length&&searchTxt.length>=EVO.Config.faq.searchMinChar){EVO.Autocomplete.show(_$autocomplete,_suggestions)}else{EVO.Autocomplete.hide(_$autocomplete)}}
function _onSearching(searchTxt){if(searchTxt.length>=EVO.Config.faq.searchMinChar){_result=EVO.FAQSearchEngine.findQuestions(searchTxt,_data);_result=JSON.parse(JSON.stringify(_result));_highlightData=EVO.FAQSearchEngine.highlightEntries(searchTxt,_result);_suggestions=EVO.FAQSearchEngine.findSuggestions(searchTxt,_data);_suggestions=_suggestions.filter(EVO.FAQSearchEngine.uniqueFilter);_suggestions.sort();_renderSearchResult(searchTxt)}else if(!_defaultIsRendered){_render();_$faq.find('.resultCount').text(_totalEntries)}}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.FAQSearchEngine=(function($){function findQuestions(searchText,data){var result={};var result2={categories:[]},i=-1,lastcategory,lastsub;var searchTokens=searchText.split(' ');var searchExpressions=_buildSearchExpressions(searchTokens);data.categories.forEach(function(category){if(category.subMenu){Object.keys(category.subMenu).forEach(function(key){var subMenu=category.subMenu[key];subMenu.fragen.forEach(function(entry){var hit=_scanEntry(searchExpressions,entry);if(hit){hit.category=category.menu;if(!result[category.menu]){result[category.menu]=[]}
if(lastcategory!==category.menu){i++;result2.categories[i]={menu:category.menu,id:category.id,subMenu:{}}}
if(lastsub!==subMenu.menu){result2.categories[i].subMenu[subMenu.id]={id:subMenu.id,menu:subMenu.menu,fragen:[]}}
result2.categories[i].subMenu[subMenu.id].fragen.push(hit);lastsub=subMenu.menu;lastcategory=category.menu;result[category.menu].push(hit)}})})}else{category.fragen.forEach(function(entry){var hit=_scanEntry(searchExpressions,entry);if(hit){hit.category=category.menu;if(!result[category.menu]){result[category.menu]=[]}
if(lastcategory!==category.menu){i++;result2.categories[i]={menu:category.menu,id:category.id,fragen:[]}}
result2.categories[i].fragen.push(hit);lastcategory=category.menu;result[category.menu].push(hit)}})}});return result2}
function findSuggestions(searchText,data){var suggestions=[];var regExp;var searchToken=searchText.trim();if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
regExp=new RegExp(searchToken+"[-/\\wäöüÄÖÜß]*\\b(?![^<]*>)","gi");var questionMatches,answerMatches;data.categories.forEach(function(category){if(category.subMenu){Object.keys(category.subMenu).forEach(function(key){var subMenu=category.subMenu[key];subMenu.fragen.forEach(function(entry){questionMatches=entry.frage.match(regExp);answerMatches=entry.antwort.match(regExp);if(questionMatches!==null){questionMatches=questionMatches.map(function(s){return s.trim()});suggestions=suggestions.concat(questionMatches)}
if(answerMatches!==null){answerMatches=answerMatches.map(function(s){return s.trim()});suggestions=suggestions.concat(answerMatches)}})})}else{category.fragen.forEach(function(entry){questionMatches=entry.frage.match(regExp);answerMatches=entry.antwort.match(regExp);if(questionMatches!==null){questionMatches=questionMatches.map(function(s){return s.trim()});suggestions=suggestions.concat(questionMatches)}
if(answerMatches!==null){answerMatches=answerMatches.map(function(s){return s.trim()});suggestions=suggestions.concat(answerMatches)}})}});return suggestions}
function _scanEntry(searchExpressions,entry){var match=!0;var i=0;var searchExpression=searchExpressions[i];var searchLength=searchExpressions.length;while(match&&i<searchLength){match=searchExpression.test(entry.frage)||searchExpression.test(entry.antwort);i++;searchExpression=searchExpressions[i]}
return match?entry:!1}
function highlightEntries(searchText,entries){var searchTokens=searchText.split(' '),entry,i,l,j,ll,k,lll,curFrage,curAntwort,highlightExpression=_buildHighlightExpression(searchTokens),spanString='<span class="'+EVO.Config.faq.highlightClass+'">';for(i=0,l=entries.categories.length;i<l;i++){if(entries.categories[i].subMenu){for(k=0,lll=Object.keys(entries.categories[i].subMenu).length;k<lll;k++){var subMenu=entries.categories[i].subMenu[Object.keys(entries.categories[i].subMenu)[k]];for(j=0,ll=subMenu.fragen.length;j<ll;j++){curFrage=subMenu.fragen[j].frage;curAntwort=subMenu.fragen[j].antwort;subMenu.fragen[j].frage=curFrage.replace(highlightExpression,spanString+'$&</span>').replace(new RegExp(EVO.Utils.escapeRegExp(spanString+' '),'g'),' '+spanString);subMenu.fragen[j].antwort=curAntwort.replace(highlightExpression,spanString+'$&</span>').replace(new RegExp(EVO.Utils.escapeRegExp(spanString+' '),'g'),' '+spanString)}}}else{for(j=0,ll=entries.categories[i].fragen.length;j<ll;j++){curFrage=entries.categories[i].fragen[j].frage;curAntwort=entries.categories[i].fragen[j].antwort;entries.categories[i].fragen[j].frage=curFrage.replace(highlightExpression,spanString+'$&</span>').replace(new RegExp(EVO.Utils.escapeRegExp(spanString+' '),'g'),' '+spanString);entries.categories[i].fragen[j].antwort=curAntwort.replace(highlightExpression,spanString+'$&</span>').replace(new RegExp(EVO.Utils.escapeRegExp(spanString+' '),'g'),' '+spanString)}}}
return entries}
function _buildSearchExpressions(searchTokens){var searchExpressions=[],searchToken;if(searchTokens[searchTokens.length-1]===''){searchTokens.pop()}
for(var i=0,l=searchTokens.length;i<l-1;i=i+1){searchToken=searchTokens[i];if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
searchExpressions.push(new RegExp("("+searchToken+"\\b)(?![^<]*>)","i"))}
searchToken=searchTokens[i];if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
searchExpressions.push(new RegExp("("+searchToken+")(?![^<]*>)","i"));return searchExpressions}
function _buildHighlightExpression(searchTokens){var highlightExpressionStr="",searchToken;if(searchTokens[searchTokens.length-1]===''){searchTokens.pop()}
for(var i=0,l=searchTokens.length;i<l-1;i=i+1){searchToken=searchTokens[i];if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
highlightExpressionStr+="("+searchToken+"\\b)(?![^<]*>)|"}
searchToken=searchTokens[i];if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
highlightExpressionStr+="("+searchToken+")(?![^<]*>)";return new RegExp(highlightExpressionStr,"gi")}
function uniqueFilter(value,index,self){return self.indexOf(value)===index}
return{findQuestions:findQuestions,findSuggestions:findSuggestions,highlightEntries:highlightEntries,uniqueFilter:uniqueFilter}})(jQuery);var EVO=window.EVO||{};EVO.Autocomplete=(function($){var _$b,publicFunctions;function _init(){_$b=$(document.body);_$b.on('click','.autocomplete a',publicFunctions.onSelect)}
function onSelect(e){e.preventDefault();e.stopPropagation();var $t=$(e.currentTarget),$autocomplete=$t.closest('.autocomplete'),$input=$autocomplete.prev('input');$input.val($t.text());$input.trigger('afterAutocomplete');publicFunctions.hide($autocomplete)}
function show($t,d){var i,l,cur,c='';if(d&&d.length){for(i=0,l=d.length;i<l;i++){cur=d[i];c+='<div><a href="#">'+cur+'</a></div>'}
$t.html(c);$t.show()}else{publicFunctions.hide($t)}}
function hide($t){$t.html('');$t.hide()}
$(_init);publicFunctions={show:show,hide:hide,onSelect:onSelect};return publicFunctions})(jQuery);var EVO=window.EVO||{};EVO.Tools=(function($){var _$b,_$toolwrapper,_$toolbarwrapper,_$autocomplete,_$autocompleteAll,_$stromVerbrauchInputPk,_$stromVerbrauchInputFk,_$gasVerbrauchInputPk,_$gasVerbrauchInputFk,config={showTabs:!0,showSwitcher:!0,defaultUserType:'privatkunde',defaultTab:'strom',urlBacklink:'',urlStromPrivatkunde:'',urlStromFirmenkunde:'',urlGasPrivatkunde:'',urlGasFirmenkunde:''},publicFunctions,_searchdata;function _init(){_$b=$(document.body);_$toolwrapper=_$b.find('.tools, .tool');_$toolbarwrapper=_$b.find('.toolbar');_$autocompleteAll=_$toolwrapper.find('.autocomplete');_$stromVerbrauchInputPk=_$b.find('.stromToolVerbrauchPK');_$stromVerbrauchInputFk=_$b.find('.stromToolVerbrauchFK');_$gasVerbrauchInputPk=_$b.find('.gasToolVerbrauchPK');_$gasVerbrauchInputFk=_$b.find('.gasToolVerbrauchFK');_$stromVerbrauchInputFk.bbFormat(EVO.Config.tools.strom.inputFormatFk);_$stromVerbrauchInputPk.bbFormat(EVO.Config.tools.strom.inputFormatPk);_$stromVerbrauchInputPk.on('bbFormatChangeEvent',_changeStromVerbrauchInput);_$stromVerbrauchInputFk.on('bbFormatChangeEvent',_changeStromVerbrauchInput);_$gasVerbrauchInputPk.bbFormat(EVO.Config.tools.gas.inputFormatFk);_$gasVerbrauchInputFk.bbFormat(EVO.Config.tools.gas.inputFormatPk);_$gasVerbrauchInputPk.on('bbFormatChangeEvent',_changeGasVerbrauchInput);_$gasVerbrauchInputFk.on('bbFormatChangeEvent',_changeGasVerbrauchInput);_$b.on('click',function(){EVO.Autocomplete.hide(_$autocompleteAll)});_$toolwrapper.on('click','a.showAktionsCode',_showActionCodeInput).on('click','.buttons a',_onClickEnergyButtons).on('change','input[type="radio"]',_onChangeUserType).on('focus','input',_clearError);_$toolbarwrapper.on('click','.show-toolbar',_focusPLZ).on('focus','#toolbarPLZ',_showToolbar);_$toolwrapper.find('.buttons a:first-child').each(function(){var $form=$(this).closest("form"),$input=$form.find(".kwh-cell input"),value=$input.attr("value");if(value){$input.trigger('blur');$input.trigger({type:'bbFormatChangeEvent',bbValue:parseInt(value,10)})}else{$(this).trigger("click")}});_$b.on('submit','.tools .button.submit',function(e){e.preventDefault()}).on('submit','.tools form',publicFunctions.onSubmit).on('click','.tool .button.submit',_senddata).on('click','.tool a.back, .tools a.back',_backToInput).on('click','.tarifrechner.lpDetails a.back',_backToInput).on('click','.tool a.tarifabschliessen',_tarifAbschliessen).on('click','.tarifrechner.lpDetails a.tarifabschliessen',_tarifAbschliessen).on('click','.vergleich.tablesaw form a.getTarif,.tarifrechner a.getTarif',_tarifAbschliessen).on('click','.tools .tabNav a',_onEtrackerTarifrechnerProduktauswahl).on('change','.tools .waerme input[type=radio]',_onEtrackerTarifrechnerProduktauswahlWS).on('change','.tools .service input[type=radio]',_onEtrackerTarifrechnerProduktauswahlWS).on('click','a[href^="http"][target="_blank"]:not([href$=".pdf"]):not([href$=".doc"])',_onEtrackerExterneLinks).on('click','.wide a[href$=".pdf"],.wide a[href$=".doc"],.left a[href$=".pdf"],.left a[href$=".doc"]',_onEtrackerDownloadLinks).on('click','.sidebar a[href$=".pdf"], .sidebar a[href$=".doc"]',_onEtrackerDownloadLinksSidebar).on('click','a[href*="Mailto"]',_onEtrackerEmailLinks).on('focus keyup','input#toolbarPLZ, input#stromToolPLZ, input#gasToolPLZ, .tx-bb-energy-tariff-calculator input#zip, input#stromTarifPrivatPLZ, input#stromTarifFirmenPLZ, input#gasTarifPrivatPLZ, input#gasTarifFirmenPLZ',publicFunctions.doAutocomplete).on('click','.tabbed-tool-tabs.tabs a.icon-gas, .tabbed-tool-tabs.tabs a.icon-strom',_toggleActiveTool);_$b.find('.tool form, .tools.form').each(function(){$(this).data('action',$(this).attr('action'));$(this).data('mobileAction',$(this).attr('data-action-mobile'))});publicFunctions.doConfig();_$toolwrapper.find('.radioGroup input:checked').trigger('change');var type=EVO.UserType?EVO.UserType.getType():'';if(type===EVO.Config.userType.idFirmenKunden){_$toolwrapper.find('#stromToolFirmenkunde').trigger('click');_$toolwrapper.find('#toolbarStromToolFirmenkunde').trigger('click')}
_setBacklinkParams();_readCookie();_scrollToOfferCalc();if(_$toolwrapper.find("form.setUrlParams").length){_setUrlParams(_$toolwrapper.find("form.setUrlParams").eq(0))}
if(_$toolwrapper.find("form.setUrlParamsAndSubmit").length){_setUrlParamsAndSubmit(_$toolwrapper.find("form.setUrlParamsAndSubmit").eq(0))}
if(window.location.hash==='#erdgas'){$('.tabbed-tool-tabs.tabs').find('.tabNav a.icon-gas').trigger('click')}
_$b.on('click',_hideToolbar)}
function _toggleActiveTool(e){if($(e.currentTarget).hasClass('icon-gas')){_$b.find('.multi-tools-tool.strom').hide();_$b.find('.multi-tools-tool.gas').show()}else{_$b.find('.multi-tools-tool.gas').hide();_$b.find('.multi-tools-tool.strom').show()}}
function _setUrlParams($form){var params=EVO.Utils.getURLparams();if(params.plz){$form.find('input[name="plz"]').val(params.plz)}
if(params.kwh){$form.find('input.kwh').val(params.kwh).trigger('blur');$form.find('input.kwh').trigger({type:'bbFormatChangeEvent',bbValue:parseInt(params.kwh,10)})}}
function _setUrlParamsAndSubmit($form){_setUrlParams($form);var params=EVO.Utils.getURLparams();if(params.plz&&params.kwh){$form.find(".button.submit").trigger("click")}}
function _scrollToOfferCalc(){setTimeout(function(){$(".tx-bb-energy-tariff-calculator.offer-calc .table-slider").velocity('scroll',{duration:500,offset:-20,easing:'ease-in-out'})},500)}
function _setBacklinkParams(){var hash,hashArray,hashPLZ,hashVerbrauch,hashKundenTyp,hashSparte;if(window.location.hash){hash=window.location.hash.substring(1);hashArray=hash.split(',');hashKundenTyp=hashArray[0];hashSparte=hashArray[1];hashPLZ=hashArray[2];hashVerbrauch=hashArray[3]}
if(hashSparte==='strom'&&hashPLZ){_$b.find('#stromToolPLZ').val(hashPLZ);_$toolwrapper.find('.icon-strom').trigger('click')}
if(hashSparte==='strom'&&hashKundenTyp==='privatkunde'){if(hashVerbrauch){_$stromVerbrauchInputPk.val(hashVerbrauch);_$stromVerbrauchInputPk.trigger('blur');_$stromVerbrauchInputPk.trigger({type:'bbFormatChangeEvent',bbValue:parseInt(hashVerbrauch,10)})}}else if(hashSparte==='strom'&&hashKundenTyp==='firmenkunde'){if(hashVerbrauch){_$stromVerbrauchInputFk.val(hashVerbrauch);_$stromVerbrauchInputFk.trigger('blur');_$stromVerbrauchInputFk.trigger({type:'bbFormatChangeEvent',bbValue:parseInt(hashVerbrauch,10)})}}}
function _readCookie(){var cookieUserType=$.cookie(EVO.Config.tools.cookie.USER_TYPE),cookieStromData=$.cookie(EVO.Config.tools.cookie.STROM_DATA_PK),cookieGasData=$.cookie(EVO.Config.tools.cookie.GAS_DATA_PK);if(cookieUserType==='fk'){cookieStromData=$.cookie(EVO.Config.tools.cookie.STROM_DATA_FK);cookieGasData=$.cookie(EVO.Config.tools.cookie.GAS_DATA_FK)}
if(cookieStromData){_fillData(JSON.parse(cookieStromData),'strom',cookieUserType)}
if(cookieGasData){_fillData(JSON.parse(cookieGasData),'gas',cookieUserType)}}
function _fillData(cookieData,type,customertyp){if(!cookieData)return;var _$form=_$toolwrapper.find(type==='strom'?'.strom form':'.erdgas form');if(cookieData.ort&&cookieData.ort!=="")_$form.find('input[name=plz]').val(cookieData.plz+' '+cookieData.ort);else _$form.find('input[name=plz]').val(cookieData.plz);if(cookieData.ort&&cookieData.ort!=="")_$toolbarwrapper.find('input[name=plz]').val(cookieData.plz+' '+cookieData.ort);else _$toolbarwrapper.find('input[name=plz]').val(cookieData.plz);_$form.find('input[name=kwh]').val(cookieData.kwh);if(customertyp==='fk'){_$form.find(type==='gas'?'.gasToolVerbrauchFK,.gasToolVerbrauchFk':'.stromToolVerbrauchFK').val(cookieData.kwh).trigger('change').trigger('blur')}else{_$form.find(type==='gas'?'.gasToolVerbrauchPK, .gasToolVerbrauchPk':'.stromToolVerbrauchPK').val(cookieData.kwh).trigger('change').trigger('blur')}}
function doAutocomplete(e){var $t=$(e.currentTarget),searchTxt=$t.val(),match=searchTxt.match(/^(\d{0,5})$|^(\d{5} .*)$|^([A-Za-zÜÖÄüöä].*)$/);_$autocomplete=$t.parent().find(".autocomplete");if(match){publicFunctions.onAutocomplete(searchTxt)}else{$t.val(searchTxt.substr(0,5))}}
function onAutocomplete(searchTxt){if(searchTxt.length>=EVO.Config.tools.autocomplete.searchMinChar){$.ajax({type:"POST",url:EVO.Config.tools.autocomplete.url,cache:!1,data:{'tx_bbenergytariffcalculator_tariffcalculator[searchTxt]':searchTxt,'type':'1470814142'},success:function(data){publicFunctions.onSuccessAutocomplete(data,searchTxt)}})}}
function onSuccessAutocomplete(d,searchTxt){_searchdata=!EVO.Config.debug?$.parseJSON(d):d;if(_searchdata&&_searchdata.length&&searchTxt.length>=EVO.Config.tools.autocomplete.searchMinChar){EVO.Autocomplete.show(_$autocomplete,_searchdata)}else{EVO.Autocomplete.hide(_$autocomplete)}}
function _onEtrackerTarifrechnerProduktauswahl(e){var $ct=$(e.currentTarget),pagename=document.title.split(" - ");if(typeof ET_Event!=='undefined')ET_Event.eventStart('Tarifrechner '+pagename[0],$ct.text(),'Klick')}
function _onEtrackerTarifrechnerProduktauswahlWS(e,data){var $target=$(e.currentTarget),$tab=$target.closest('.tabs').find('.tabNav a.active'),tabName=$tab.text(),pagename=document.title.split(" - "),value=$target.val();if($target.closest('.radioBtnElement').is(':visible')){if(e.hasOwnProperty('originalEvent')||(data&&data.customEvent)){if(typeof ET_Event!=='undefined')ET_Event.eventStart('Tarifrechner '+pagename[0],tabName+' '+value,'Klick')}}}
function _onEtrackerExterneLinks(e){var $ct=$(e.currentTarget);if(typeof ET_Event!=='undefined')ET_Event.eventStart('Externe Seite',$ct.attr('href'),'Klick')}
function _onEtrackerDownloadLinks(e){var $ct=$(e.currentTarget);if(typeof ET_Event!=='undefined')ET_Event.eventStart($ct.text(),$ct.attr('href'),'Download')}
function _onEtrackerDownloadLinksSidebar(e){var $ct=$(e.currentTarget);if(typeof ET_Event!=='undefined')ET_Event.eventStart($ct.text()+' Sidebar-Buttons',$ct.attr('href'),'Download')}
function _onEtrackerEmailLinks(e){var $ct=$(e.currentTarget),ctTextContent=$ct.text().replace('remove-this.','');if(typeof ET_Event!=='undefined')ET_Event.eventStart('E-Mail-Adresse',ctTextContent,'Klick')}
function _tarifAbschliessen(e){e.preventDefault();var $t=$(e.currentTarget),$wrapper=$t.closest('.buttonHolder'),$form=$wrapper.find('form');if(EVO.MatchMediaQuery.getState()==='desktop'||EVO.MatchMediaQuery.getState()==='tablet-l'){$form.attr('action',$form.data('action'))}else{$form.attr('action',$form.data('mobileAction'))}
$form.submit()}
function doConfig(){var $toolsConfig=_$b.find('.tools-config'),showTabs=$toolsConfig.attr('data-config-showTabs'),showSwitcher=$toolsConfig.attr('data-config-showSwitcher'),defaultUserType=$toolsConfig.attr('data-config-defaultUserType'),defaultTab=$toolsConfig.attr('data-config-defaultTab'),base=$('base').attr('href')||'',urlBacklink,urlStromPrivatkunde,urlStromFirmenkunde,urlGasPrivatkunde,urlGasFirmenkunde;urlBacklink=$toolsConfig.attr('data-config-action-url-backlink');urlStromPrivatkunde=base+$toolsConfig.attr('data-config-action-url-strom-privatkunde');urlStromFirmenkunde=base+$toolsConfig.attr('data-config-action-url-strom-firmenkunde');urlGasPrivatkunde=base+$toolsConfig.attr('data-config-action-url-gas-privatkunde');urlGasFirmenkunde=base+$toolsConfig.attr('data-config-action-url-gas-firmenkunde');if(showTabs){config.showTabs=showTabs==='true';if(!config.showTabs&&showTabs!=='false'){config.showTabs=showTabs.replace(/ /g,"");config.showTabs=config.showTabs.split(",");_$toolwrapper.find('form > h3').hide();if(typeof config.showTabs==="object"){_$toolwrapper.find('.tabNav a').hide();for(var i=0,j=config.showTabs.length;i<j;i++){_$toolwrapper.find('.tabNav a.icon-'+config.showTabs[i]).show()}
if(config.showTabs.indexOf(config.defaultTab)===-1){defaultTab=config.showTabs[0]}}}}
if(showSwitcher){config.showSwitcher=showSwitcher==='true'}
if(defaultUserType){config.defaultUserType=defaultUserType}
if(defaultTab){config.defaultTab=defaultTab}
if(urlBacklink){config.urlBacklink=urlBacklink;_$toolwrapper.find("form").append('<input name="backpid" type="hidden" value="'+urlBacklink+'">')}
if(urlStromPrivatkunde){config.urlStromPrivatkunde=urlStromPrivatkunde}
if(urlStromFirmenkunde){config.urlStromFirmenkunde=urlStromFirmenkunde}
if(urlGasPrivatkunde){config.urlGasPrivatkunde=urlGasPrivatkunde}
if(urlGasFirmenkunde){config.urlGasFirmenkunde=urlGasFirmenkunde}
if(!config.showTabs){_$toolwrapper.find('.tabNav:not(.toolbar-row .tabNav)').hide();_$toolwrapper.find('form > h3').show()}
if(!config.showSwitcher){_$toolwrapper.find('.radioGroup').hide()}
if(config.defaultUserType==='firmenkunde'){_$toolwrapper.find('.radioGroup input[value="firmenkunde"]').trigger('click')}
if(config.defaultTab==='gas'){_$toolwrapper.find('.icon-gas').trigger('click')}else if(config.defaultTab==='service'){_$toolwrapper.find('.icon-service').trigger('click')}}
function _senddata(e){e.preventDefault();var $t=$(e.currentTarget),$wrapper=$t.closest('.tool'),$form=$wrapper.find('form.getjson'),$plz=$wrapper.find('input[name=plz]'),isFk=$wrapper.hasClass('fk'),isStrom=$wrapper.hasClass('strom'),$err=$wrapper.find('.errorTool'),v=$wrapper.find('.kwh').bbFormat(),preventdefault=$wrapper.hasClass('preventdefault'),max;if($plz.val()===''){$plz.addClass('error');return!1}
if(!preventdefault){if(isFk){max=isStrom?EVO.Config.tools.strom.firmenkundeMax:EVO.Config.tools.gas.firmenkundeMax;if(v>max){$err.html(isStrom?EVO.Config.tools.strom.errorFirmenkundeMax:EVO.Config.tools.gas.errorFirmenkundeMax);$err.find("a").attr("href",EVO.Utils.appendUrlParams($err.find("a"),{"kategorie":isStrom?"10":"5","plz":$plz.val(),"bis":1}));$err.velocity('slideDown');return!1}}else{max=isStrom?EVO.Config.tools.strom.privatkundeMax:EVO.Config.tools.gas.privatkundeMax;if(v>max){$err.html(isStrom?EVO.Config.tools.strom.errorPrivatkundeMax:EVO.Config.tools.gas.errorPrivatkundeMax);$err.find("a").attr("href",EVO.Utils.appendUrlParams($err.find("a"),{"kategorie":isStrom?"10":"5","plz":$plz.val(),"bis":1}));$err.velocity('slideDown');return!1}}
$form.find('input[name=kwh]').val($form.find('input.kwh').bbFormat());$.ajax({url:$form.attr('action'),type:$form.attr('method'),dataType:"json",data:$form.serialize(),success:function(d){_showResult($wrapper,d);EVO.Tracking.trackEvent(EVO.Config.tracking.tools.art.category,EVO.Config.tracking.tools.art.action,$wrapper.find('input[name="rechnertype"]').val());var sparte=isStrom?"strom":"gas",kundentyp=isFk?"firmenkunde":"privatkunde";if(d.code!==5){EVO.Tracking.trackPLZkWh(EVO.Config.tracking.tools.tarifBerechnen.category,EVO.Config.tracking.tools.tarifBerechnen.action,sparte+" - "+kundentyp,d.plz,d.kwh)}
if(d.code===5){EVO.Tracking.trackPLZkWh(EVO.Config.tracking.tools.ueberleitungEVON.category,EVO.Config.tracking.tools.ueberleitungEVON.action,sparte+" - "+kundentyp,d.plz,d.kwh)}}})}}
function _showResult($wrapper,d){var isLp=_$b.hasClass('evo-lp'),tooltip=_$b.find('.tooltip-hidden-content'),$result=!isLp?$wrapper.find('.result'):_$b.find('.tarifrechner .result'),$err=$wrapper.find('.errorTool'),showTariffInfo=$wrapper.hasClass("show-additional-tariff-info"),staffelIndex=0,currentStaffelIndex=staffelIndex;if(!d.error){$result.find('.tarifname').text(d.name_anzeige);$result.find('.plz').text(d.plz);$result.find('.ort').text(d.ort);$result.find('.verbrauch').bbFormat(EVO.Config.tools.strom.inputFormatFk);$result.find('.verbrauch').bbFormat({value:d.kwh});$result.find('form input[name="tarif"]').val(d.tarif);$result.find('form input[name="kwh"]').val(d.kwh);$result.find('form input[name="plz"]').val(d.plz);$result.find('form input[name="ort"]').val(d.ort);$result.find('form input[name="verbrauch"]').val(d.kwh);$result.find('form input[name="gesamtpreis"]').val(d.gesamtpreis);$result.find('form input[name="mandant"]').val('evo');if(d.telljaid){$result.find('form input[name="telljaid"]').val(d.telljaid)}else{$result.find('form input[name="telljaid"]').remove()}
if(showTariffInfo){if(typeof d.tarife!=="undefined"){$result.find('.verbrauchspreis').remove();if(typeof d.tarifeCounts!=="undefined"&&d.tarifeCounts.countVerbrauchspreis>1){$.each(d.tarife.reverse(),function(){if(this.selected){staffelIndex=currentStaffelIndex}
$result.find('.grundpreis').after('<tr class="verbrauchspreis">'+'<td class="verbrauchspreisName">'+this.verbrauchspreis_name+' <span class="netto">(Netto)</span>'+'</td>'+'<td>'+'<span class="netto">'+this.verbrauchspreis_netto+'&nbsp;'+this.verbrauchspreis_einheit+'</span>'+'<span class="brutto">'+this.verbrauchspreis_brutto+'&nbsp;'+this.verbrauchspreis_einheit+'</span>'+'</td>'+'</tr>');currentStaffelIndex++})}else{$grundpreis=$result.find('.grundpreis');$grundpreisTooltips=$grundpreis.find('.tooltip-hidden-content.ttrechner');hasTooltip16=!1;if($grundpreisTooltips.length){hasTooltip16=!0}
$grundpreis.after('<tr class="verbrauchspreis">'+'<td class="verbrauchspreisName">'+d.tarife[staffelIndex].verbrauchspreis_name+' <span class="netto">(Netto)</span>'+'</td>'+'<td>'+'<span class="netto">'+d.tarife[staffelIndex].verbrauchspreis_netto+'&nbsp;'+d.tarife[staffelIndex].verbrauchspreis_einheit+'</span>'+'<span class="brutto">'+d.tarife[staffelIndex].verbrauchspreis_brutto+'&nbsp;'+d.tarife[staffelIndex].verbrauchspreis_einheit+'</span>'+(hasTooltip16?'<a class="info-icon tooltip ARBEITSPREIS-tooltip" data-tooltip="ARBEITSPREIS-tooltip" href="#"></a>':'')+'</td>'+'</tr>');if(hasTooltip16){EVO.Tooltip.init();$grundpreis.find('.GRUNDPREIS-tooltip').tooltipster('content',$grundpreis.find('#GRUNDPREIS-tooltip').html().replace('##grundpreisBrutto19##',d.tarife[staffelIndex].grundpreis_brutto_19));jQuery('.ARBEITSPREIS-tooltip').tooltipster('content',jQuery('#ARBEITSPREIS-tooltip').html().replace('##arbeitspreisBrutto19##',d.tarife[staffelIndex].verbrauchspreis_brutto_19))}}}
$result.find('.monatspreis').text(d.gesamtpreis);if(d.tarife[staffelIndex].bonus_wert){$result.find('.bonusEinheit').text(d.tarife[staffelIndex].bonus_einheit);$result.find('.bonusWert').text(d.tarife[staffelIndex].bonus_wert);$result.find('.bonusWertNetto').text(d.tarife[staffelIndex].bonus_wert_netto);$result.find('.bonus').show()}else{$result.find('a.bonus-tooltip').remove();$result.find('.bonusWert').text('--');$result.find('.bonusWertNetto').text('--');$result.find('.bonus').hide()}
$result.find('.grundpreisEinheit').text(d.tarife[staffelIndex].grundpreis_einheit);$result.find('.grundpreisNetto').text(d.tarife[staffelIndex].grundpreis_netto);$result.find('.grundpreisBrutto').text(d.tarife[staffelIndex].grundpreis_brutto);$result.find('.laufzeit').text(d.vertragslaufzeit);if(d.preisgarantie_bis){$result.find('.preisgarantie').text(d.preisgarantie_bis)}else{$result.find('a.preisgarantie-tooltip').remove();$result.find('.preisgarantie').text('--')}
$result.find('.kuendigungsfrist').text(d.kuendigungsfrist);$result.find('.vertragsverlaengerung').text(d.vertragsverlaengerung_in_monaten);$result.find('.zahlungsarten').text(d.zahlungsarten);$result.find('.preisImErstenJahr').text(d.preis_im_ersten_jahr);$result.find('.preisImErstenJahrEinheit').text(d.preis_im_ersten_jahr_einheit);$result.find('.price-value').text(d.gesamtpreis+' €');_$b.find('.tool-disclaimer .disclaimer-text').html(d.beschreibung_rechtlich);$result.find('.verbrauchspreisEinheit').text(d.verbrauchspreis_einheit);$result.find('.verbrauchspreisNetto').text(d.verbrauchspreis_netto);$result.find('.verbrauchspreisBrutto').text(d.verbrauchspreis_brutto);if(typeof d.service_sterne!=="undefined"){$result.find('.service-sterne').html("");$.each(d.service_sterne,function(){$result.find('.service-sterne').append('<li>'+this+'</li>')})}
if(typeof d.zertifikate!=="undefined"){$result.find('.awards-images').html("");$result.find('.awards-images-mobile').html('<strong>Unsere Zertifikate</strong><div class="zertifikat-images"></div>');$.each(d.zertifikate,function(){if(this.tooltip.id){$result.find('.awards-images').append('<img class="tooltip" data-tooltip="'+this.tooltip.id+'" src="'+this.src+'" alt="Zertifikat" height="72"/>');$result.find('.awards-images-mobile .zertifikat-images').append('<img class="tooltip" data-tooltip="'+this.tooltip.id+'" src="'+this.src+'" alt="Zertifikat" height="72"/>');$result.find('.awards-images-mobile').append('<div id="'+this.tooltip.id+'" class="tooltip-hidden-content">'+this.tooltip.html+'</div>')}else{$result.find('.awards-images').append('<img src="'+this.src+'" alt="Zertifikat" height="72"/>');$result.find('.awards-images-mobile .zertifikat-images').append('<img src="'+this.src+'" alt="Zertifikat" height="72"/>')}})}
$wrapper.find('form').velocity("slideUp",{duration:300});$result.velocity("slideDown",{duration:300,complete:function(){EVO.Tooltip.init()}});if($($wrapper.data("disclaimer-selector")).length>0){$($wrapper.data("disclaimer-selector")).show()}}else if(isLp){$result.find('.ort').text(d.ort);$result.find('.grundpreisEinheit').text(d.grundpreis_einheit);$result.find('.grundpreisNetto').text(d.grundpreis_netto);$result.find('.grundpreisBrutto').text(d.grundpreis_brutto);$result.find('.verbrauchspreisEinheit').text(d.verbrauchspreis_einheit);$result.find('.verbrauchspreisNetto').text(d.verbrauchspreis_netto);$result.find('.verbrauchspreisBrutto').text(d.verbrauchspreis_brutto);$result.find('.monatspreisNetto').text(d.gesamtpreis_netto);$result.find('.monatspreisBrutto').text(d.gesamtpreis);if(d.bonus_wert!==null){$result.find('.bonusEinheit').text(d.bonus_einheit);$result.find('.bonusWert').text(d.bonus_wert);$result.find('.bonus').show();$result.find('.checkBonus').show()}else{$result.find('.bonus').hide();$result.find('.checkBonus').hide()}
if(d.ersparnis===undefined||parseInt(d.ersparnis,10)<=0){$result.find('.ersparnis').hide()}else{$result.find('.ersparnis').show()}
$result.find('.ersparnisWert').text(d.ersparnis);$result.find('.laufzeit').text(d.vertragslaufzeit);$result.find('.kuendigungsfrist').text(d.kuendigungsfrist);$result.find('.vertragsverlaengerung').text(d.vertragsverlaengerung_in_monaten);$result.find('.preisgarantie').text(d.preisgarantie_bis);$result.find('.zahlungsarten').text(d.zahlungsarten);if(d.grundversorger_name!==null){tooltip.find('.grundversorgerName').text(d.grundversorger_name);tooltip.find('.grundversorgerGrundpreisEinheit').text(d.grundversorger_grundpreis_einheit);tooltip.find('.grundversorgerGrundpreis').text(d.grundversorger_grundpreis);tooltip.find('.grundversorgerVerbrauchspreisEinheit').text(d.grundversorger_verbrauchspreis_einheit);tooltip.find('.grundversorgerVerbrauchspreis').text(d.grundversorger_verbrauchspreis)}
$wrapper.velocity("slideUp",{duration:300});$result.velocity("slideDown",{duration:300});EVO.Tooltip.update()}else{$result.find('.price-value').text(d.gesamtpreis+' EUR');$wrapper.find('form').velocity("slideUp",{duration:300});$result.velocity("slideDown",{duration:300})}}else{$err.html(d.message);$err.velocity('slideDown')}}
function _backToInput(e){e.preventDefault();var _$wrapper=$(e.currentTarget).closest('.tool, .tools'),isLp=_$b.hasClass('evo-lp'),showTariffInfo=_$wrapper.hasClass("show-additional-tariff-info"),$disclaimer=$(_$wrapper.data("disclaimer-selector"));if(showTariffInfo){_$wrapper.find('form').velocity("slideDown",{duration:300});_$wrapper.find('.result').velocity("slideUp",{duration:300});if($disclaimer.length>0){$disclaimer.hide();$disclaimer.find(".bbAccordion-open").click();_$wrapper.find(".bbAccordion-open").click()}}else if(isLp){_$wrapper=$(e.currentTarget).closest('.tx-bb-energy-tariff-calculator');_$wrapper.find('.tool').velocity("slideDown",{duration:300});_$wrapper.find('.result').velocity("slideUp",{duration:300})}else{_$wrapper.find('form').velocity("slideDown",{duration:300});_$wrapper.find('.result').velocity("slideUp",{duration:300})}}
function _clearError(e){var $t=$(e.currentTarget);$t.removeClass('error')}
function onSubmit(e){var $t=$(e.currentTarget),isFk=$t.find('input[name="kundentyp"]:checked').val()==='firmenkunde',v=isFk?$t.find('.fk input.validateVerbrauch').bbFormat():$t.find('.pk input.validateVerbrauch').bbFormat(),isStromRechner=$t.closest('.strom').length>0,$err=$t.find('.errorTool'),max,$plz=$t.find('input[name=plz]'),$toolbarPlz=$t.closest(".toolbar").find('#toolbarPLZ');if($toolbarPlz.length!==0){if($toolbarPlz.val()===''){$toolbarPlz.addClass('error');return!1}
$plz.val($toolbarPlz.val())}
if($plz.val()===''){$plz.addClass('error');return!1}
if(isFk){max=isStromRechner?EVO.Config.tools.strom.firmenkundeMax:EVO.Config.tools.gas.firmenkundeMax;if(v>max){$err.html(isStromRechner?EVO.Config.tools.strom.errorFirmenkundeMax:EVO.Config.tools.gas.errorFirmenkundeMax);$err.find("a").attr("href",EVO.Utils.appendUrlParams($err.find("a"),{"kategorie":isStromRechner?"10":"5","plz":$plz.val(),"bis":1}));$err.velocity('slideDown');return!1}
$t.find('input[name=kwh]').val(isStromRechner?$t.find('#stromToolVerbrauchFK').bbFormat():$t.find('#gasToolVerbrauchFK').bbFormat());$t.attr('action',isStromRechner?config.urlStromFirmenkunde:config.urlGasFirmenkunde)}else{max=isStromRechner?EVO.Config.tools.strom.privatkundeMax:EVO.Config.tools.gas.privatkundeMax;if(v>max){$err.html(isStromRechner?EVO.Config.tools.strom.errorPrivatkundeMax:EVO.Config.tools.gas.errorPrivatkundeMax);$err.find("a").attr("href",EVO.Utils.appendUrlParams($err.find("a"),{"kategorie":isStromRechner?"10":"5","plz":$plz.val(),"bis":1}));$err.velocity('slideDown');return!1}
$t.find('input[name=kwh]').val(isStromRechner?$t.find('#stromToolVerbrauchPK').bbFormat():$t.find('#gasToolVerbrauchPK').bbFormat());$t.attr('action',isStromRechner?config.urlStromPrivatkunde:config.urlGasPrivatkunde)}}
function _onChangeUserType(e){var $t=$(e.currentTarget),v=$t.val(),$form=$t.closest('form'),$err=$form.find('.errorTool'),$wrapper=$t.closest('.tools, .tool'),radioSwitchPkFk=$wrapper.find('input:radio');$err.hide();if(v==='privatkunde'){$wrapper.find('.switch').hide();$wrapper.find('.switch.pk').show()}else{$wrapper.find('.switch').hide();$wrapper.find('.switch.fk').show()}
$.each(radioSwitchPkFk,function(idx,val){if($(val).val()===v){$(val).trigger('click').prop('checked')}else{$(val).removeProp('checked')}})}
function _changeStromVerbrauchInput(e){var value=e.bbValue,$t=$(e.currentTarget),$wrapper=$t.closest('div.switch'),isFk=$wrapper.hasClass('fk'),$buttons=$wrapper.find('.buttons a'),closestValue=isFk?EVO.Utils.findClosest(EVO.Config.tools.strom.firmenkundeKWH,value):EVO.Utils.findClosest(EVO.Config.tools.strom.privatkundeKWH,value);$buttons.removeClass('active');$buttons.eq(closestValue.idx).addClass('active')}
function _changeGasVerbrauchInput(e){var value=e.bbValue,$t=$(e.currentTarget),$wrapper=$t.closest('div.switch'),isFk=$wrapper.hasClass('fk'),$buttons=$wrapper.find('.buttons a'),closestValue=isFk?EVO.Utils.findClosest(EVO.Config.tools.gas.firmenkundeKWH,value):EVO.Utils.findClosest(EVO.Config.tools.gas.privatkundeKWH,value);$buttons.removeClass('active');$buttons.eq(closestValue.idx).addClass('active')}
function _onClickEnergyButtons(e){e.preventDefault();var $t=$(e.currentTarget),$wrapper=$t.closest('.buttons'),$form=$t.closest('form'),$err=$form.find('.errorTool'),$switch=$wrapper.closest('div.switch'),isFk=$switch.hasClass('fk'),$other=$wrapper.find('a').not($t),idx=$t.index(),energy='strom';$t.addClass('active');$other.removeClass('active');if($wrapper.data('energy')){energy=$wrapper.data('energy')}
if(isFk){$switch.find('.'+energy+'ToolVerbrauchFK').bbFormat({value:EVO.Config.tools[energy].firmenkundeKWH[idx]})}else{$switch.find('.'+energy+'ToolVerbrauchPK').bbFormat({value:EVO.Config.tools[energy].privatkundeKWH[idx]})}
$err.hide()}
function _focusPLZ(e){e.preventDefault();var $t=$(e.currentTarget),$toolbar=$t.parents('.toolbar'),$plz=$toolbar.find('#toolbarPLZ');if(!$toolbar.hasClass('open')){$plz.focus()}}
function _showToolbar(e){var $t=$(e.currentTarget),$toolbar=$t.parents('.toolbar');if(!$toolbar.hasClass('open')){$toolbar.find('.tabCont').velocity('slideDown',{duration:150});$toolbar.addClass('open');EVO.ServiceLascheDesktopTablet.hide();_$b.find('#tsbadge4_db8d3657bdbe440c985ae127463eaad4').hide()}}
function _hideToolbar(e){var $t=$(e.target),$toolbarParent=$t.parents('.toolbar'),$toolbar=$('.toolbar');if($toolbarParent.length===0){$toolbar.find('.tabCont').velocity('slideUp',{duration:150});if($toolbar.hasClass('open')){$toolbar.removeClass('open')}
if(EVO.ServiceLascheDesktopTablet){EVO.ServiceLascheDesktopTablet.show()}
_$b.find('#tsbadge4_db8d3657bdbe440c985ae127463eaad4').show()}}
function _showActionCodeInput(e){e.preventDefault();var $t=$(e.currentTarget),$wrapper=$t.closest('.boxLeft'),$aktionsCode=$wrapper.find('.aktionsCode'),isOpen=$aktionsCode.hasClass('open');if(!isOpen){$aktionsCode.velocity('slideDown',{duration:150});$aktionsCode.addClass('open')}else{$aktionsCode.velocity('slideUp',{duration:150});$aktionsCode.removeClass('open')}}
$(_init);publicFunctions={doAutocomplete:doAutocomplete,onAutocomplete:onAutocomplete,onSuccessAutocomplete:onSuccessAutocomplete,doConfig:doConfig,onSubmit:onSubmit};return publicFunctions})(jQuery);var EVO=window.EVO||{};EVO.CompareTable=(function($){var _$b,_$wrapper,_$btnRight,_$btnLeft,_$count,_$topbar,_$slider,_totalCols,_visibleCols,_indexCols,_$rowInnerHeights;function _init(){_$b=$(document.body);_$wrapper=_$b.find('.tarifrechner .compare');_$topbar=_$wrapper.find('.tablesaw-advance');_$count=$('<span class="count"></span>');_$topbar.prepend(_$count);_$btnRight=_$wrapper.find('.tablesaw-nav-btn.right');_$btnLeft=_$wrapper.find('.tablesaw-nav-btn.left');_$wrapper.on('click','.acc-toggle > span',_toggleAccordion);_$btnRight.on('click',function(){setTimeout(_updateCount,0)});_$btnLeft.on('click',function(){setTimeout(_updateCount,0)});_$wrapper.find('.acc-toggle .inner').wrap('<div class="spacer"></div>');_setLabels();$(window).load(function(){_initSlider();setTimeout(_setTableHeights,100)});setTimeout(_updateCount,0)}
function _initSlider(){function getItemMargin(){return(window.innerWidth<1001)?10:30}
function getGridSize(){return(window.innerWidth<769)?0:3}
function toggleDirectionNav(){if(_$slider.length>0){if(_$slider.data('flexslider').pagingCount>1){$(".table-slider-custom-navigation").show()}else{$(".table-slider-custom-navigation").hide()}}}
var resizeTimer;_$slider=$('.table-slider').flexslider({animation:"slide",selector:'.slides > .slide-column',animationLoop:!1,itemWidth:290,itemMargin:getItemMargin(),controlNav:!1,directionNav:!0,customDirectionNav:$(".table-slider-custom-navigation a"),slideshow:!1,minItems:getGridSize(),maxItems:getGridSize()});toggleDirectionNav();$(window).on('resize',function(e){if(_$slider.length>0){var gridSize=getGridSize(),itemMargin=getItemMargin();_$slider.data('flexslider').vars.minItems=gridSize;_$slider.data('flexslider').vars.maxItems=gridSize;_$slider.data('flexslider').vars.itemMargin=itemMargin;toggleDirectionNav();clearTimeout(resizeTimer);resizeTimer=setTimeout(function(){_$slider.data('flexslider').resize();setTimeout(function(){_$slider.find(".slide-column").css("margin-right",itemMargin);gridSize=getGridSize();clearTimeout(resizeTimer);_setTableHeights()},150)},150)}})}
function _setTableHeights(){var $columns=_$wrapper.find('.slide-column');$columns.find('.spacer').each(function(i,el){if($(el).height()>0)
$(el).height("auto")});var rowHeights=[],_openRows=[];_$rowInnerHeights=[];$columns.each(function(i,col){$(col).find("> div").css("min-height","").each(function(i,row){var $row=$(row);if(_openRows[i])
_openRows[i]=_openRows[i]||$row.hasClass('open');else _openRows[i]=$row.hasClass('open');if(rowHeights[i])
rowHeights[i]=Math.max(rowHeights[i],$row.outerHeight(!0));else rowHeights[i]=$row.outerHeight();if($row.hasClass('acc-toggle')){var $inner=$row.find('> .spacer .inner');if(_$rowInnerHeights[i])
_$rowInnerHeights[i]=Math.max(_$rowInnerHeights[i],$inner.actual('outerHeight',{includeMargin:!0}));else _$rowInnerHeights[i]=$inner.actual('outerHeight',{includeMargin:!0})}})});$columns.each(function(i,col){$(col).find("> div").each(function(i,row){if(_openRows[i]){$(row).find('> .spacer').height(_$rowInnerHeights[i]);$(row).css("min-height",rowHeights[i]-_$rowInnerHeights[i])}else $(row).css("min-height",rowHeights[i])})})}
function _toggleAccordion(e){var $t=$(e.currentTarget),$p=$t.parent(),$innerAcc=$p.hasClass("acc-toggle-inner"),$idx=$p.index(),isOpen=$t.hasClass('open'),$columns=_$wrapper.find('.slide-column, .fixed-column'),tempHeight=0;if($innerAcc){$idx=$p.parent().closest(".acc-toggle").index()}
if(!isOpen){$columns.each(function(i,col){var temp=$(col).find("> div").eq($idx),height=0,spacer;if(!$innerAcc){temp.addClass('open').find('> span').addClass('open');temp.find(".acc-toggle-inner.open .inner").each(function(){height+=$(this).outerHeight()});spacer=temp.find('> .spacer');spacer.velocity("stop").velocity({height:_$rowInnerHeights[$idx]+height,duration:300})}else{$p.addClass('open').find('> span').addClass('open');$p.closest(".inner").find(".acc-toggle-inner.open .inner").each(function(){height+=$(this).outerHeight()});spacer=$p.find('> .spacer');spacer.velocity("stop").velocity({height:spacer.find(".inner").outerHeight(),duration:300});spacer=temp.find('> .spacer');if(spacer.height()<_$rowInnerHeights[$idx]+height){spacer.velocity("stop").velocity({height:_$rowInnerHeights[$idx]+height,duration:300})}}})}else{$columns.each(function(i,col){var temp=$(col).find("> div").eq($idx),spacer=temp.find('> .spacer'),height=0;if(!$innerAcc){temp.find('> span').removeClass('open');spacer.velocity("stop").velocity({height:0,duration:300},{complete:function(){temp.removeClass('open');temp.find(".acc-toggle-inner").removeClass("open");temp.find(".acc-toggle-inner > span").removeClass("open");temp.find(".acc-toggle-inner > .spacer").removeAttr("style")}})}else{$p.find('> span').removeClass('open');temp.find(".acc-toggle-inner.open").not($p).find(".inner").each(function(){height+=$(this).outerHeight()});if(tempHeight<height){tempHeight=height}}});if($innerAcc){$columns.each(function(i,col){var temp=$(col).find("> div").eq($idx);var spacer=$p.find('> .spacer');spacer.velocity("stop").velocity({height:0,duration:300},{complete:function(){$p.removeClass('open')}});spacer=temp.find('> .spacer');spacer.velocity("stop").velocity({height:_$rowInnerHeights[$idx]+tempHeight,duration:300})})}}}
function _setLabels(){_$btnRight.attr("title",EVO.Config.compareTable.next);_$btnLeft.attr("title",EVO.Config.compareTable.prev)}
function _getCount(){_totalCols=_$wrapper.find('th').not('.fixedCell');_visibleCols=_totalCols.not('.tablesaw-cell-hidden');_indexCols=_totalCols.index(_visibleCols);return{total:_totalCols.length,visible:_visibleCols.length,index:_totalCols.index(_visibleCols)}}
function _updateCount(){var counts=_getCount(),countStr='',start=counts.index+1,end=counts.index+counts.visible;if(counts.visible>1){countStr="Tarife "+start+" bis "+end+" von "+counts.total+" Tarifen"}else{countStr="Tarif "+start+" von "+counts.total+" Tarifen"}
_$count.html(countStr)}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.RangeSlider=(function($){var _$b,_$toolwrapper,_$rangeSliderPk,_$rangeSliderFk,_$rangeSliderScalePk,_$gasToolVerbrauchFk,_$gasToolVerbrauchPk,_lastInputValue=0;function _init(){_$b=$(document.body);_$toolwrapper=_$b.find('.tools, .tool, .tx-bb-energy-tariff-calculator');_$rangeSliderPk=_$b.find('.pk .rangeSlider');_$rangeSliderFk=_$b.find('.fk .rangeSlider');_$rangeSliderScalePk=_$b.find('.pk .scale').get(0);_$gasToolVerbrauchFk=_$b.find('.gasToolVerbrauchFk');_$gasToolVerbrauchPk=_$b.find('.gasToolVerbrauchPk');_$gasToolVerbrauchFk.bbFormat(EVO.Config.tools.gas.inputFormatFk);_$gasToolVerbrauchPk.bbFormat(EVO.Config.tools.gas.inputFormatPk);_$gasToolVerbrauchFk.on('bbFormatChangeEvent',_changegasVerbrauchInput);_$gasToolVerbrauchPk.on('bbFormatChangeEvent',_changegasVerbrauchInput);if(_$rangeSliderPk&&_$rangeSliderPk.length){_$rangeSliderPk.each(function(){noUiSlider.create(this,EVO.Config.tools.gas.sliderPk);this.noUiSlider.on('slide',_.bind(function(v){v=parseInt(v,10);$(this).closest('.switch').find('input.kwh').bbFormat({value:_calcVerbrauch(v)})},this))})}
if(_$rangeSliderFk&&_$rangeSliderFk.length){_$rangeSliderFk.each(function(){noUiSlider.create(this,EVO.Config.tools.gas.sliderFk);this.noUiSlider.on('slide',_.bind(function(v){v=parseInt(v,10);if(_lastInputValue<=v){$(this).closest('.switch').find('input.kwh').bbFormat({value:_calcVerbrauch(v)})}
_lastInputValue=0;_$b.find('.erdgas form .errorTool').hide()},this))})}
_setBacklinkParams()}
function _setBacklinkParams(){var hash,hashArray,hashPLZ,hashVerbrauch,hashKundenTyp,hashSparte;if(window.location.hash){hash=window.location.hash.substring(1);hashArray=hash.split(',');hashKundenTyp=hashArray[0];hashSparte=hashArray[1];hashPLZ=hashArray[2];hashVerbrauch=hashArray[3]}
if(hashSparte==='gas'&&hashPLZ){_$b.find('#gasToolPLZ').val(hashPLZ);_$toolwrapper.find('.icon-gas').trigger('click')}
if(hashSparte==='gas'&&hashKundenTyp==='privatkunde'){if(hashVerbrauch){_$gasToolVerbrauchPk.val(hashVerbrauch);_$gasToolVerbrauchPk.trigger('blur');_$gasToolVerbrauchPk.trigger({type:'bbFormatChangeEvent',bbValue:parseInt(hashVerbrauch,10)})}}else if(hashSparte==='gas'&&hashKundenTyp==='firmenkunde'){if(hashVerbrauch){_$gasToolVerbrauchFk.val(hashVerbrauch);_$gasToolVerbrauchFk.trigger('blur');_$gasToolVerbrauchFk.trigger({type:'bbFormatChangeEvent',bbValue:parseInt(hashVerbrauch,10)})}}}
function _calcVerbrauch(v){return v*200}
function _claclFlaesche(v){return v/200}
function _changegasVerbrauchInput(e){var value=e.bbValue,$t=$(e.currentTarget),$form=$t.closest('form'),$err=$form.find('.errorTool'),$wrapper=$t.closest('div.switch'),$slider=$wrapper.find('.rangeSlider');if($slider.length){_lastInputValue=value;$slider.get(0).noUiSlider.set(_claclFlaesche(value))}
$err.hide()}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.FuelCalc=(function($){var $ctx,$compareValues,$result,animationDuration=300;function _init(){$ctx=$('.fuelcalc');$compareValues=$ctx.find('.hiddenCompareValues');$result=$ctx.find('.result');if($ctx.length===0){return}
$ctx.find('#kmyear').bbFormat(EVO.Config.fuelCalc.kmOptions);$ctx.find('#usefullLife').bbFormat(EVO.Config.fuelCalc.yearsOptions);$ctx.find('#superConsumption').bbFormat(EVO.Config.fuelCalc.roz95UsageOptions);$ctx.find('#dieselConsumption').bbFormat(EVO.Config.fuelCalc.dieselUsageOptions);$ctx.find('#gasConsumption').bbFormat(EVO.Config.fuelCalc.naturalGasUsageOptions);$ctx.find('#superPrice').bbFormat(EVO.Config.fuelCalc.roz95PriceOptions);$ctx.find('#dieselPrice').bbFormat(EVO.Config.fuelCalc.dieselPriceOptions);$ctx.find('#gasPrice').bbFormat(EVO.Config.fuelCalc.naturalGasPriceOptions);$ctx.find('.compareValues a').on('click',toggleCompareValues);$ctx.find('.calculate.button').on('click',calculate);$ctx.find('.back').on('click',goBack);initCompareValues();$compareValues.find('table').find('.action a').on('click',useCompareValues);initResult()}
function initCompareValues(){var i,l,s='';for(i=0,l=EVO.Config.fuelCalc.compareValues.length;i<l;++i){s+='<tr>'+'<td>'+EVO.Config.fuelCalc.compareValues[i][0]+'</td>'+'<td>'+EVO.Config.fuelCalc.compareValues[i][1]+'</td>'+'<td>'+EVO.Config.fuelCalc.compareValues[i][2]+'</td>'+'<td class="action"><a class="button-usevalues" href="#">&nbsp;<span class="onhover">Werte übernehmen</span></a></td>'+'</tr>'}
$compareValues.find('table').append(s).find('td:not(".action")').bbFormat(EVO.Config.fuelCalc.compareValuesOptions)}
function initResult(){var $compareTable=$result.find('.compare table'),$teaserBox=$ctx.find('.teaserbox');$compareTable.find('.pricefuel').find('td').bbFormat(EVO.Config.fuelCalc.resultFuelCostsOptions);$compareTable.find('.investment').find('td').bbFormat(EVO.Config.fuelCalc.resultFuelCostsOptions);$compareTable.find('.subtotal').find('td').bbFormat(EVO.Config.fuelCalc.resultFuelCostsOptions);$compareTable.find('.sponsoring').find('td span').bbFormat(EVO.Config.fuelCalc.resultFuelCostsOptions);$($compareTable.find('.sponsoring').find('td').get(1)).find('span').bbFormat(EVO.Config.fuelCalc.resultFuelCostsOptions);$compareTable.find('.sum').find('td h3').bbFormat(EVO.Config.fuelCalc.resultFuelCostsOptions);$teaserBox.find('.km').bbFormat(EVO.Config.fuelCalc.kmOptions);$teaserBox.find('.savingsDiesel').bbFormat(EVO.Config.fuelCalc.teaserBoxOptions);$teaserBox.find('.savingsSuper').bbFormat(EVO.Config.fuelCalc.teaserBoxOptions);$teaserBox.find('.savings').bbFormat(EVO.Config.fuelCalc.teaserBoxSavingsOptions)}
function toggleCompareValues(e){if(e){e.preventDefault()}
var $ct=$ctx.find('.compareValues a');if($ct.hasClass('button-arrow-bottom')){$ct.removeClass('button-arrow-bottom');$ct.addClass('button-arrow-top');$compareValues.velocity("slideDown",{duration:animationDuration})}else{$ct.removeClass('button-arrow-top');$ct.addClass('button-arrow-bottom');$compareValues.velocity("slideUp",{duration:animationDuration})}}
function useCompareValues(e){var idx;if(e){e.preventDefault()}
var $ct=$(e.currentTarget);idx=$ct.closest('tr').index()-1;$ctx.find('#superConsumption').bbFormat({value:EVO.Config.fuelCalc.compareValues[idx][2]});$ctx.find('#dieselConsumption').bbFormat({value:EVO.Config.fuelCalc.compareValues[idx][1]});$ctx.find('#gasConsumption').bbFormat({value:EVO.Config.fuelCalc.compareValues[idx][0]});toggleCompareValues();$ctx.velocity("scroll",{duration:animationDuration,delay:animationDuration})}
function calculate(e){var costGas,costSuper,costDiesel,investmentGas,investmentSuper,investmentDiesel,gasvssuper,gasvsdiesel,bestsavings,sponsoringGas=0,$inputs=$($ctx.find('.inputReview table tr').get(0)).find('td'),calculationType=$ctx.find('#calculationType').val(),calculationTypeString,kmYear=$ctx.find('#kmyear').bbFormat(),years=$ctx.find('#usefullLife').bbFormat(),$compareTable=$result.find('.compare table'),$teaserBox=$ctx.find('.teaserbox');if(e){e.preventDefault()}
$ctx.find('.step1').velocity("slideUp",{duration:animationDuration});$ctx.find('.result').velocity("slideDown",{duration:animationDuration,delay:animationDuration});$($inputs.get(0)).find('strong').text($ctx.find('#kmyear').val());$($inputs.get(1)).find('strong').text($ctx.find('#usefullLife').val());if(calculationType==='new'){calculationTypeString="Neuwagen";investmentGas=2500;investmentSuper=0;investmentDiesel=2500;sponsoringGas=500*$ctx.find('#gasPrice').bbFormat()}else if(calculationType==='used'){calculationTypeString="Gebrauchwagen";investmentGas=1250;investmentSuper=0;investmentDiesel=1250}else{calculationTypeString="Umrüstung auf Erdgas";investmentGas=4000;investmentSuper=4000;investmentDiesel=0}
$($inputs.get(2)).find('strong').text(calculationTypeString);$($compareTable.find('.consumption').find('td').get(0)).text($ctx.find('#superConsumption').val());$($compareTable.find('.consumption').find('td').get(1)).text($ctx.find('#gasConsumption').val());$($compareTable.find('.consumption').find('td').get(2)).text($ctx.find('#dieselConsumption').val());$($compareTable.find('.priceperlkm').find('td').get(0)).text($ctx.find('#superPrice').val());$($compareTable.find('.priceperlkm').find('td').get(1)).text($ctx.find('#gasPrice').val());$($compareTable.find('.priceperlkm').find('td').get(2)).text($ctx.find('#dieselPrice').val());costGas=years*kmYear*$ctx.find('#gasConsumption').bbFormat()*$ctx.find('#gasPrice').bbFormat()/100;costSuper=years*kmYear*$ctx.find('#superConsumption').bbFormat()*$ctx.find('#superPrice').bbFormat()/100;costDiesel=years*kmYear*$ctx.find('#dieselConsumption').bbFormat()*$ctx.find('#dieselPrice').bbFormat()/100;$($compareTable.find('.pricefuel').find('td').get(0)).bbFormat({value:costSuper});$($compareTable.find('.pricefuel').find('td').get(1)).bbFormat({value:costGas});$($compareTable.find('.pricefuel').find('td').get(2)).bbFormat({value:costDiesel});$($compareTable.find('.investment').find('td').get(0)).bbFormat({value:investmentSuper});$($compareTable.find('.investment').find('td').get(1)).bbFormat({value:investmentGas});$($compareTable.find('.investment').find('td').get(2)).bbFormat({value:investmentDiesel});$($compareTable.find('.subtotal').find('td').get(0)).bbFormat({value:costSuper+investmentSuper});$($compareTable.find('.subtotal').find('td').get(1)).bbFormat({value:costGas+investmentGas});$($compareTable.find('.subtotal').find('td').get(2)).bbFormat({value:costDiesel+investmentDiesel});$($compareTable.find('.sponsoring').find('td').get(1)).find('span').bbFormat({value:sponsoringGas});$($compareTable.find('.sum').find('td').get(0)).find('h3').bbFormat({value:costSuper+investmentSuper});$($compareTable.find('.sum').find('td').get(1)).find('h3').bbFormat({value:costGas+investmentGas-sponsoringGas});$($compareTable.find('.sum').find('td').get(2)).find('h3').bbFormat({value:costDiesel+investmentDiesel});gasvssuper=(costSuper+investmentSuper)-(costGas+investmentGas-sponsoringGas);gasvsdiesel=(costDiesel+investmentDiesel)-(costGas+investmentGas-sponsoringGas);bestsavings=Math.max(gasvssuper,gasvsdiesel);if(bestsavings>0){$teaserBox.find('.cansave').show();$teaserBox.find('.cannotsave').hide()}else{$teaserBox.find('.cansave').hide();$teaserBox.find('.cannotsave').show()}
if(gasvssuper<0){gasvssuper*=-1;$teaserBox.find('.superCheap').text('teurer')}else{$teaserBox.find('.superCheap').text('günstiger')}
if(gasvsdiesel<0){gasvsdiesel*=-1;$teaserBox.find('.dieselCheap').text('teurer')}else{$teaserBox.find('.dieselCheap').text('günstiger')}
$teaserBox.find('.years').text($ctx.find('#usefullLife').val());$teaserBox.find('.km').bbFormat({value:$ctx.find('#usefullLife').bbFormat()*$ctx.find('#kmyear').bbFormat()});$teaserBox.find('.savingsDiesel').bbFormat({value:gasvsdiesel});$teaserBox.find('.savingsSuper').bbFormat({value:gasvssuper});$teaserBox.find('.savings').bbFormat({value:bestsavings})}
function goBack(e){if(e){e.preventDefault()}
$ctx.find('.result').velocity("slideUp",{duration:animationDuration});$ctx.find('.step1').velocity("slideDown",{duration:animationDuration,delay:animationDuration})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.MapUtils=(function($){function getMyLocation(address,callback){var geocoder=new google.maps.Geocoder(),coord={lng:0,lat:0};geocoder.geocode({'address':address,'region':EVO.Config.maps.region},function(results,status){if(status===google.maps.GeocoderStatus.OK){coord.lng=results[0].geometry.location.lng();coord.lat=results[0].geometry.location.lat()}
if(_.isFunction(callback)){callback(coord)}})}
function coordToAddress(lat,lng,callback){var geocoder=new google.maps.Geocoder(),latlng=new google.maps.LatLng(lat,lng);geocoder.geocode({'latLng':latlng},function(results,status){if(status===google.maps.GeocoderStatus.OK){if(results[1]){if(_.isFunction(callback)){callback(results[1])}}}})}
function getAirDistance(myLatLng,advisorLatLng){return google.maps.geometry.spherical.computeDistanceBetween(myLatLng,advisorLatLng)}
function getLatLngObject(lat,lng){return new google.maps.LatLng(lat,lng)}
function getDistance(myLatLng,kizLatLng,callback){var directionsService=new google.maps.DirectionsService(),request={origin:myLatLng,destination:kizLatLng,travelMode:google.maps.DirectionsTravelMode.DRIVING},result={distance:0,duration:0};directionsService.route(request,function(response,status){var resp;if(response&&response.routes&&response.routes.length){resp=response.routes[0].legs[0]}
if(status===google.maps.DirectionsStatus.OK&&resp){result.distance=resp.distance.value/1000;result.duration=resp.duration.text;if(_.isFunction(callback)){callback(result)}}})}
return{getMyLocation:getMyLocation,getAirDistance:getAirDistance,getLatLngObject:getLatLngObject,getDistance:getDistance,coordToAddress:coordToAddress}})(jQuery);var EVO=window.EVO||{};EVO.KizSuche=(function($){var _$b,_$w,_$kiz,_gm,_$location,_locationInfo={},_autocomplete,_autocompleteListener,_markers=[];function _init(){_$b=$(document.body);_$w=$(window);_$kiz=_$b.find('.kiz');_$location=_$kiz.find('.location');_$w.on('resize',_onResize);if(_$kiz.find('.gm').length){_$kiz.on('focus','#kizMyLocation',_doInputEmpy).on('click','a.search',_onClickSearch).on('click','a.getPosition',_getPosition);_$kiz.find('.gm').each(function(){_initMap(this)});_$location.each(function(){var $t=$(this),name=$t.attr('data-name'),lat=$t.attr('data-lat'),lng=$t.attr('data-lng');_locationInfo[name]={lat:lat,lng:lng,el:$t}});$(document).on({'DOMNodeInserted':function(){$('.pac-item, .pac-item span',this).addClass('needsclick')}},'.pac-container');_addAutocomplete();_initSearch()}}
function _doInputEmpy(e){$(e.currentTarget).val('')}
function _addAutocomplete(){_autocomplete=new google.maps.places.Autocomplete(_$kiz.find('#kizMyLocation').get(0),EVO.Config.kiz.autocomplete);_autocompleteListener=google.maps.event.addListener(_autocomplete,'place_changed',function(){_onClickSearch()})}
function _getPosition(e){if(e){e.preventDefault()}
var lat,lng;if(navigator&&navigator.geolocation){navigator.geolocation.getCurrentPosition(function(position){lat=position.coords.latitude;lng=position.coords.longitude;_search({lat:lat,lng:lng});EVO.MapUtils.coordToAddress(lat,lng,function(resp){_$kiz.find('#kizMyLocation').val(resp.formatted_address)})},function(){})}}
function _onClickSearch(e){if(e){e.preventDefault()}
var val=_$kiz.find('#kizMyLocation').val();EVO.MapUtils.getMyLocation(val,function(myLocation){_search(myLocation)})}
function _initSearch(){_search({lat:EVO.Config.maps.center.lat,lng:EVO.Config.maps.center.lng})}
function _search(myLocation){var i,count=0,respCount=0;_deleteAllMarker();_addMarker(EVO.MapUtils.getLatLngObject(myLocation.lat,myLocation.lng),EVO.Config.kiz.icons.myLocation,null,100);if(_$kiz.hasClass('tierparks')||_$kiz.hasClass('hotspot')){_showResult();_gm.setCenter(new google.maps.LatLng(myLocation.lat,myLocation.lng));_gm.setZoom(10);if(_$kiz.hasClass('hotspot')){_gm.setZoom(11)}}else{for(i in _locationInfo){count++;EVO.MapUtils.getDistance(EVO.MapUtils.getLatLngObject(myLocation.lat,myLocation.lng),EVO.MapUtils.getLatLngObject(_locationInfo[i].lat,_locationInfo[i].lng),_.bind(function(result){respCount++;this.el.attr('data-distance',result.distance);this.el.find('.distance').text(EVO.Utils.numberFormat(result.distance,',','.',1)+' km entfernt, aktuell ca. '+result.duration);if(respCount===count){_showResult()}},_locationInfo[i]))}}}
function _sort(){_$location.sort(function(a,b){var distanceA=parseFloat($(a).attr('data-distance')),distanceB=parseFloat($(b).attr('data-distance'));return(distanceA<distanceB)?-1:(distanceA>distanceB)?1:0})}
function _showResult(){_sort();_$location.each(function(i){var $t=$(this),lng=$t.attr('data-lng'),lat=$t.attr('data-lat'),infowindow=new google.maps.InfoWindow({content:'<b>'+$t.find('h3').text()+'</b><br><p>'+$t.find('.address p').html()+'</p>'}),route;if(_$kiz.hasClass('tierparks')){_addMarker(EVO.MapUtils.getLatLngObject(lat,lng),EVO.Config.kiz.icons.tierpark,infowindow)}else if(_$kiz.hasClass('hotspot')){route=$t.find(".route a:last-child");if(route.length){route=route.clone().removeAttr("class");infowindow.setContent('<b>'+$t.find('h3').text()+'</b><br><p>'+$t.find('.address p').html()+'</p>'+route.prop('outerHTML'))}
_addMarker(EVO.MapUtils.getLatLngObject(lat,lng),EVO.Config.kiz.icons.hotspot,infowindow)}else{_addMarker(EVO.MapUtils.getLatLngObject(lat,lng),i===0?EVO.Config.kiz.icons.closestLocation:EVO.Config.kiz.icons.location,infowindow);_fitMap()}});_$kiz.find('.locations').html(_$location)}
function _addMarker(curLatLng,icon,infowindow,zIndex){if(_gm){var marker=new google.maps.Marker({position:curLatLng,map:_gm,icon:icon,zIndex:zIndex?zIndex:0});_markers.push(marker);if(infowindow){google.maps.event.addListener(marker,'click',function(){infowindow.open(_gm,marker)})}
return marker}}
function _deleteAllMarker(){var i,l;if(_gm){for(i=0,l=_markers.length;i<l;i++){google.maps.event.clearListeners(_markers[i],'click');_markers[i].setMap(null)}
_markers=[]}}
function _fitMap(){var i,l,bounds=new google.maps.LatLngBounds();if(_gm){for(i=0,l=_markers.length;i<l;i++){bounds.extend(_markers[i].getPosition())}
_gm.fitBounds(bounds)}}
function _initMap(cont){_gm=new google.maps.Map(cont,{center:new google.maps.LatLng(EVO.Config.maps.center.lat,EVO.Config.maps.center.lng),zoom:_$kiz.hasClass('tierparks')?10:15,streetViewControl:!1,mapTypeControl:!1,scrollwheel:!1,styles:EVO.Config.maps.styles});_onResize()}
function _onResize(){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(_gm){if(curMediaQueryState==='mobile'){_gm.setOptions({disableDefaultUI:!0})}else{_gm.setOptions({disableDefaultUI:!1})}}}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Datepicker=(function($){function create($el){moment.locale('de');$el.append('<div class="datepicker"></div>');$el.find('.datepicker').clndr({weekOffset:EVO.Config.calendar.weekOffset,daysOfTheWeek:EVO.Config.calendar.daysOfTheWeek,startWithMonth:moment(),clickEvents:{click:function(target){var $el=$(target.element),$wrapper=$el.closest('.input'),$input=$wrapper.find('input'),$datepicker=$wrapper.find('.datepicker'),date=moment(target.date).format('L');if($el.hasClass('inactive')){return!1}
$el.closest('.clndr-table').find('td').removeClass('selected');$el.addClass('selected');$input.val(date);$datepicker.hide();this.selectedday=target.date._i}},showAdjacentMonths:EVO.Config.calendar.showAdjacentMonths,adjacentDaysChangeMonth:EVO.Config.calendar.adjacentDaysChangeMonth,render:function(data){return _render(data,this)}})}
function _render(data,clndr){var c='',j,d,i,isSelected=!1,classes='',maxdays=parseInt($(clndr.element.context).attr('data-days-to-start'),10),maxdate,now;if(maxdays){maxdate=new Date();now=new Date();now.setDate(maxdate.getDate()-1);maxdate.setDate(maxdate.getDate()+maxdays)}
c+='<div class="clndr-controls">';c+='<div class="clndr-previous-button">&nbsp;</div>';c+='<div class="month">'+data.month+' '+data.year+'</div>';c+='<div class="clndr-next-button">&nbsp;</div>';c+='</div>';c+='<table class="clndr-table" border="0" cellspacing="0" cellpadding="0">';c+='<thead>';c+='<tr class="header-days">';for(i=0;i<data.daysOfTheWeek.length;i++){c+='<td class="header-day">';c+=data.daysOfTheWeek[i];c+='</td>'}
c+='</tr>';c+='</thead>';c+='<tbody>';for(i=0;i<data.numberOfRows;i++){c+='<tr>';for(j=0;j<7;j++){d=j+i*7;if(clndr.selectedday){if(moment(data.days[d].date._d).format('L')===moment(clndr.selectedday).format('L')){isSelected=!0}else{isSelected=!1}}else{isSelected=!1}
if(isSelected){classes+=' selected'}else{classes=''}
if(maxdays){if(maxdate>data.days[d].date._d){classes+=' inactive'}
if(data.days[d].date._d<=now){classes+=' inactive'}}
c+='<td class="'+data.days[d].classes+classes+'">';c+='<div class="day-contents">'+data.days[d].day+'</div>';c+='</td>'}
c+='</tr>'}
c+='</tbody>';c+='</table>';return c}
return{create:create}})(jQuery);var EVO=window.EVO||{};EVO.ContactPerson=(function($){var _$w,_$b,_erdgasId=5,_stromId=10,_teamIdsToHideIfPersonFound=[35],_$wrapper,_curPLZ='',_curCategory=14,_isStromU=!0,_isGasVerbrauchU=!0,_data,_$pdgas,_$pdstrom,_$ipplz,_$bbContactperson,_result,_keyupTimeoutId,_urlParams,_backendPreselect;function _init(){_$b=$(document.body);_$w=$(window);_$wrapper=_$b.find('.tx-bb-evo-contactpersons');if(_$wrapper&&_$wrapper.length){_$w.on('resize',_adjustHeight);_$wrapper.on('change','select#category',_onChangeCategory).on('change','select#strom',_onChangeStromVerbrauch).on('change','select#gas',_onChangeGasVerbrauch).on('keyup','input#plz',_onChangePLZ).on('submit','form',function(e){e.preventDefault()});_$pdgas=_$wrapper.find('.pdgas');_$pdstrom=_$wrapper.find('.pdstrom');_$ipplz=_$wrapper.find('.ipplz');_$bbContactperson=_$wrapper.find('.bb-contactperson');if(window.cp){_data=window.cp}
if(window.backendPreselect){_backendPreselect=window.backendPreselect}
_urlParams=EVO.Utils.getURLparams();if(_urlParams||_backendPreselect){_prefillFields()}
_doSearch()}}
function _adjustHeight(){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState==='tablet-p'||curMediaQueryState==='mobile'){_$bbContactperson.height("auto");return 0}
_$bbContactperson.removeClass("last");_$bbContactperson.filter(":visible:even").each(function(){var height,$nextVisible=$(this).nextAll(":visible").eq(0);$(this).height("auto");if($nextVisible.length){$nextVisible.height("auto");height=$(this).height()<=$nextVisible.height()?$nextVisible.height():$(this).height();$(this).height(height);$nextVisible.height(height)}else{$(this).addClass("last")}})}
function _prefillFields(){var plz,category,bis;if(_backendPreselect){plz=_backendPreselect.plz?_backendPreselect.plz.toString():undefined;category=parseInt(_backendPreselect.category,10);bis=category===_stromId?parseInt(_backendPreselect.verbrauchstrom,10):parseInt(_backendPreselect.verbrauchgas,10)}
if(_urlParams){if(_urlParams.kategorie){plz=_urlParams.plz;category=parseInt(_urlParams.kategorie,10);bis=parseInt(_urlParams.bis,10)}}
if(plz){$("#plz").val(plz);_curPLZ=plz}
if(category){$('select#category option[value='+category+']').prop("selected",!0);_curCategory=category}
if(_curCategory===_stromId){if(bis){$('select#strom option:eq('+bis+')').prop("selected",!0);_isStromU=!1}}else if(_curCategory===_erdgasId){if(bis){$('select#gas option:eq('+bis+')').prop("selected",!0);_isGasVerbrauchU=!1}}
_toggleCategoryExtension();_togglePlzExtension()}
function _onChangePLZ(e){var $t=$(e.currentTarget),val=$t.val();_curPLZ=val;window.clearTimeout(_keyupTimeoutId);_keyupTimeoutId=window.setTimeout(function(){_doSearch()},250)}
function _onChangeCategory(e){var $t=$(e.currentTarget),val=$t.val();_curCategory=parseInt(val,10);_toggleCategoryExtension();_doSearch();_togglePlzExtension()}
function _toggleCategoryExtension(){if(_curCategory===_stromId){_$pdstrom.velocity('slideDown',{duration:EVO.Config.contactPerson.animation.duration});_$pdgas.velocity('slideUp',{duration:EVO.Config.contactPerson.animation.duration})}else if(_curCategory===_erdgasId){_$pdgas.velocity('slideDown',{duration:EVO.Config.contactPerson.animation.duration});_$pdstrom.velocity('slideUp',{duration:EVO.Config.contactPerson.animation.duration})}else{_$pdgas.velocity('slideUp',{duration:EVO.Config.contactPerson.animation.duration});_$pdstrom.velocity('slideUp',{duration:EVO.Config.contactPerson.animation.duration})}}
function _togglePlzExtension(){var sortByCategory=_findAllByCategory(),showPlz=!1;$.each(sortByCategory,function(){if(this.plz.length>1){showPlz=!0}});if(showPlz){if(_curCategory===_stromId){if(_isStromU){showPlz=!1}}else if(_curCategory===_erdgasId){if(_isGasVerbrauchU){showPlz=!1}}}
if(showPlz){_$ipplz.velocity('slideDown',{duration:EVO.Config.contactPerson.animation.duration})}else{_$ipplz.velocity('slideUp',{duration:EVO.Config.contactPerson.animation.duration})}}
function _findAllByCategory(){var array=[];$.each(_data,function(){if($.inArray(_curCategory,this.category)>-1){array.push(this)}});return array}
function _onChangeStromVerbrauch(e){var $t=$(e.currentTarget),val=$t.val();if(val==='stromu'){_isStromU=!0}else{_isStromU=!1}
_doSearch();_togglePlzExtension()}
function _onChangeGasVerbrauch(e){var $t=$(e.currentTarget),val=$t.val();if(val==='gasu'){_isGasVerbrauchU=!0}else{_isGasVerbrauchU=!1}
_doSearch();_togglePlzExtension()}
function _searchByValue(key,value){return _result.filter(function(obj){return obj[key]===value})[0]}
function _doSearch(){_result=_.filter(_data,function(cur){var showPerson=!1;if(_categoryFilter(_curCategory,cur.category)&&_plzFilter(_curPLZ,cur.plz)){if(_curCategory!==_stromId&&_curCategory!==_erdgasId){showPerson=!0}else{if(_curCategory===_stromId){showPerson=_stromFilter(cur)}else if(_curCategory===_erdgasId){showPerson=_erdgasFilter(cur)}}}
return showPerson});if(_result.length>1){$.each(_teamIdsToHideIfPersonFound,function(){var obj=_searchByValue("uid",parseInt(this,10)),index=_result.indexOf(obj);delete _result[index]})}
_showResult()}
function _stromFilter(cur){var result=!1;if(_isStromU){if(cur.stromu===!0){result=!0}}else{if(cur.strom===!0){result=!0}}
return result}
function _erdgasFilter(cur){var result=!1;if(_isGasVerbrauchU){if(cur.gasu===!0){result=!0}}else{if(cur.gas===!0){result=!0}}
return result}
function _plzFilter(val,array){var i,l;for(i=0,l=array.length;i<l;i++){if(val.indexOf(array[i])===0){return!0}}
return!1}
function _categoryFilter(val,array){var i,l;for(i=0,l=array.length;i<l;i++){if(array[i]===val){return!0}}
return!1}
function _showResult(){var i,ids=[],$cur;for(i in _result){ids.push('#uid'+_result[i].uid)}
$cur=_$wrapper.find(ids.toString());$cur.show();_$wrapper.find('.bb-contactperson').not($cur).hide();_adjustHeight()}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Angebot=(function($){var _$b,_$toolwrapper;function _init(){_$b=$(document.body);_$toolwrapper=_$b.find('.tarifrechner');_$toolwrapper.on('click','a.getTarif',_postToWizard);_$toolwrapper.find('form').each(function(){$(this).data('action',$(this).attr('action'));$(this).data('mobileAction',$(this).attr('data-action-mobile'))})}
function _postToWizard(e){e.preventDefault();var $t=$(e.currentTarget),$wrapper=$t.closest('.product'),formName=$t.attr('data-form-name'),$targetForm=$wrapper.find('form[name="'+formName+'"]');if(EVO.MatchMediaQuery.getState()==='desktop'||EVO.MatchMediaQuery.getState()==='tablet-l'){$targetForm.attr('action',$targetForm.data('action'))}else{$targetForm.attr('action',$targetForm.data('mobileAction'))}
$targetForm.submit()}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Tooltip=(function($){var _$b;function _init(){_$b=$(document.body);_$b.find('.tooltip').on('click',function(e){e.preventDefault()});_$b.find('.tooltip').each(function(){var $t=$(this),toolTipId=$t.attr('data-tooltip'),$tooltip=$('#'+toolTipId),options;options={position:'bottom',contentAsHTML:!0,maxWidth:450,autoClose:!0,interactive:!0,trigger:'click',content:$tooltip};if($t.hasClass("info-icon"))options.maxWidth=800;$(this).tooltipster(options)})}
function update(){_$b.find('.tooltip').each(function(){var $t=$(this),toolTipId=$t.attr('data-tooltip'),$tooltip=$('#'+toolTipId);$t.tooltipster('content',$tooltip)})}
$(_init);return{init:_init,update:update}})(jQuery);var EVO=window.EVO||{};EVO.CustomerCallback=(function($){var _$b,_$form,_$successMsg,_$errorMsg,_$calltime,_timepattern=/^(\d{1,2}):(\d{2})$/;function _init(){_$b=$(document.body);_$form=_$b.find('form.customerCallback');_$successMsg=_$form.find('.successMsg');_$errorMsg=_$form.find('.errorMsg.default');_$errorMsgs=_$form.find('.errorMsg');_$calltime=_$form.find('#calltime');_$form.on('focus','input',_clearError).on('change','input[type="radio"]',_clearError).on('change','input[type="radio"]',_onDayChange).on('submit',_doSubmit);_$form.find('input[name="rueckruf"][value="now"]').click()}
function _clearError(e){_$errorMsgs.velocity('slideUp',{duration:EVO.Config.customerCallback.animation.duration})}
function _showError(id){_$form.find('.errorMsg.'+id).velocity('slideDown',{duration:EVO.Config.customerCallback.animation.duration})}
function _showErrorText(message){_$errorMsg.text(message);_showError('default')}
function _onDayChange(event){var $target=$(event.currentTarget),callbackDay=$target.val(),hours=(new Date()).getHours().toString(),minutes=(new Date()).getMinutes().toString();hours=hours.length>1?hours:'0'+hours;minutes=minutes.length>1?minutes:'0'+minutes;_$calltime.attr('disabled',callbackDay==="now");if(callbackDay==="now"){_$calltime.val(hours+":"+minutes)}}
function _getDelay(){var timeString=_$calltime.val(),result=timeString.match(_timepattern),hours,minutes,now=new Date(),targetDate,dayOffset,callbackDay=_$form.find('input[name="rueckruf"]:checked').val(),delay;if(callbackDay==="now"){return 0}else if(result===null){_showError('validTime');return!1}else{hours=parseInt(result[1],10);minutes=parseInt(result[2],10);if(hours>24||minutes>59){_showError('validTime');return!1}else{switch(callbackDay){case 'now':dayOffset=0;break;case 'today':dayOffset=0;break;case 'tomorrow':dayOffset=1;break}
targetDate=new Date(now.getFullYear(),now.getMonth(),now.getDate()+parseInt(dayOffset,10),hours,minutes,59);delay=parseInt((targetDate-now)/1000,10);if(delay<0){_showError('inPast');return!1}else{return delay}}}}
function _doSubmit(e){e.preventDefault();var $form=$(e.currentTarget),caller=$form.find('#caller').val(),delay=_getDelay(),$loading=$form.find('.loading_ajax-submit');if(delay===!1)return!1;$loading.show();$.ajax({url:EVO.Config.customerCallback.url,crossDomain:!0,data:{psec:'ac646f778ca80ea75becf2090c4f2c42',button_id:'106',caller:caller,delay:delay},success:function(e){var resp=JSON.parse(e);if(resp.data){if(!resp.data.callback_id){if(resp.data.code==209){_showError('outOfBusinessHours')}else{_showErrorText(resp.data.description)}}else{_$successMsg.velocity('slideDown',{duration:EVO.Config.customerCallback.animation.duration});$form.find('.input').velocity('slideUp',{duration:EVO.Config.customerCallback.animation.duration});_$successMsg.text(resp.data.description)}}
$loading.hide()},error:function(e){$loading.hide();_showError('notAvailable')}})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.EasyZoom=(function($){var _$b;function _init(){_initVariables();_initEvents();_initEasyZoom()}
function _initVariables(){_$b=$(document.body)}
function _initEvents(){_$b.on("click",".easyzoom-show-fallback",_openEasyZoomFallback).on("click",".easyzoom-fallback .button-close-second",_closeEasyZoomFallback)}
function _initEasyZoom(){var $easyzoom=$('.easyzoom').easyZoom({loadingNotice:'Lade Text',errorNotice:"The image could not be loaded"});var api=$easyzoom.data('easyZoom')}
function _openEasyZoomFallback(e){e.preventDefault();var id=$(e.currentTarget).data('easyzoom-id');$('#'+id).show()}
function _closeEasyZoomFallback(e){e.preventDefault();$(e.currentTarget).closest(".easyzoom-fallback").hide()}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.PromoPopup=(function($){var _promoPopup;function _init(){_promoPopup=$('.'+EVO.Config.promoPopup.popupClass);if(_promoPopup.length>=1){if(_readCookie(EVO.Config.promoPopup.cookie)===null){_createCookie(EVO.Config.promoPopup.cookie,!0,30);setTimeout(function(){_show()},1000)}}}
function _show(){$.fancybox({href:_promoPopup.find("div.trigger").data("banner"),overlayColor:'transparent',padding:0,overlayShow:!1,onComplete:function(){_setTimer()}})}
function _createCookie(name,value,minutes){var expires;if(minutes){var date=new Date();date.setTime(date.getTime()+(minutes*60*1000));expires="; expires="+date.toGMTString()}else{expires=""}
document.cookie=encodeURIComponent(name)+"="+encodeURIComponent(value)+expires+"; path=/"}
function _readCookie(name){var nameEQ=encodeURIComponent(name)+"=";var ca=document.cookie.split(';');for(var i=0;i<ca.length;i++){var c=ca[i];while(c.charAt(0)===' ')c=c.substring(1,c.length);if(c.indexOf(nameEQ)===0)return decodeURIComponent(c.substring(nameEQ.length,c.length))}
return null}
function _setTimer(){setTimeout(function(){$.fancybox.close()},6000)}
$(_init);return{init:_init}})(jQuery);var EVO=window.EVO||{};EVO.Lightbox=(function($){var _$b;function _init(){_$b=$('body');_$b.find("a.lightbox").fancybox({'transitionIn':'fade','transitionOut':'fade','speedIn':600,'speedOut':200,'overlayShow':!1})}
$(_init);return{init:_init}})(jQuery);var EVO=window.EVO||{};EVO.Login=(function($){var _$d,_$formMehrWert;function _init(){_$d=$(document);_$formMehrWert=_$d.find('.evo-mehr-wert form');$(".evo-online-service form").each(function(){$(this).validate({errorClass:'error-message-class',rules:{"usr:benutzername":{required:!0},"pwd:passwort":{required:!0}},messages:{"usr:benutzername":"Das ist ein Pflichtfeld.","pwd:passwort":"Das ist ein Pflichtfeld."}})});$(".vorteilswelt-login-wrapper form").each(function(){$(this).validate({errorClass:'error-message-class',rules:{"user":{required:!0},"pass":{required:!0}},messages:{"user":"Das ist ein Pflichtfeld.","pass":"Das ist ein Pflichtfeld."}})});$(".evo-mehr-wert form").each(function(){$(this).validate({errorClass:'error-message-class',rules:{"user":{required:!0},"pass":{required:!0}},messages:{"user":"Das ist ein Pflichtfeld.","pass":"Das ist ein Pflichtfeld."}})})}
function _login(e){var $form=$(e),username=$form.find("#user-mehrwert").val(),password=$form.find("#pw-mehrwert").val();$.ajax({url:EVO.Config.login.mehrwert.authUrl,method:"POST",data:{username:username,password:password},success:function(e){var response=JSON.parse(e);if(response.token!=="false"){window.location.href=EVO.Config.login.mehrwert.loginUrl+response.token}else{$form.find(".server-response").text(response.error_message).show()}},error:function(e){$form.find(".server-response").text(EVO.Config.login.mehrwert.notAvailableMessage).show()}});return!1}
$(_init)})(jQuery);var EVO=window.EVO||{};window.dataLayer=window.dataLayer||[];EVO.Tracking=(function($){var _$b;function _init(){_$b=$(document.body)}
function trackEvent(category,action,label,callback){callback=typeof callback!=="function"?function(){return!0}:callback;dataLayer.push({'event':'trackEvent','eventCategory':category,'eventAction':action,'eventLabel':label,'eventCallback':callback,'eventTimeout':2000})}
function trackPLZkWh(category,action,label,plz,kwh){dataLayer.push({'event':'trackPLZkWh','eventCategory':category,'eventAction':action,'eventLabel':label,'eventPLZ':plz,'eventKWH':kwh})}
function virtualPage(page){dataLayer.push({'event':'trackPageview','eventPage':page})}
$(_init);return{trackEvent:trackEvent,trackPLZkWh:trackPLZkWh,virtualPage:virtualPage}})(jQuery);var EVO=window.EVO||{};EVO.ClickToCall=(function($){var _$body,_mobileDetect,_CLASSES={_clickToCall:'click-to-call',_body:'mobile'};function _init(){_mobileDetect=new window.MobileDetect(window.navigator.userAgent);_$body=$(document.body);if(_mobileDetect.mobile()){_$body.addClass(_CLASSES._body);_$body.find('a[href^="tel"]').addClass(_CLASSES._clickToCall)}else{_$body.on('click','a[href^="tel"]',_preventClick)}}
function _preventClick(event){event.preventDefault()}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Download=(function($){var _$b,_$faq,_$resultCont,_$listCont,_$autocomplete,_data,_result,_suggestions,_highlightData,_totalEntries,_defaultIsRendered=!1,_hasResult=!0;function _init(){_$b=$(document.body);_$faq=_$b.find('.downloadCont');if(!_$faq||_$faq.length===0){return}
_$faq.hide();_$resultCont=_$faq.find('.result');_$listCont=_$faq.find('.list');_$autocomplete=_$faq.find('.autocomplete');_$b.on('click',function(){EVO.Autocomplete.hide(_$autocomplete)});_$faq.on('click','input.search',function(e){e.stopPropagation()});_$faq.on('click','.accordion.nested > dt',function(e){if($(e.currentTarget).hasClass('bbAccordion-open')){$.address.parameter('c',$(this).attr('data-category-id'))}else{$.address.parameter('c','no');$.address.parameter('q','no')}
$.address.update()});_$faq.on('click','.accordion.nested .accordion dt',function(e){if($(e.currentTarget).hasClass('bbAccordion-open')){$.address.parameter('q',$(this).attr('data-frage-id'))}else{$.address.parameter('q','no')}
$.address.update()});_$faq.on('submit','form',function(e){e.preventDefault()}).on('focus keyup afterAutocomplete','input.search',_doSearch).on('click','a.submit',function(e){e.preventDefault()});_load()}
function _load(){if(!EVO.Config.debug){var contentUid=jQuery('#contentUid').val();$.ajax({type:"POST",url:EVO.Config.faq.url,cache:!1,data:{'tx_bbdownloads_jsondownloadsfeed[controller]':'Entries','tx_bbdownloads_jsondownloadsfeed[action]':'jsonFeed','tx_bbdownloads_jsondownloadsfeed[contentUid]':contentUid||'','type':'1500020611'},success:_onSuccessLoad})}else{$.ajax({url:EVO.Config.faq.url,dataType:'json',success:_onSuccessLoad})}}
function _onSuccessLoad(d){var parameterC=$.address.parameter('c'),parameterQ=$.address.parameter('q'),lastParameterC,lastParameterQ;_data={topics:!EVO.Config.debug?$.parseJSON(d):d};_$faq.show();_renderSearchResult();triggerClickCategory(parameterC);tiggerClickQuestion(parameterQ);$('a.faqLink').address();$.address.change(function(){if(typeof e!=='function'){parameterC=$.address.parameter('c');parameterQ=$.address.parameter('q');if(lastParameterC!==parameterC||lastParameterQ!==parameterQ){if(lastParameterC!==parameterC){triggerClickCategory(parameterC)}
if(lastParameterQ!==parameterQ){tiggerClickQuestion(parameterQ)}}
lastParameterC=parameterC;lastParameterQ=parameterQ}})}
function triggerClickCategory(parameterC){var $curCategory=_$faq.find('dt[data-category-id="'+parameterC+'"]');if($curCategory&&$curCategory.length){$curCategory.addClass('bbAccordion-open');$curCategory.next().show()}}
function tiggerClickQuestion(parameterQ){var $curQuestion=_$faq.find('dt[data-frage-id="'+parameterQ+'"]');if($curQuestion&&$curQuestion.length){$curQuestion.addClass('bbAccordion-open');$curQuestion.next().show()}}
function _doSearch(e){var $t=$(e.currentTarget),searchTxt=$t.val();_onSearching(searchTxt)}
function _buildmarkup(d){var i,l,cur,curCategory,j,ll,dl,dlc,c='';_totalEntries=0;c+='<dl class="accordion nested clear">';for(i=0,l=d.topics.length;i<l;i++){cur=d.topics[i];if(cur.categories.length){_totalEntries+=cur.categories.length;c+=' <dt data-category-id="'+cur.id+'">'+cur.menu+' ('+cur.categories.length+')</dt>';c+='<dd><div class="inner">';if(cur.categories.length){c+='<dl class="accordion">';for(j=0,ll=cur.categories.length;j<ll;j++){curCategory=cur.categories[j];c+='<dt data-frage-id="'+curCategory.id+'">'+curCategory.category+'</dt>';c+='<dd><div class="inner">';c+=curCategory.intro;if(curCategory.downloads.length){for(dl=0,dlc=curCategory.downloads.length;dl<dlc;dl++){var iconClass;switch(curCategory.downloads[dl].ext){case 'pdf':case 'PDF':iconClass='button-icon-pdf';break;case 'doc':case 'DOC':case 'docx':case 'DOCX':case 'ods':case 'ODS':iconClass='button-icon-doc';break;default:iconClass='button-arrow-left'}
c+='<p><a href="'+curCategory.downloads[dl].path+'" target="_blank" class="'+iconClass+'">'+curCategory.downloads[dl].title+'</a></p>'}}
c+='</div></dd>'}
c+='</dl>'}
c+='</div></dd>'}}
c+='</dl>';return c}
function _render(){_$resultCont.html(_buildmarkup(_data));_$resultCont.find('.accordion').bbAccordion({'selectorHead':'dt','selectorContent':'dd',singleOpened:!1});_defaultIsRendered=!0}
function _renderSearchResult(searchTxt){if(searchTxt&&(searchTxt.length>=EVO.Config.faq.searchMinChar)){_hasResult=!0;_$resultCont.html(_buildmarkup(_highlightData));_$resultCont.find('.accordion').bbAccordion({'selectorHead':'dt','selectorContent':'dd',singleOpened:!1});_defaultIsRendered=!1}else{if(_hasResult){_render();_hasResult=!1}}
_renderAutoComplete(searchTxt);_$faq.find('.resultCount').text(_totalEntries)}
function _renderAutoComplete(searchTxt){if(_suggestions&&_suggestions.length&&searchTxt.length>=EVO.Config.faq.searchMinChar){EVO.Autocomplete.show(_$autocomplete,_suggestions)}else{EVO.Autocomplete.hide(_$autocomplete)}}
function _onSearching(searchTxt){if(searchTxt.length>=EVO.Config.faq.searchMinChar){_result=EVO.DownloadSearchEngine.findQuestions(searchTxt,_data);_result=JSON.parse(JSON.stringify(_result));_highlightData=EVO.DownloadSearchEngine.highlightEntries(searchTxt,_result);_suggestions=EVO.DownloadSearchEngine.findSuggestions(searchTxt,_data);_suggestions=_suggestions.filter(EVO.DownloadSearchEngine.uniqueFilter);_suggestions.sort();_renderSearchResult(searchTxt)}else if(!_defaultIsRendered){_render();_$faq.find('.resultCount').text(_totalEntries)}}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.DownloadSearchEngine=(function($){function findQuestions(searchText,data){var result={};var result2={topics:[]},i=-1,lastcategory;var searchTokens=searchText.split(' ');var searchExpressions=_buildSearchExpressions(searchTokens);data.topics.forEach(function(topic){topic.categories.forEach(function(entry){var hit=_scanEntry(searchExpressions,entry);if(hit){hit.topic=topic.menu;if(!result[topic.menu]){result[topic.menu]=[]}
if(lastcategory!==topic.menu){i++;result2.topics[i]={menu:topic.menu,id:topic.id,categories:[]}}
result2.topics[i].categories.push(hit);lastcategory=topic.menu;result[topic.menu].push(hit)}})});return result2}
function findSuggestions(searchText,data){var suggestions=[];var regExp;var searchToken=searchText.trim();if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
regExp=new RegExp(searchToken+"[-/\\wäöüÄÖÜß]*\\b(?![^<]*>)","gi");var categoryMatches,introMatches,downloadMatches;data.topics.forEach(function(topic){topic.categories.forEach(function(entry){categoryMatches=entry.category.match(regExp);introMatches=entry.intro.match(regExp);if(categoryMatches!==null){categoryMatches=categoryMatches.map(function(s){return s.trim()});suggestions=suggestions.concat(categoryMatches)}
if(introMatches!==null){introMatches=introMatches.map(function(s){return s.trim()});suggestions=suggestions.concat(introMatches)}
entry.downloads.forEach(function(download){downloadMatches=download.title.match(regExp);if(downloadMatches!==null){downloadMatches=downloadMatches.map(function(s){return s.trim()});suggestions=suggestions.concat(downloadMatches)}})})});return suggestions}
function _scanEntry(searchExpressions,entry){var match=!0;var i=0;var searchExpression=searchExpressions[i];var searchLength=searchExpressions.length;var k,dl;while(match&&i<searchLength){match=searchExpression.test(entry.category)||searchExpression.test(entry.intro);if(match===!1){for(k=0,dl=entry.downloads.length;k<dl;k++){match=searchExpression.test(entry.downloads[k].title);if(match){break}}}
i+=1;searchExpression=searchExpressions[i]}
return match?entry:!1}
function highlightEntries(searchText,entries){var searchTokens=searchText.split(' '),entry,i,l,j,k,ll,dl,curCategory,curIntro,curDownload,highlightExpression=_buildHighlightExpression(searchTokens),spanString='<span class="'+EVO.Config.faq.highlightClass+'">';for(i=0,l=entries.topics.length;i<l;i++){for(j=0,ll=entries.topics[i].categories.length;j<ll;j++){curCategory=entries.topics[i].categories[j].category;curIntro=entries.topics[i].categories[j].intro;for(k=0,dl=entries.topics[i].categories[j].downloads.length;k<dl;k++){curDownload=entries.topics[i].categories[j].downloads[k].title;entries.topics[i].categories[j].downloads[k].title=curDownload.replace(highlightExpression,spanString+'$&</span>').replace(new RegExp(EVO.Utils.escapeRegExp(spanString+' '),'g'),' '+spanString)}
entries.topics[i].categories[j].category=curCategory.replace(highlightExpression,spanString+'$&</span>').replace(new RegExp(EVO.Utils.escapeRegExp(spanString+' '),'g'),' '+spanString);entries.topics[i].categories[j].intro=curIntro.replace(highlightExpression,spanString+'$&</span>').replace(new RegExp(EVO.Utils.escapeRegExp(spanString+' '),'g'),' '+spanString)}}
return entries}
function _buildSearchExpressions(searchTokens){var searchExpressions=[],searchToken;if(searchTokens[searchTokens.length-1]===''){searchTokens.pop()}
for(var i=0,l=searchTokens.length;i<l-1;i=i+1){searchToken=searchTokens[i];if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
searchExpressions.push(new RegExp("("+searchToken+"\\b)(?![^<]*>)","gi"))}
searchToken=searchTokens[i];if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
searchExpressions.push(new RegExp("("+searchToken+")(?![^<]*>)","gi"));return searchExpressions}
function _buildHighlightExpression(searchTokens){var highlightExpressionStr="",searchToken;if(searchTokens[searchTokens.length-1]===''){searchTokens.pop()}
for(var i=0,l=searchTokens.length;i<l-1;i=i+1){searchToken=searchTokens[i];if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
highlightExpressionStr+="("+searchToken+"\\b)(?![^<]*>)|"}
searchToken=searchTokens[i];if(searchToken&&searchToken.match(/^[äöüÄÖÜ]/)){searchToken="(^|\\s)"+searchToken}else{searchToken="\\b"+searchToken}
highlightExpressionStr+="("+searchToken+")(?![^<]*>)";return new RegExp(highlightExpressionStr,"gi")}
function uniqueFilter(value,index,self){return self.indexOf(value)===index}
return{findQuestions:findQuestions,findSuggestions:findSuggestions,highlightEntries:highlightEntries,uniqueFilter:uniqueFilter}})(jQuery);var EVO=window.EVO||{};EVO.ServerMethods=(function($){var _urlParams,_fails={checkParameterRequest:2};function _init(){_urlParams=EVO.Utils.getURLparamsObject();if(_urlParams){_triggerCheckParameterRequest()}}
function _triggerCheckParameterRequest(){var data=$.extend({},_urlParams,{'tx_bbenergytariffcalculator_tariffcalculator[controller]':'Tariff','tx_bbenergytariffcalculator_tariffcalculator[action]':'checkParameterRequest','type':'1509982972'});$.ajax({type:"POST",url:'parametercheck-ajax/',cache:!1,dataType:"json",data:data}).fail(function(){_fails.checkParameterRequest-=1;if(_fails.checkParameterRequest!==0){window.setTimeout(function(){_triggerCheckParameterRequest()},2000)}})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Landingpage=(function($){var _$b,_$params;function _init(){_$b=$(document.body);_$params=EVO.Utils.getURLparamsObject();if(_$b.hasClass("evo-lp-dyn-content")){_appendDynTextElement()}
if(_$b.find(".dyn-param-content").length){_showParamContent()}}
function _appendDynTextElement(){_.each(_$params,function(value,key){if(value){key=key.replace(/[^\w\s]/gi,'');_$b.find(".dyn-content-"+key).text(value)}});_$b.find(".dyn-content").show()}
function _showParamContent(){_.each(_$params,function(value,key){if(value){key=key.replace(/[^\w\s]/gi,'');var $paramContent=_$b.find(".dyn-param-content-"+key);if($paramContent.length&&$paramContent.filter("."+value).length){$paramContent.filter(".dyn-param-content-default").hide();$paramContent.filter("."+value).show()}}})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Popup=(function($){var configExist=!0,showPopupOnThisPage=!0,cookies={showOnNextSessionPopup:!1,showPopup:!1,showLaterPopup:!1,completedPopup:!1},defaultConfig={href:"",type:"iframe",padding:0,overlayColor:'transparent',fitToView:!1,autoDimensions:!0,speedIn:0,speedOut:0,changeSpeed:0,transitionIn:"none",transitionOut:"none",hideOnOverlayClick:!1,centerOnScroll:!0,width:588,onStart:function(){$("#fancybox-wrap").addClass("hidden")},onComplete:function(){$('#fancybox-frame').load(function(){$("#fancybox-outer").addClass("blue-border");if($(this).contents().find(".popup-link").length){$(this).contents().find('body').addClass("iframe-body");$(this).contents().find('main.popup').addClass("image-iframe");EVO.Utils.resizeFancyboxIFrame();EVO.Tracking.trackEvent("Popup","Image","Open");$(this).contents().find(".popup-link").on("click",function(e){e.preventDefault();_setCookie(EVO.Config.popup.cookies.completedPopup,!0,365);var targetUrl=e.currentTarget.href,target=e.currentTarget.target;if(window.google_tag_manager){EVO.Tracking.trackEvent("Popup","Image","Click",function(){if(target){window.open(targetUrl,target)}else{window.location=targetUrl}})}else{if(target){window.open(targetUrl,target)}else{window.location=targetUrl}}})}else if($(this).contents().find('.Tx-Formhandler form').length){var formID=$(this).contents().find('.Tx-Formhandler form').attr("id");$(this).contents().find('main.popup').addClass(formID);EVO.Utils.resizeFancyboxIFrame(0,30)}
setTimeout(function(){$("#fancybox-wrap").removeClass("hidden")},500)})},onClosed:function(){if(!$.cookie(EVO.Config.popup.cookies.completedPopup,{useLocalStorage:!1})){_setCookie(EVO.Config.popup.cookies.showLaterPopup,!0,3)}}};function _init(){_initEvents();_extendConfig();if(configExist){_checkForOtherPopups();_checkCookies();_evaluateCookies()}}
function _initEvents(){$(document).on("resizeFancyboxIFrame",EVO.Utils.resizeFancyboxIFrame);var formID=$("main.popup .Tx-Formhandler form").attr("id");if(formID){$(document).on("submitAjaxFormCallback",_onSubmitCallback)}}
function _extendConfig(){if(EVO.PopupConfig){defaultConfig=$.extend(!0,defaultConfig,EVO.PopupConfig);if(EVO.PopupConfig.showPopupOnThisPage===!1){showPopupOnThisPage=!1}}else{configExist=!1}}
function _checkForOtherPopups(){var _promoPopup=$('.'+EVO.Config.promoPopup.popupClass);if(_promoPopup.length>=1){showPopupOnThisPage=!1}}
function _onSubmitCallback(e){if(e.customData.form){if(!$(e.customData.form).find(".row.error").length){_setCookie(EVO.Config.popup.cookies.completedPopup,!0,365);$('main.popup').addClass("success")}}
parent.$("body").trigger('resizeFancyboxIFrame')}
function _evaluateCookies(){if(cookies.showLaterPopup!==!0&&cookies.completedPopup!==!0){if(cookies.showPopup!==!0&&cookies.showOnNextSessionPopup!==!0){var date=new Date(),minutes=720;date.setTime(date.getTime()+(minutes*60*1000));_setCookie(EVO.Config.popup.cookies.showOnNextSessionPopup,!0,date);_setCookie(EVO.Config.popup.cookies.showPopup,!0,100)}else if(cookies.showPopup&&cookies.showOnNextSessionPopup!==!0){if(showPopupOnThisPage){_showPopup()}}}}
function _checkCookies(){cookies.showOnNextSessionPopup=$.cookie(EVO.Config.popup.cookies.showOnNextSessionPopup,{useLocalStorage:!1})==="true"?!0:!1;cookies.showPopup=$.cookie(EVO.Config.popup.cookies.showPopup,{useLocalStorage:!1})==="true"?!0:!1;cookies.showLaterPopup=$.cookie(EVO.Config.popup.cookies.showLaterPopup,{useLocalStorage:!1})==="true"?!0:!1;cookies.completedPopup=$.cookie(EVO.Config.popup.cookies.completedPopup,{useLocalStorage:!1})==="true"?!0:!1}
function _setCookie(cookieName,value,expires){$.cookie(cookieName,value,{useLocalStorage:!1,expires:expires,path:"/"});_checkCookies()}
function _showPopup(){$.fancybox(defaultConfig)}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.WarningStrip=(function($){var _$b,_config,_closeClicked;function _init(){_$b=$(document.body);_config=$.extend(!0,EVO.Config.warningStrip,window.WarningStrip||{});_initEvents();_closeClicked=$.cookie(_config.cookie.cookieName,{useLocalStorage:!1});if(!_closeClicked&&_config.show){_appendWarningStrip()}}
function _initEvents(){_$b.on("click",".warning-strip a.button-close-warning-strip",_closeWarning)}
function _appendWarningStrip(){_$b.find("> main").prepend('<div class="warning-strip">'+_config.message+'<a href="#" class="button-close-warning-strip">Schließen</a></div>')}
function _closeWarning(e){e.preventDefault();var $t=$(e.currentTarget),_$warningStrip=$t.closest('.warning-strip');$.cookie(_config.cookie.cookieName,!0,{useLocalStorage:!1,expires:_config.cookie.cookieExpires,path:"/"});_$warningStrip.velocity('slideUp',{duration:_config.animation.duration,complete:function(){}})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.CertificateSlider=(function(){var _$body,_$window,_$slider,_slider;function _init(){_$body=$(document.body);_$window=$(window);_$slider=_$body.find('.certificate-footer');if(_$slider&&_$slider.length){_$window.on('resize',_onResize);_buildSlider()}}
function _onResize(){if(_slider){_update();_slider.flexslider(0)}}
function _update(){_$slider.data('flexslider').vars.maxItems=getGridSize();_$slider.data('flexslider').update()}
function getGridSize(){if(window.innerWidth<480){return 1}else if(window.innerWidth<759){return 2}else{return 100}}
function _buildSlider(){_slider=_$slider.flexslider({animation:"slide",animationLoop:!1,slideshow:!1,itemWidth:217,itemMargin:0,controlNav:!1,nextText:' ',prevText:' ',maxItems:getGridSize()});window.setTimeout(function(){_$slider.data('flexslider').update();_update()},0)}
$(window).load(_init)})(jQuery);function decryptCharcode(n,start,end,offset){n=n+offset;if(offset>0&&n>end){n=start+(n-end-1)}else if(offset<0&&n<start){n=end-(start-n-1)}
return String.fromCharCode(n)}
function decryptString(enc,offset){var dec="";var len=enc.length;for(var i=0;i<len;i++){var n=enc.charCodeAt(i);if(n>=0x2B&&n<=0x3A){dec+=decryptCharcode(n,0x2B,0x3A,offset)}else if(n>=0x40&&n<=0x5A){dec+=decryptCharcode(n,0x40,0x5A,offset)}else if(n>=0x61&&n<=0x7A){dec+=decryptCharcode(n,0x61,0x7A,offset)}else{dec+=enc.charAt(i)}}
return dec}
function linkTo_UnCryptMailto(s){location.href=decryptString(s,3)}
var EVO=window.EVO||{};EVO.TrustedShop=(function($){var _$b,_$w,_$trusted,_$footer;function _init(){_$w=$(window);_$b=$(document.body);_$footer=_$b.find('footer');_$trusted=_$b.find('#tsbadge4_db8d3657bdbe440c985ae127463eaad4');_$w.on('scroll resize',_onWindowScrollResize);_onWindowScrollResize();_$b.on('click',_onBodyClick);_$b.on('click','#tsbadge4_db8d3657bdbe440c985ae127463eaad4',_onClick)}
function _onClick(event){event.stopPropagation();if(_$trusted.length)_$trusted.addClass('onTop')}
function _onBodyClick(){if(_$trusted.length)_$trusted.removeClass('onTop')}
function _onWindowScrollResize(){var curMediaQueryState=EVO.MatchMediaQuery.getState();if(curMediaQueryState==='tablet-p'||curMediaQueryState==='tablet-l'||curMediaQueryState==='desktop'){_toggleTrustedShop()}}
function _toggleTrustedShop(){_$trusted=_$b.find('#tsbadge4_db8d3657bdbe440c985ae127463eaad4');if(_$trusted.length===0)return;var tsHeight=_$trusted.outerHeight();if(_$footer.offset().left+_$footer.width()<=_$trusted.offset().left){_$trusted.css("opacity","1")}else{if(_$footer.offset().top<=_$trusted.offset().top+tsHeight){_$trusted.css("opacity","0")}else{_$trusted.css("opacity","1")}}}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.ToolFernwaerme_v1=(function($){var _$b,_$toolwrapper,_$toolInput,_$result,_$verbrauchInput,_$anschlusswertInput,_$verbrauch,_$anschlusswert,_$calcResult=[];function _init(){_$b=$(document.body);_$toolwrapper=_$b.find('.tool-fernwaerme_v1');_$toolInput=_$toolwrapper.find(".tool-input");_$result=_$toolwrapper.find(".result");_$verbrauchInput=_$toolwrapper.find("input#verbrauch");_$anschlusswertInput=_$toolwrapper.find("input#anschlusswert");_$toolwrapper.on('click','.button.submit',_calcAndShowResult).on('click','a.back',_backToInput);_$verbrauchInput.bbFormat(EVO.Config.tools.fernwaerme_v1.inputFormatVerbrauchspreis);_$anschlusswertInput.bbFormat(EVO.Config.tools.fernwaerme_v1.inputFormatGrundpreis)}
function _calcAndShowResult(e){e.preventDefault();_$verbrauch=_$verbrauchInput.bbFormat();_$anschlusswert=_$anschlusswertInput.bbFormat();var entgeltEmissionen=parseInt(_$verbrauch,10)*EVO.Config.tools.fernwaerme_v1.entgeltEmissionen.preis.netto._0,messungUndAbrechnung;$.each(EVO.Config.tools.fernwaerme_v1.messungUndAbrechnung.preis.netto,function(key,val){messungUndAbrechnung=val;if(_$anschlusswert&&(_$anschlusswert-parseInt(key.substring(1),10)<=0)){return!1}});_$calcResult.tarife={};$.each(EVO.Config.tools.fernwaerme_v1.tarife,function(key,val){var verbrauchspreisNetto=_calc(val.preis.verbrauchspreis.netto,_$verbrauch),grundpreisNetto=_calc(val.preis.grundpreis.netto,_$anschlusswert);_$calcResult.tarife[key]={"name":val.name,"verbrauchspreis":{"netto":verbrauchspreisNetto,"brutto":_nettoToBrutto(verbrauchspreisNetto)},"grundpreis":{"netto":grundpreisNetto,"brutto":_nettoToBrutto(grundpreisNetto)},"messungUndAbrechnung":{"netto":messungUndAbrechnung,"brutto":_nettoToBrutto(messungUndAbrechnung)},"entgeltEmissionen":{"netto":entgeltEmissionen,"brutto":_nettoToBrutto(entgeltEmissionen)},"gesamtsumme":{"netto":verbrauchspreisNetto+grundpreisNetto+messungUndAbrechnung+entgeltEmissionen,"brutto":_nettoToBrutto(verbrauchspreisNetto+grundpreisNetto+messungUndAbrechnung+entgeltEmissionen)}}});_findCheapest();_showResult();_toggleContent()}
function _findCheapest(){var keyList=[];for(var key in _$calcResult.tarife){keyList.push(key)}
keyList.sort(function(a,b){a=_$calcResult.tarife[a].gesamtsumme.netto;b=_$calcResult.tarife[b].gesamtsumme.netto;if(a<b){return-1}
if(a>b){return 1}
return 0});_$calcResult.rang=keyList}
function _nettoToBrutto(netto){return netto*EVO.Config.tools.ust}
function _showResult(){var alwaysCompareWith=EVO.Config.tools.fernwaerme_v1.alwaysCompareWith,t1,t2,messungUndAbrechnungText;_$result.find(".input-data .verbrauch span").text(_$verbrauchInput.val());_$result.find(".input-data .anschlusswert span").text(_$anschlusswertInput.val());$.each(EVO.Config.tools.fernwaerme_v1.tarife,function(key,val){if(val.maxAnschlusswert<_$anschlusswertInput.bbFormat()&&val.maxAnschlusswert!==0){var index=_$calcResult.rang.indexOf(key);_$calcResult.rang.splice(index,1)}});$.each(EVO.Config.tools.fernwaerme_v1.messungUndAbrechnung.range,function(key,val){messungUndAbrechnungText=val;if(_$anschlusswertInput.bbFormat()<=parseInt(key.substring(1),10)){return!1}});t1=_$calcResult.rang[1];t2=alwaysCompareWith;if(_$calcResult.rang[0]!==alwaysCompareWith){t1=_$calcResult.rang[0];t2=alwaysCompareWith}
_$toolwrapper.find(".tarif .tarif-1 span").html(_$calcResult.tarife[t1].name);_$toolwrapper.find(".tarif .tarif-2 span").html(_$calcResult.tarife[t2].name);_$toolwrapper.find(".data-grundpreis .netto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].grundpreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-grundpreis .netto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].grundpreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-grundpreis .brutto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].grundpreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-grundpreis .brutto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].grundpreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-verbrauchspreis .netto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].verbrauchspreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-verbrauchspreis .netto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].verbrauchspreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-verbrauchspreis .brutto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].verbrauchspreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-verbrauchspreis .brutto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].verbrauchspreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-messung .netto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].messungUndAbrechnung.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-messung .netto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].messungUndAbrechnung.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-messung .brutto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].messungUndAbrechnung.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-messung .brutto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].messungUndAbrechnung.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-messung td:first-child").html(messungUndAbrechnungText);_$toolwrapper.find(".data-emission .netto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].entgeltEmissionen.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-emission .netto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].entgeltEmissionen.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-emission .brutto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].entgeltEmissionen.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-emission .brutto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].entgeltEmissionen.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-gesammt-netto .netto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].gesamtsumme.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-gesammt-netto .netto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].gesamtsumme.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-gesammt-brutto .brutto-1").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].gesamtsumme.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".data-gesammt-brutto .brutto-2").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].gesamtsumme.brutto,',','.',2)+"&nbsp;EUR")}
function _calc(obj,val){var ret=0,length=Object.keys(obj).length-1,loop=!0,diff=0;for(var i=0;i<=length;i++){if(loop){var key=Object.keys(obj)[i],interval=parseInt(key.substring(1),10),value=obj[key],quotient=length===i||interval===0?0:val/interval;loop=quotient<=1?!1:!0;if(loop){ret+=(interval-diff)*value}else{ret+=(val-diff)*value}
diff=interval}}
return ret}
function _backToInput(e){e.preventDefault();_toggleContent()}
function _toggleContent(){var isOpen=_$toolInput.is(":visible");_$toolInput.velocity(isOpen?"slideUp":"slideDown",{duration:300});_$result.velocity(isOpen?"slideDown":"slideUp",{duration:300})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.ToolFernwaerme_v2=(function($){var _$b,_$toolwrapper,_$toolInput,_$result,_$tarifSelect,_$verbrauchInput,_$anschlusswertInput,_$tarif,_$verbrauch,_$anschlusswert,_$errorMessageHolder,_$calcResult=[];function _init(){_$b=$(document.body);_$toolwrapper=_$b.find('.tool-fernwaerme_v2');_$toolInput=_$toolwrapper.find(".tool-input");_$result=_$toolwrapper.find(".result");_$tarifSelect=_$toolwrapper.find("select#tarif");_$verbrauchInput=_$toolwrapper.find("input#verbrauch");_$anschlusswertInput=_$toolwrapper.find("input#anschlusswert");_$errorMessageHolder=_$toolwrapper.find(".error-message-holder");_$toolwrapper.on('click','.button.submit',errorHandling).on('click','a.back',_backToInput);_$toolInput.find("input, select").on("focus",_hideErrorMessage);_$toolwrapper.on("click",".preis-garantie .button",function(){_$toolwrapper.find(".jetzt-sichern").velocity('scroll')});_prefillTarif();_$verbrauchInput.bbFormat(EVO.Config.tools.fernwaerme_v2.inputFormatVerbrauchspreis);_$anschlusswertInput.bbFormat(EVO.Config.tools.fernwaerme_v2.inputFormatGrundpreis)}
function errorHandling(e){e.preventDefault();var error=!1;if(_$tarifSelect.val()===""){error=!0;_$errorMessageHolder.html(EVO.Config.tools.fernwaerme_v2.error.tarifauswaehlen)}
if(_$tarifSelect.val()===EVO.Config.tools.fernwaerme_v2.tarife.komfort.key){if(_$anschlusswertInput.bbFormat()>EVO.Config.tools.fernwaerme_v2.tarife.komfort.maxAnschlusswert){error=!0;_$errorMessageHolder.html(EVO.Config.tools.fernwaerme_v2.error.komfort.maxAnschlusswert)}}
if(error){_showErrorMessage()}else{_hideErrorMessage();_calcAndShowResult()}}
function _showErrorMessage(){_$errorMessageHolder.velocity("slideDown",{duration:300});_$tarifSelect.addClass("error-element-class")}
function _hideErrorMessage(){_$errorMessageHolder.velocity("slideUp",{duration:300});_$toolInput.find("input, select").removeClass("error-element-class")}
function _prefillTarif(){$.each(EVO.Config.tools.fernwaerme_v2.tarife,function(key,val){_$tarifSelect.append('<option value='+val.key+'>'+val.name+'</option>')})}
function _calcAndShowResult(){_$tarif=_$tarifSelect.val();_$verbrauch=_$verbrauchInput.bbFormat();_$anschlusswert=_$anschlusswertInput.bbFormat();var entgeltEmissionen=parseInt(_$verbrauch,10)*EVO.Config.tools.fernwaerme_v2.entgeltEmissionen.preis.netto._0,entgeltEmissionenNeu=parseInt(_$verbrauch,10)*EVO.Config.tools.fernwaerme_v2.entgeltEmissionen.preis.neu.netto._0,messungUndAbrechnung,messungUndAbrechnungNeu;$.each(EVO.Config.tools.fernwaerme_v2.messungUndAbrechnung.preis.netto,function(key,val){messungUndAbrechnung=val;if(_$anschlusswert&&(_$anschlusswert-parseInt(key.substring(1),10)<=0)){return!1}});$.each(EVO.Config.tools.fernwaerme_v2.messungUndAbrechnung.preis.neu.netto,function(key,val){messungUndAbrechnungNeu=val;if(_$anschlusswert&&(_$anschlusswert-parseInt(key.substring(1),10)<=0)){return!1}});_$calcResult.tarife={};$.each(EVO.Config.tools.fernwaerme_v2.tarife,function(key,val){var verbrauchspreisNetto=_calc(val.preis.verbrauchspreis.netto,_$verbrauch),verbrauchspreisNettoNeu=_calc(val.preis.verbrauchspreis.neu.netto,_$verbrauch),grundpreisNetto=_calc(val.preis.grundpreis.netto,_$anschlusswert),grundpreisNettoNeu=_calc(val.preis.grundpreis.neu.netto,_$anschlusswert);_$calcResult.tarife[key]={"name":val.name,"verbrauchspreis":{"netto":verbrauchspreisNetto,"brutto":_nettoToBrutto(verbrauchspreisNetto),"neu":{"netto":verbrauchspreisNettoNeu,"brutto":_nettoToBrutto(verbrauchspreisNettoNeu)}},"grundpreis":{"netto":grundpreisNetto,"brutto":_nettoToBrutto(grundpreisNetto),"neu":{"netto":grundpreisNettoNeu,"brutto":_nettoToBrutto(grundpreisNettoNeu)}},"messungUndAbrechnung":{"netto":messungUndAbrechnung,"brutto":_nettoToBrutto(messungUndAbrechnung),"neu":{"netto":messungUndAbrechnungNeu,"brutto":_nettoToBrutto(messungUndAbrechnungNeu)}},"entgeltEmissionen":{"netto":entgeltEmissionen,"brutto":_nettoToBrutto(entgeltEmissionen),"neu":{"netto":entgeltEmissionenNeu,"brutto":_nettoToBrutto(entgeltEmissionenNeu)}},"gesamtsumme":{"netto":verbrauchspreisNetto+grundpreisNetto+messungUndAbrechnung+entgeltEmissionen,"brutto":_nettoToBrutto(verbrauchspreisNetto+grundpreisNetto+messungUndAbrechnung+entgeltEmissionen),"neu":{"netto":verbrauchspreisNettoNeu+grundpreisNettoNeu+messungUndAbrechnungNeu+entgeltEmissionenNeu,"brutto":_nettoToBrutto(verbrauchspreisNettoNeu+grundpreisNettoNeu+messungUndAbrechnungNeu+entgeltEmissionenNeu)}}}});_findCheapest();_showResult();_toggleContent()}
function _findCheapest(){var keyList=[],keyListNeu=[];for(var key in _$calcResult.tarife){keyList.push(key);keyListNeu.push(key)}
keyList.sort(function(a,b){a=_$calcResult.tarife[a].gesamtsumme.netto;b=_$calcResult.tarife[b].gesamtsumme.netto;if(a<b){return-1}
if(a>b){return 1}
return 0});keyListNeu.sort(function(a,b){a=_$calcResult.tarife[a].gesamtsumme.neu.netto;b=_$calcResult.tarife[b].gesamtsumme.neu.netto;if(a<b){return-1}
if(a>b){return 1}
return 0});_$calcResult.rang=keyList;_$calcResult.rang.neu=keyListNeu}
function _nettoToBrutto(netto){return netto*EVO.Config.tools.ust}
function _showResult(){var t1=_$tarif,t2=_$tarif,messungUndAbrechnungText;_$result.find(".tarif-name").html(EVO.Config.tools.fernwaerme_v2.tarife[t1].name);_$result.find(".input-data .verbrauch span").text(_$verbrauchInput.val());_$result.find(".input-data .anschlusswert span").text(_$anschlusswertInput.val());if(_$tarif===EVO.Config.tools.fernwaerme_v2.tarife.komfort.key){if(_$calcResult.rang.neu.indexOf(EVO.Config.tools.fernwaerme_v2.tarife.komfort.key)>_$calcResult.rang.neu.indexOf(EVO.Config.tools.fernwaerme_v2.tarife.direkt.key)){t1=t2=EVO.Config.tools.fernwaerme_v2.tarife.direkt.key;_$result.find(".bestpreis, .note-bestpreis").show()}}
$.each(EVO.Config.tools.fernwaerme_v2.messungUndAbrechnung.range,function(key,val){messungUndAbrechnungText=val;if(_$anschlusswertInput.bbFormat()<=parseInt(key.substring(1),10)){return!1}});_$toolwrapper.find(".jahresgrundpreis .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].grundpreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresgrundpreis .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].grundpreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresgrundpreis .ab .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].grundpreis.neu.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresgrundpreis .ab .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t2].grundpreis.neu.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresverbrauchspreis .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].verbrauchspreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresverbrauchspreis .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].verbrauchspreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresverbrauchspreis .ab .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].verbrauchspreis.neu.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresverbrauchspreis .ab .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t2].verbrauchspreis.neu.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".messung-und-abrechnung .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].messungUndAbrechnung.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".messung-und-abrechnung .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].messungUndAbrechnung.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".messung-und-abrechnung .ab .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].messungUndAbrechnung.neu.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".messung-und-abrechnung .ab .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t2].messungUndAbrechnung.neu.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".messung-und-abrechnung .messung-und-abrechnung-bis-ab").html(messungUndAbrechnungText);_$toolwrapper.find(".jahresentgelt-emissionen .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].entgeltEmissionen.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresentgelt-emissionen .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].entgeltEmissionen.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresentgelt-emissionen .ab .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].entgeltEmissionen.neu.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresentgelt-emissionen .ab .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t2].entgeltEmissionen.neu.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".gesamtpreis .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].gesamtsumme.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".gesamtpreis .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].gesamtsumme.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".gesamtpreis .ab .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t2].gesamtsumme.neu.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".gesamtpreis .ab .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t2].gesamtsumme.neu.netto,',','.',2)+"&nbsp;EUR")}
function _calc(obj,val){var ret=0,length=Object.keys(obj).length-1,loop=!0,diff=0;for(var i=0;i<=length;i++){if(loop){var key=Object.keys(obj)[i],interval=parseInt(key.substring(1),10),value=obj[key],quotient=length===i||interval===0?0:val/interval;loop=quotient<=1?!1:!0;if(loop){ret+=(interval-diff)*value}else{ret+=(val-diff)*value}
diff=interval}}
return ret}
function _backToInput(e){e.preventDefault();_$result.find(".bestpreis, .note-bestpreis").hide();_toggleContent()}
function _toggleContent(){var isOpen=_$toolInput.is(":visible");_$toolInput.velocity(isOpen?"slideUp":"slideDown",{duration:300});_$result.velocity(isOpen?"slideDown":"slideUp",{duration:300})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.ToolFernwaerme_v2=(function($){var _$b,_$toolwrapper,_$toolInput,_$result,_$tarifSelect,_$verbrauchInput,_$anschlusswertInput,_$tarif,_$verbrauch,_$anschlusswert,_$errorMessageHolder,_$calcResult=[];function _init(){_$b=$(document.body);_$toolwrapper=_$b.find('.tool-fernwaerme_v3');_$toolInput=_$toolwrapper.find(".tool-input");_$result=_$toolwrapper.find(".result");_$tarifSelect=_$toolwrapper.find("select#tarif");_$verbrauchInput=_$toolwrapper.find("input#verbrauch");_$anschlusswertInput=_$toolwrapper.find("input#anschlusswert");_$errorMessageHolder=_$toolwrapper.find(".error-message-holder");_$toolwrapper.on('click','.button.submit',errorHandling).on('click','a.back',_backToInput);_$toolInput.find("input, select").on("focus",_hideErrorMessage);_$toolwrapper.on("click",".preis-garantie .button",function(){_$toolwrapper.find(".jetzt-sichern").velocity('scroll')});_prefillTarif();_$verbrauchInput.bbFormat(EVO.Config.tools.fernwaerme_v3.inputFormatVerbrauchspreis);_$anschlusswertInput.bbFormat(EVO.Config.tools.fernwaerme_v3.inputFormatGrundpreis)}
function errorHandling(e){e.preventDefault();var error=!1;if(_$tarifSelect.val()===""){error=!0;_$errorMessageHolder.html(EVO.Config.tools.fernwaerme_v3.error.tarifauswaehlen)}
if(_$tarifSelect.val()===EVO.Config.tools.fernwaerme_v3.tarife.komfort.key){if(_$anschlusswertInput.bbFormat()>EVO.Config.tools.fernwaerme_v3.tarife.komfort.maxAnschlusswert){error=!0;_$errorMessageHolder.html(EVO.Config.tools.fernwaerme_v3.error.komfort.maxAnschlusswert)}}
if(_$tarifSelect.val()===EVO.Config.tools.fernwaerme_v3.tarife.komfort2021.key){if(_$anschlusswertInput.bbFormat()>EVO.Config.tools.fernwaerme_v3.tarife.komfort2021.maxAnschlusswert){error=!0;_$errorMessageHolder.html(EVO.Config.tools.fernwaerme_v3.error.komfort2021.maxAnschlusswert)}}
if(error){_showErrorMessage()}else{_hideErrorMessage();_calcAndShowResult()}}
function _showErrorMessage(){_$errorMessageHolder.velocity("slideDown",{duration:300});_$tarifSelect.addClass("error-element-class")}
function _hideErrorMessage(){_$errorMessageHolder.velocity("slideUp",{duration:300});_$toolInput.find("input, select").removeClass("error-element-class")}
function _prefillTarif(){$.each(EVO.Config.tools.fernwaerme_v3.tarife,function(key,val){_$tarifSelect.append('<option value='+val.key+'>'+val.name+'</option>')})}
function _calcAndShowResult(){_$tarif=_$tarifSelect.val();_$verbrauch=_$verbrauchInput.bbFormat();_$anschlusswert=_$anschlusswertInput.bbFormat();var entgeltEmissionen=parseInt(_$verbrauch,10)*EVO.Config.tools.fernwaerme_v3.entgeltEmissionen.preis.netto._0,messungUndAbrechnung;$.each(EVO.Config.tools.fernwaerme_v3.messungUndAbrechnung.preis.netto,function(key,val){messungUndAbrechnung=val;if(_$anschlusswert&&(_$anschlusswert-parseInt(key.substring(1),10)<=0)){return!1}});_$calcResult.tarife={};$.each(EVO.Config.tools.fernwaerme_v3.tarife,function(key,val){var verbrauchspreisNetto=_calc(val.preis.verbrauchspreis.netto,_$verbrauch),grundpreisNetto=_calc(val.preis.grundpreis.netto,_$anschlusswert);_$calcResult.tarife[key]={"name":val.name,"verbrauchspreis":{"netto":verbrauchspreisNetto,"brutto":_nettoToBrutto(verbrauchspreisNetto)},"grundpreis":{"netto":grundpreisNetto,"brutto":_nettoToBrutto(grundpreisNetto)},"messungUndAbrechnung":{"netto":messungUndAbrechnung,"brutto":_nettoToBrutto(messungUndAbrechnung)},"entgeltEmissionen":{"netto":entgeltEmissionen,"brutto":_nettoToBrutto(entgeltEmissionen)},"gesamtsumme":{"netto":verbrauchspreisNetto+grundpreisNetto+messungUndAbrechnung+entgeltEmissionen,"brutto":_nettoToBrutto(verbrauchspreisNetto+grundpreisNetto+messungUndAbrechnung+entgeltEmissionen)}}});_findCheapest();_showResult();_toggleContent()}
function _findCheapest(){var keyList=[];for(var key in _$calcResult.tarife){keyList.push(key)}
keyList.sort(function(a,b){a=_$calcResult.tarife[a].gesamtsumme.netto;b=_$calcResult.tarife[b].gesamtsumme.netto;if(a<b){return-1}
if(a>b){return 1}
return 0});_$calcResult.rang=keyList}
function _nettoToBrutto(netto){return netto*EVO.Config.tools.ust}
function _showResult(){var t1=_$tarif,t2=_$tarif,messungUndAbrechnungText;_$result.find(".tarif-name").html(EVO.Config.tools.fernwaerme_v3.tarife[t1].name);_$result.find(".input-data .verbrauch span").text(_$verbrauchInput.val());_$result.find(".input-data .anschlusswert span").text(_$anschlusswertInput.val());_$toolwrapper.find(".tarif-vertrag").hide().filter(".tarif-vertrag-"+t1).show();if(_$tarif===EVO.Config.tools.fernwaerme_v3.tarife.komfort.key){if(_$calcResult.rang.indexOf(EVO.Config.tools.fernwaerme_v3.tarife.komfort.key)>_$calcResult.rang.indexOf(EVO.Config.tools.fernwaerme_v3.tarife.direkt.key)){t1=t2=EVO.Config.tools.fernwaerme_v3.tarife.direkt.key;_$result.find(".bestpreis, .note-bestpreis").show()}}
$.each(EVO.Config.tools.fernwaerme_v3.messungUndAbrechnung.range,function(key,val){messungUndAbrechnungText=val;if(_$anschlusswertInput.bbFormat()<=parseInt(key.substring(1),10)){return!1}});_$toolwrapper.find(".jahresgrundpreis .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].grundpreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresgrundpreis .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].grundpreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresverbrauchspreis .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].verbrauchspreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresverbrauchspreis .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].verbrauchspreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".messung-und-abrechnung .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].messungUndAbrechnung.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".messung-und-abrechnung .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].messungUndAbrechnung.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".messung-und-abrechnung .messung-und-abrechnung-bis-ab").html(messungUndAbrechnungText);_$toolwrapper.find(".jahresentgelt-emissionen .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].entgeltEmissionen.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".jahresentgelt-emissionen .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].entgeltEmissionen.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".gesamtpreis .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarife[t1].gesamtsumme.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".gesamtpreis .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarife[t1].gesamtsumme.netto,',','.',2)+"&nbsp;EUR")}
function _calc(obj,val){var ret=0,length=Object.keys(obj).length-1,loop=!0,diff=0;for(var i=0;i<=length;i++){if(loop){var key=Object.keys(obj)[i],interval=parseInt(key.substring(1),10),value=obj[key],quotient=length===i||interval===0?0:val/interval;loop=quotient<=1?!1:!0;if(loop){ret+=(interval-diff)*value}else{ret+=(val-diff)*value}
diff=interval}}
return ret}
function _backToInput(e){e.preventDefault();_$result.find(".bestpreis, .note-bestpreis").hide();_toggleContent()}
function _toggleContent(){var isOpen=_$toolInput.is(":visible");_$toolInput.velocity(isOpen?"slideUp":"slideDown",{duration:300});_$result.velocity(isOpen?"slideDown":"slideUp",{duration:300})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.ToolStromheizung=(function($){var _$b,_$toolwrapper,_$toolInput,_$result,_$htKwhInput,_$ntKwhInput,_$plzInput,_$htKwh,_$ntKwh,_$plz,_$errorMessageHolder,_$calcResult=[];function _init(){_$b=$(document.body);_$toolwrapper=_$b.find('.tool-stromheizung');_$toolInput=_$toolwrapper.find(".tool-input");_$result=_$toolwrapper.find(".result");_$htKwhInput=_$toolwrapper.find("input#ht-kwh");_$ntKwhInput=_$toolwrapper.find("input#nt-kwh");_$plzInput=_$toolwrapper.find("input#ihre-plz");_$errorMessageHolder=_$toolwrapper.find(".error-message-holder");_$toolwrapper.on('click','.button.submit',errorHandling).on('click','a.back',_backToInput);_$toolInput.find("input").on("focus",_hideErrorMessage);_$htKwhInput.bbFormat(EVO.Config.tools.stromheizung.inputFormatHTkWh);_$ntKwhInput.bbFormat(EVO.Config.tools.stromheizung.inputFormatNTkWh)}
function errorHandling(e){e.preventDefault();var error=!1;if(_$plzInput.val()===""){_$errorMessageHolder.html(EVO.Config.tools.stromheizung.error.plzEmpty);error=!0}else if(EVO.Config.tools.stromheizung.plz.indexOf(_$plzInput.val())<0){_$errorMessageHolder.html(EVO.Config.tools.stromheizung.error.plz);error=!0}
if(error){_showErrorMessage()}else{_hideErrorMessage();_calcAndShowResult()}}
function _showErrorMessage(){_$errorMessageHolder.velocity("slideDown",{duration:300});_$plzInput.addClass("error-element-class")}
function _hideErrorMessage(){_$errorMessageHolder.velocity("slideUp",{duration:300});_$toolInput.find("input").removeClass("error-element-class")}
function _calcAndShowResult(){_$htKwh=_$htKwhInput.bbFormat();_$ntKwh=_$ntKwhInput.bbFormat();_$plz=_$plzInput.val();var verbrauchspreisHT=_calc(EVO.Config.tools.stromheizung.preis.verbrauchspreis.ht.netto,_$htKwh),verbrauchspreisNT=_calc(EVO.Config.tools.stromheizung.preis.verbrauchspreis.nt.netto,_$ntKwh),grundpreis=EVO.Config.tools.stromheizung.preis.grundpreis.netto;_$calcResult.tarif={"verbrauchspreisHT":{"netto":verbrauchspreisHT,"brutto":_nettoToBrutto(verbrauchspreisHT)},"verbrauchspreisNT":{"netto":verbrauchspreisNT,"brutto":_nettoToBrutto(verbrauchspreisNT)},"grundpreis":{"netto":grundpreis,"brutto":_nettoToBrutto(grundpreis)},"gesamtsumme":{"netto":verbrauchspreisHT+verbrauchspreisNT+grundpreis,"brutto":_nettoToBrutto(verbrauchspreisHT+verbrauchspreisNT+grundpreis)}};_showResult();_toggleContent()}
function _nettoToBrutto(netto){return netto*EVO.Config.tools.ust}
function _showResult(){_$result.find(".input-data .ht-kwh span").text(_$htKwhInput.val());_$result.find(".input-data .nt-kwh span").text(_$ntKwhInput.val());_$result.find(".input-data .ihre-plz span").text(_$plzInput.val());_$toolwrapper.find(".preis-ht .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarif.verbrauchspreisHT.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".preis-ht .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarif.verbrauchspreisHT.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".preis-nt .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarif.verbrauchspreisNT.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".preis-nt .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarif.verbrauchspreisNT.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".grundpreis .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarif.grundpreis.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".grundpreis .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarif.grundpreis.netto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".gesamtpreis .bis .preis-brutto").html(EVO.Utils.numberFormat(_$calcResult.tarif.gesamtsumme.brutto,',','.',2)+"&nbsp;EUR");_$toolwrapper.find(".gesamtpreis .bis .preis-netto").html("Netto:&nbsp;"+EVO.Utils.numberFormat(_$calcResult.tarif.gesamtsumme.netto,',','.',2)+"&nbsp;EUR")}
function _calc(price,val){return price*val}
function _backToInput(e){e.preventDefault();_toggleContent()}
function _toggleContent(){var isOpen=_$toolInput.is(":visible");_$toolInput.velocity(isOpen?"slideUp":"slideDown",{duration:300});_$result.velocity(isOpen?"slideDown":"slideUp",{duration:300})}
$(_init)})(jQuery);var EVO=window.EVO||{};EVO.Vorteilswelt=(function(){var _$b;function _init(){_$b=$(document.body);_$b.on('click','.vorteilswelt-login-button',_openVorteilsweltFancybox)}
function _openVorteilsweltFancybox(event){event.preventDefault();$.fancybox({href:'#fancy-vorteilswelt-login',type:'inline',padding:0,margin:0,centerOnScroll:!0,autoScale:!0,autoDimensions:!1,onComplete:function(){var $fancyWrap=$('#fancybox-wrap'),$fancyContent=$('#fancybox-content');$fancyContent.addClass('vorteilswelt');$fancyWrap.css({'width':'auto','max-width':'700px'});$fancyContent.css({'border-width':'4px','width':'auto','height':'auto'});$fancyContent.find('> div').css({'width':'auto','max-width':'100%','height':'auto'});$.fancybox.center()}})}
$(_init);return{}})();var EVO=window.EVO||{};EVO.Appointment=(function(){var _$b;function _init(){_$b=$(document.body);_$b.on('change','#beratungstermin #termin',function(event){event.preventDefault();_setTimeSlots($(event.currentTarget))});$('#beratungstermin #termin option:selected').change()}
function _setTimeSlots(target){var timeData=JSON.parse($('#timeSlots').html()),currentAppointment=target.val(),timeSelect=$(_$b).find('#uhrzeit');if(timeData.appointments[currentAppointment]){$(timeSelect).find('option').remove().end().append('<option value="0">'+timeData.defaultOption+'</option>').val(0);$.each(timeData.appointments[currentAppointment].timeSlots,function(i,item){var options='<option '+(item.deactivated?'disabled':'')+' value="'+item.uid+'" '+(item.selected?'selected':'')+'>'+item.time+'</option>';$(timeSelect).append(options)})}else{$(timeSelect).find('option').remove().end().append('<option value="0">'+timeData.defaultTimeOptionEmpty+'</option>').val(0)}}
$(_init);return{}})();var EVO=window.EVO||{};EVO.CodeOverlay=(function(){var _$b,_codes,_showCodeOverlay=!0;function _init(){_checkCookies();if($('#code-overlay').length){if(_showCodeOverlay){_getAllCodes();$(document).on('ready',_openCodeOverlay);_$b=$(document.body);_$b.on('click','#code-submit',_compareCodes)}}}
function _openCodeOverlay(event){$.fancybox({href:'#code-overlay',type:'inline',padding:0,margin:0,enableEscapeButton:!1,showCloseButton:!1,hideOnContentClick:!1,hideOnOverlayClick:!1,centerOnScroll:!0,autoScale:!0,autoDimensions:!1,onComplete:function(){var $fancyWrap=$('#fancybox-wrap'),$fancyContent=$('#fancybox-content');$fancyContent.addClass('code-overlay-fancybox');$fancyWrap.css({'width':'auto','max-width':'550px'});$fancyContent.css({'border-width':'4px','width':'auto','height':'auto'});$fancyContent.find('> div').css({'width':'auto','max-width':'100%','height':'auto'});$.fancybox.center()}})}
function _getAllCodes(){$.ajax({url:EVO.Config.codeOverlay.codesUrl+EVO.Config.codeOverlay.name+'.txt',dataType:"text"}).done(function(data){_codes=data.split('\n')})}
function _compareCodes(event){event.preventDefault();var $form=$(event.currentTarget).closest('form');var codeValue=$form.find('#code').val();var codeValid=!1;if(_codes){_codes.forEach(function(code){if(code.trim()===codeValue){codeValid=!0}})}
if(codeValid){$.fancybox.close();_setCookie(EVO.Config.codeOverlay.cookies.show+EVO.Config.codeOverlay.name,!1)}else{var validator=$form.validate();validator.showErrors({"code":"Der Code ist nicht gültig."})}}
function _checkCookies(){_showCodeOverlay=sessionStorage.getItem(EVO.Config.codeOverlay.cookies.show+EVO.Config.codeOverlay.name)===null?!0:!1}
function _setCookie(cookieName,value){sessionStorage.setItem(cookieName,value);_checkCookies()}
$(_init);return{}})()