PageSourceSearch

https://buenosairespoetry.com/_static/??-eJyVkN0OgjAMRl/I0cwQfy6M1…yaMj0XY509Yjqc077PYLBfe+abPtb6e9LGu+w96XZ/r

js buenosairespoetry.com collected 2026-10-02 07:04:57 UTC 311,162 bytes, 6,298 lines download raw bytes

1/* global wpcom_reblog */
2
3var jetpackLikesWidgetBatch = [];
4var jetpackLikesMasterReady = false;
5
6// Due to performance problems on pages with a large number of widget iframes that need to be loaded,
7// we are limiting the processing at any instant to unloaded widgets that are currently in viewport,
8// plus this constant that will allow processing of widgets above and bellow the current fold.
9// This aim of it is to improve the UX and hide the transition from unloaded to loaded state from users.
10var jetpackLikesLookAhead = 2000; // pixels
11
12// Keeps track of loaded comment likes widget so we can unload them when they are scrolled out of view.
13var jetpackCommentLikesLoadedWidgets = [];
14
15var jetpackLikesDocReadyPromise = new Promise( resolve => {
16	if ( document.readyState !== 'loading' ) {
17		resolve();
18	} else {
19		window.addEventListener( 'DOMContentLoaded', () => resolve() );
20	}
21} );
22
23function JetpackLikesPostMessage( message, target ) {
24	if ( typeof message === 'string' ) {
25		try {
26			message = JSON.parse( message );
27		} catch ( e ) {
28			return;
29		}
30	}
31
32	if ( target && typeof target.postMessage === 'function' ) {
33		try {
34			target.postMessage(
35				JSON.stringify( {
36					type: 'likesMessage',
37					data: message,
38				} ),
39				'*'
40			);
41		} catch ( e ) {
42			return;
43		}
44	}
45}
46
47function JetpackLikesBatchHandler() {
48	const requests = [];
49	document.querySelectorAll( 'div.jetpack-likes-widget-unloaded' ).forEach( widget => {
50		if ( jetpackLikesWidgetBatch.indexOf( widget.id ) > -1 ) {
51			return;
52		}
53
54		if ( ! jetpackIsScrolledIntoView( widget ) ) {
55			return;
56		}
57
58		jetpackLikesWidgetBatch.push( widget.id );
59
60		var regex = /like-(post|comment)-wrapper-(\d+)-(\d+)-(\w+)/,
61			match = regex.exec( widget.id ),
62			info;
63
64		if ( ! match || match.length !== 5 ) {
65			return;
66		}
67
68		info = {
69			blog_id: match[ 2 ],
70			width: widget.width,
71		};
72
73		if ( 'post' === match[ 1 ] ) {
74			info.post_id = match[ 3 ];
75		} else if ( 'comment' === match[ 1 ] ) {
76			info.comment_id = match[ 3 ];
77		}
78
79		info.obj_id = match[ 4 ];
80
81		requests.push( info );
82	} );
83
84	if ( requests.length > 0 ) {
85		JetpackLikesPostMessage(
86			{ event: 'initialBatch', requests: requests },
87			window.frames[ 'likes-master' ]
88		);
89	}
90}
91
92function JetpackLikesMessageListener( event ) {
93	let message = event && event.data;
94	if ( typeof message === 'string' ) {
95		try {
96			message = JSON.parse( message );
97		} catch ( err ) {
98			return;
99		}
100	}
101
102	const type = message && message.type;
103	const data = message && message.data;
104
105	if ( type !== 'likesMessage' || typeof data.event === 'undefined' ) {
106		return;
107	}
108
109	// We only allow messages from one origin
110	const allowedOrigin = 'https://widgets.wp.com';
111	if ( allowedOrigin !== event.origin ) {
112		return;
113	}
114
115	switch ( data.event ) {
116		case 'masterReady':
117			jetpackLikesDocReadyPromise.then( () => {
118				jetpackLikesMasterReady = true;
119
120				const stylesData = {
121					event: 'injectStyles',
122				};
123				const sdTextColor = document.querySelector( '.sd-text-color' );
124				const sdLinkColor = document.querySelector( '.sd-link-color' );
125				const sdTextColorStyles = ( sdTextColor && getComputedStyle( sdTextColor ) ) || {};
126				const sdLinkColorStyles = ( sdLinkColor && getComputedStyle( sdLinkColor ) ) || {};
127
128				// enable reblogs if they are enabled for the page
129				if ( document.body.classList.contains( 'jetpack-reblog-enabled' ) ) {
130					JetpackLikesPostMessage( { event: 'reblogsEnabled' }, window.frames[ 'likes-master' ] );
131				}
132
133				stylesData.textStyles = {
134					color: sdTextColorStyles[ 'color' ],
135					fontFamily: sdTextColorStyles[ 'font-family' ],
136					fontSize: sdTextColorStyles[ 'font-size' ],
137					direction: sdTextColorStyles[ 'direction' ],
138					fontWeight: sdTextColorStyles[ 'font-weight' ],
139					fontStyle: sdTextColorStyles[ 'font-style' ],
140					textDecoration: sdTextColorStyles[ 'text-decoration' ],
141				};
142
143				stylesData.linkStyles = {
144					color: sdLinkColorStyles[ 'color' ],
145					fontFamily: sdLinkColorStyles[ 'font-family' ],
146					fontSize: sdLinkColorStyles[ 'font-size' ],
147					textDecoration: sdLinkColorStyles[ 'text-decoration' ],
148					fontWeight: sdLinkColorStyles[ 'font-weight' ],
149					fontStyle: sdLinkColorStyles[ 'font-style' ],
150				};
151
152				JetpackLikesPostMessage( stylesData, window.frames[ 'likes-master' ] );
153
154				JetpackLikesBatchHandler();
155			} );
156
157			break;
158
159		// We're keeping this for planned future follow ups.
160		// @see: https://github.com/Automattic/jetpack/pull/42361#discussion_r1995338815
161		case 'showLikeWidget':
162			break;
163
164		// We're keeping this for planned future follow ups.
165		// @see: https://github.com/Automattic/jetpack/pull/42361#discussion_r1995338815
166		case 'showCommentLikeWidget':
167			break;
168
169		case 'killCommentLikes':
170			// If kill switch for comment likes is enabled remove all widgets wrappers and `Loading...` placeholders.
171			document
172				.querySelectorAll( '.jetpack-comment-likes-widget-wrapper' )
173				.forEach( wrapper => wrapper.remove() );
174			break;
175
176		case 'clickReblogFlair':
177			if ( wpcom_reblog && typeof wpcom_reblog.toggle_reblog_box_flair === 'function' ) {
178				wpcom_reblog.toggle_reblog_box_flair( data.obj_id, data.post_id );
179			}
180			break;
181
182		case 'hideOtherGravatars': {
183			hideLikersPopover();
184			break;
185		}
186
187		case 'showOtherGravatars': {
188			const container = document.querySelector( '#likes-other-gravatars' );
189
190			if ( ! container ) {
191				break;
192			}
193
194			const list = container.querySelector( 'ul' );
195
196			container.style.display = 'none';
197			list.innerHTML = '';
198
199			container
200				.querySelectorAll( '.likes-text span' )
201				.forEach( item => ( item.textContent = data.totalLikesLabel ) );
202
203			( data.likers || [] ).forEach( async ( liker, index ) => {
204				if ( liker.profile_URL.substr( 0, 4 ) !== 'http' ) {
205					// We only display gravatars with http or https schema
206					return;
207				}
208
209				const element = document.createElement( 'li' );
210				list.append( element );
211
212				element.innerHTML = `
213				<a href="${ encodeURI( liker.profile_URL ) }" rel="nofollow" target="_parent" class="wpl-liker">
214					<img src="${ encodeURI( liker.avatar_URL ) }"
215						alt=""
216						style="width: 28px; height: 28px;" />
217					<span></span>
218				</a>
219				`;
220
221
222				// Add some extra attributes through native methods, to ensure strings are sanitized.
223				element.classList.add( liker.css_class );
224				element.querySelector( 'img' ).alt = data.avatarAltTitle.replace( '%s', liker.name );
225				element.querySelector( 'span' ).innerText = liker.name;
226
227				if ( index === data.likers.length - 1 ) {
228					element.addEventListener( 'keydown', ( e ) => {
229						if ( e.key === 'Tab' && ! e.shiftKey ) {
230							e.preventDefault();
231							hideLikersPopover();
232
233							JetpackLikesPostMessage(
234								{ event: 'focusLikesCount', parent: data.parent },
235								window.frames[ 'likes-master' ]
236							);
237						}
238					} );
239				}
240			} );
241
242			const positionPopup = function() {
243				const containerStyle = getComputedStyle(container);
244				const isRtl = containerStyle.direction === 'rtl';
245
246				const el = document.querySelector( `*[name='${ data.parent }']` );
247				const rect = el.getBoundingClientRect();
248				const win = el.ownerDocument.defaultView;
249
250				const offset = {
251					top: rect.top + win.pageYOffset,
252					left: rect.left + win.pageXOffset,
253				};
254
255				// don't display yet or we get skewed window.innerWidth later
256				container.style.display = 'none';
257
258				let containerLeft = 0;
259				container.style.top = offset.top + data.position.top - 1 + 'px';
260
261				if ( isRtl ) {
262					const visibleAvatarsCount = data && data.likers ? Math.min( data.likers.length, 5 ) : 0;
263					// 24px is the width of the avatar + 4px is the padding between avatars
264					containerLeft = offset.left + data.position.left + 24 * visibleAvatarsCount + 4;
265					container.style.transform = 'translateX(-100%)';
266				} else {
267					containerLeft = offset.left + data.position.left;
268				}
269				container.style.left = containerLeft + 'px';
270
271				// Container width - padding
272				const initContainerWidth = data.width - 20;
273				const rowLength = Math.floor( initContainerWidth / 37 );
274				// # of rows + (avatar + avatar padding) + text above + container padding
275				let height = Math.ceil( data.likers.length / rowLength ) * 37 + 17 + 22;
276				if ( height > 204 ) {
277					height = 204;
278				}
279
280				// If the popup is overflows viewport width, we should show it on the next line
281				// Push it offscreen to calculated rendered width
282				const windowWidth = win.innerWidth;
283				container.style.left = '-9999px';
284				container.style.display = 'block';
285
286				// If the popup exceeds the viewport width,
287				// flip the position of the popup.
288				const containerWidth = container.offsetWidth;
289				const containerRight = containerLeft + containerWidth;
290
291				if ( containerRight > windowWidth && ! isRtl) {
292					containerLeft = rect.left + rect.width - containerWidth;
293				} else if ( containerLeft - containerWidth < 0 && isRtl ) {
294					container.style.transform = 'none';
295					containerLeft = rect.left;
296				}
297				// Set the container left
298				container.style.left = containerLeft + 'px';
299
300				container.setAttribute( 'aria-hidden', 'false' );
301			}
302
303			positionPopup();
304			container.focus();
305
306			const debounce = function( func, wait ) {
307				var timeout;
308				return function() {
309					var context = this;
310					var args = arguments;
311					clearTimeout( timeout );
312					timeout = setTimeout( function() {
313						func.apply( context, args );
314					}, wait );
315				};
316			};
317
318			const debouncedPositionPopup = debounce( positionPopup, 100 );
319
320			// Keep a reference of this function in the element itself
321			// so that we can destroy it later
322			container.__resizeHandler = debouncedPositionPopup;
323
324			// When window is resized, resize the popup.
325			window.addEventListener( "resize", debouncedPositionPopup );
326		}
327	}
328}
329
330window.addEventListener( 'message', JetpackLikesMessageListener );
331
332function hideLikersPopover() {
333	const container = document.querySelector( '#likes-other-gravatars' );
334
335	if ( container ) {
336		container.style.display = 'none';
337		container.setAttribute( 'aria-hidden', 'true' );
338
339		// Remove the resize event listener and cleanup.
340		const resizeHandler = container.__resizeHandler;
341		if ( resizeHandler ) {
342			window.removeEventListener( "resize", resizeHandler );
343			delete container.__resizeHandler;
344		}
345	}
346}
347
348document.addEventListener( 'click', hideLikersPopover );
349
350function JetpackLikesWidgetQueueHandler() {
351	var wrapperID;
352
353	if ( ! jetpackLikesMasterReady ) {
354		setTimeout( JetpackLikesWidgetQueueHandler, 500 );
355		return;
356	}
357
358	// Restore widgets to initial unloaded state when they are scrolled out of view.
359	jetpackUnloadScrolledOutWidgets();
360
361	var unloadedWidgetsInView = jetpackGetUnloadedWidgetsInView();
362
363	if ( unloadedWidgetsInView.length > 0 ) {
364		// Grab any unloaded widgets for a batch request
365		JetpackLikesBatchHandler();
366	}
367
368	for ( var i = 0, length = unloadedWidgetsInView.length; i <= length - 1; i++ ) {
369		wrapperID = unloadedWidgetsInView[ i ].id;
370
371		if ( ! wrapperID ) {
372			continue;
373		}
374
375		jetpackLoadLikeWidgetIframe( wrapperID );
376	}
377}
378
379function jetpackLoadLikeWidgetIframe( wrapperID ) {
380	if ( typeof wrapperID === 'undefined' ) {
381		return;
382	}
383
384	const wrapper = document.querySelector( '#' + wrapperID );
385	wrapper.querySelectorAll( 'iframe' ).forEach( iFrame => iFrame.remove() );
386
387	const placeholder = wrapper.querySelector( '.likes-widget-placeholder' );
388
389	// Post like iframe
390	if ( placeholder && placeholder.classList.contains( 'post-likes-widget-placeholder' ) ) {
391		const postLikesFrame = document.createElement( 'iframe' );
392
393		postLikesFrame.classList.add( 'post-likes-widget', 'jetpack-likes-widget' );
394		postLikesFrame.name = wrapper.dataset.name;
395		postLikesFrame.src = wrapper.dataset.src;
396		postLikesFrame.height = '55px';
397		postLikesFrame.width = '100%';
398		postLikesFrame.frameBorder = '0';
399		postLikesFrame.scrolling = 'no';
400		postLikesFrame.title = wrapper.dataset.title;
401
402		placeholder.after( postLikesFrame );
403	}
404
405	// Comment like iframe
406	if ( placeholder.classList.contains( 'comment-likes-widget-placeholder' ) ) {
407		const commentLikesFrame = document.createElement( 'iframe' );
408
409		commentLikesFrame.class = 'comment-likes-widget-frame jetpack-likes-widget-frame';
410		commentLikesFrame.name = wrapper.dataset.name;
411		commentLikesFrame.src = wrapper.dataset.src;
412		commentLikesFrame.height = '18px';
413		commentLikesFrame.width = '100%';
414		commentLikesFrame.frameBorder = '0';
415		commentLikesFrame.scrolling = 'no';
416
417		wrapper.querySelector( '.comment-like-feedback' ).after( commentLikesFrame );
418
419		jetpackCommentLikesLoadedWidgets.push( commentLikesFrame );
420	}
421
422	wrapper.classList.remove( 'jetpack-likes-widget-unloaded' );
423	wrapper.classList.add( 'jetpack-likes-widget-loading' );
424
425	wrapper.querySelector( 'iframe' ).addEventListener( 'load', e => {
426		JetpackLikesPostMessage(
427			{ event: 'loadLikeWidget', name: e.target.name, width: e.target.width },
428			window.frames[ 'likes-master' ]
429		);
430
431		wrapper.classList.remove( 'jetpack-likes-widget-loading' );
432		wrapper.classList.add( 'jetpack-likes-widget-loaded' );
433	} );
434}
435
436function jetpackGetUnloadedWidgetsInView() {
437	const unloadedWidgets = document.querySelectorAll( 'div.jetpack-likes-widget-unloaded' );
438
439	return [ ...unloadedWidgets ].filter( item => jetpackIsScrolledIntoView( item ) );
440}
441
442function jetpackIsScrolledIntoView( element ) {
443	const top = element.getBoundingClientRect().top;
444	const bottom = element.getBoundingClientRect().bottom;
445
446	// Allow some slack above and bellow the fold with jetpackLikesLookAhead,
447	// with the aim of hiding the transition from unloaded to loaded widget from users.
448	return top + jetpackLikesLookAhead >= 0 && bottom <= window.innerHeight + jetpackLikesLookAhead;
449}
450
451function jetpackUnloadScrolledOutWidgets() {
452	for ( let i = jetpackCommentLikesLoadedWidgets.length - 1; i >= 0; i-- ) {
453		const currentWidgetIframe = jetpackCommentLikesLoadedWidgets[ i ];
454
455		if ( ! jetpackIsScrolledIntoView( currentWidgetIframe ) ) {
456			const widgetWrapper =
457				currentWidgetIframe &&
458				currentWidgetIframe.parentElement &&
459				currentWidgetIframe.parentElement.parentElement;
460
461			// Restore parent class to 'unloaded' so this widget can be picked up by queue manager again if needed.
462			widgetWrapper.classList.remove( 'jetpack-likes-widget-loaded' );
463			widgetWrapper.classList.remove( 'jetpack-likes-widget-loading' );
464			widgetWrapper.classList.add( 'jetpack-likes-widget-unloaded' );
465
466			// Bring back the loading placeholder into view.
467			widgetWrapper
468				.querySelectorAll( '.comment-likes-widget-placeholder' )
469				.forEach( item => ( item.style.display = 'block' ) );
470
471			// Remove it from the list of loaded widgets.
472			jetpackCommentLikesLoadedWidgets.splice( i, 1 );
473
474			// Remove comment like widget iFrame.
475			currentWidgetIframe.remove();
476		}
477	}
478}
479
480var jetpackWidgetsDelayedExec = function ( after, fn ) {
481	var timer;
482	return function () {
483		clearTimeout( timer );
484		timer = setTimeout( fn, after );
485	};
486};
487
488var jetpackOnScrollStopped = jetpackWidgetsDelayedExec( 250, JetpackLikesWidgetQueueHandler );
489
490// Load initial batch of widgets, prior to any scrolling events.
491JetpackLikesWidgetQueueHandler();
492
493// Add event listener to execute queue handler after scroll.
494window.addEventListener( 'scroll', jetpackOnScrollStopped, true );
495;
496!function(e){var o={};function n(t){if(o[t])return o[t].exports;var r=o[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=o,n.d=function(e,o,t){n.o(e,o)||Object.defineProperty(e,o,{enumerable:!0,get:t})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,o){if(1&o&&(e=n(e)),8&o)return e;if(4&o&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(n.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&o&&"string"!=typeof e)for(var r in e)n.d(t,r,function(o){return e[o]}.bind(null,r));return t},n.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(o,"a",o),o},n.o=function(e,o){return Object.prototype.hasOwnProperty.call(e,o)},n.p="",n(n.s=273)}({273:function(e,o){!function(){"use strict";let e,o;function n(e){return new Promise((o,n)=>{const t=document.createElement("script");t.onload=()=>o(),t.onerror=e=>n(e),t.src=e,document.body.appendChild(t)})}function t(){if(e)return e;const o=window.wpcom_coblocks_js;return e=n(o.coblocks_lightbox_js),e}function r(){if(o)return o;window.wpcomJQueryUsageLoggerDisabled=!0;const e=window.wpcom_coblocks_js,t=window.jQuery?Promise.resolve():n(e.jquery_core_js).then(()=>n(e.jquery_migrate_js)),r=t.then(()=>window.imagesLoaded?Promise.resolve():n(e.imagesloaded_js)),c=t.then(()=>window.Masonry?Promise.resolve():n(e.masonry_js)),u=Promise.all([t,r,c]).then(()=>n(e.coblocks_masonry_js));return o=u,o}function c(){document.querySelector(".wp-block-coblocks-gallery-masonry")&&r(),document.querySelector(".has-lightbox")&&t(),document.body.classList.contains("block-editor-page")&&(r(),t())}"loading"!==document.readyState?c():document.addEventListener("DOMContentLoaded",c)}()}});;
497/*! This file is auto-generated */
498/*!
499 * imagesLoaded PACKAGED v5.0.0
500 * JavaScript is all like "You images are done yet or what?"
501 * MIT License
502 */
503!function(t,e){"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,(function(){function t(){}let e=t.prototype;return e.on=function(t,e){if(!t||!e)return this;let i=this._events=this._events||{},s=i[t]=i[t]||[];return s.includes(e)||s.push(e),this},e.once=function(t,e){if(!t||!e)return this;this.on(t,e);let i=this._onceEvents=this._onceEvents||{};return(i[t]=i[t]||{})[e]=!0,this},e.off=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;let s=i.indexOf(e);return-1!=s&&i.splice(s,1),this},e.emitEvent=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;i=i.slice(0),e=e||[];let s=this._onceEvents&&this._onceEvents[t];for(let n of i){s&&s[n]&&(this.off(t,n),delete s[n]),n.apply(this,e)}return this},e.allOff=function(){return delete this._events,delete this._onceEvents,this},t})),
504/*!
505 * imagesLoaded v5.0.0
506 * JavaScript is all like "You images are done yet or what?"
507 * MIT License
508 */
509function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}("undefined"!=typeof window?window:this,(function(t,e){let i=t.jQuery,s=t.console;
vendor: 4,185 bytes, lines 509-510
509function n(t,e,o){if(!(this instanceof n))return new n(t,e,o);let r=t;var h;("string"==typeof t&&(r=document.querySelectorAll(t)),r)?(this.elements=(h=r,Array.isArray(h)?h:"object"==typeof h&&"number"==typeof h.length?[...h]:[h]),this.options={},"function"==typeof e?o=e:Object.assign(this.options,e),o&&this.on("always",o),this.getImages(),i&&(this.jqDeferred=new i.Deferred),setTimeout(this.check.bind(this))):s.error(`Bad element for imagesLoaded ${r||t}`)}n.prototype=Object.create(e.prototype),n.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)};const o=[1,9,11];n.prototype.addElementImages=function(t){"IMG"===t.nodeName&&this.addImage(t),!0===this.options.background&&this.addElementBackgroundImages(t);let{nodeType:e}=t;if(!e||!o.includes(e))return;let i=t.querySelectorAll("img");for(let t of i)this.addImage(t);if("string"==typeof this.options.background){let e=t.querySelectorAll(this.options.background);for(let t of e)this.addElementBackgroundImages(t)}};const r=/url\((['"])?(.*?)\1\)/gi;function h(t){this.img=t}function d(t,e){this.url=t,this.element=e,this.img=new Image}return n.prototype.addElementBackgroundImages=function(t){let e=getComputedStyle(t);if(!e)return;let i=r.exec(e.backgroundImage);for(;null!==i;){let s=i&&i[2];s&&this.addBackground(s,t),i=r.exec(e.backgroundImage)}},n.prototype.addImage=function(t){let e=new h(t);this.images.push(e)},n.prototype.addBackground=function(t,e){let i=new d(t,e);this.images.push(i)},n.prototype.check=function(){if(this.progressedCount=0,this.hasAnyBroken=!1,!this.images.length)return void this.complete();let t=(t,e,i)=>{setTimeout((()=>{this.progress(t,e,i)}))};this.images.forEach((function(e){e.once("progress",t),e.check()}))},n.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount===this.images.length&&this.complete(),this.options.debug&&s&&s.log(`progress: ${i}`,t,e)},n.prototype.complete=function(){let t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){let t=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[t](this)}},h.prototype=Object.create(e.prototype),h.prototype.check=function(){this.getIsImageComplete()?this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.img.crossOrigin&&(this.proxyImage.crossOrigin=this.img.crossOrigin),this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.proxyImage.src=this.img.currentSrc||this.img.src)},h.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth},h.prototype.confirm=function(t,e){this.isLoaded=t;let{parentNode:i}=this.img,s="PICTURE"===i.nodeName?i:this.img;this.emitEvent("progress",[this,s,e])},h.prototype.handleEvent=function(t){let e="on"+t.type;this[e]&&this[e](t)},h.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},h.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},h.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype=Object.create(h.prototype),d.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url,this.getIsImageComplete()&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},d.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},n.makeJQueryPlugin=function(e){(e=e||t.jQuery)&&(i=e,i.fn.imagesLoaded=function(t,e){return new n(this,t,e).jqDeferred.promise(i(this))})},n.makeJQueryPlugin(),n}));;
510/*! This file is auto-generated */
vendor: 24,103 bytes, lines 511-519
511/*!
512 * Masonry PACKAGED v4.2.2
513 * Cascading grid layout library
514 * https://masonry.desandro.com
515 * MIT License
516 * by David DeSandro
517 */
518
519!function(t,e){"function"==typeof define&&define.amd?define("jquery-bridget/jquery-bridget",["jquery"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("jquery")):t.jQueryBridget=e(t,t.jQuery)}(window,function(t,e){"use strict";function i(i,r,a){function h(t,e,n){var o,r="$()."+i+'("'+e+'")';return t.each(function(t,h){var u=a.data(h,i);if(!u)return void s(i+" not initialized. Cannot call methods, i.e. "+r);var d=u[e];if(!d||"_"==e.charAt(0))return void s(r+" is not a valid method");var l=d.apply(u,n);o=void 0===o?l:o}),void 0!==o?o:t}function u(t,e){t.each(function(t,n){var o=a.data(n,i);o?(o.option(e),o._init()):(o=new r(n,e),a.data(n,i,o))})}a=a||e||t.jQuery,a&&(r.prototype.option||(r.prototype.option=function(t){a.isPlainObject(t)&&(this.options=a.extend(!0,this.options,t))}),a.fn[i]=function(t){if("string"==typeof t){var e=o.call(arguments,1);return h(this,t,e)}return u(this,t),this},n(a))}function n(t){!t||t&&t.bridget||(t.bridget=i)}var o=Array.prototype.slice,r=t.console,s="undefined"==typeof r?function(){}:function(t){r.error(t)};return n(e||t.jQuery),i}),function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||{};return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){i=i.slice(0),e=e||[];for(var n=this._onceEvents&&this._onceEvents[t],o=0;o<i.length;o++){var r=i[o],s=n&&n[r];s&&(this.off(t,r),delete n[r]),r.apply(this,e)}return this}},e.allOff=function(){delete this._events,delete this._onceEvents},t}),function(t,e){"function"==typeof define&&define.amd?define("get-size/get-size",e):"object"==typeof module&&module.exports?module.exports=e():t.getSize=e()}(window,function(){"use strict";function t(t){var e=parseFloat(t),i=-1==t.indexOf("%")&&!isNaN(e);return i&&e}function e(){}function i(){for(var t={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},e=0;u>e;e++){var i=h[e];t[i]=0}return t}function n(t){var e=getComputedStyle(t);return e||a("Style returned "+e+". Are you running this code in a hidden iframe on Firefox? See https://bit.ly/getsizebug1"),e}function o(){if(!d){d=!0;var e=document.createElement("div");e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style.boxSizing="border-box";var i=document.body||document.documentElement;i.appendChild(e);var o=n(e);s=200==Math.round(t(o.width)),r.isBoxSizeOuter=s,i.removeChild(e)}}function r(e){if(o(),"string"==typeof e&&(e=document.querySelector(e)),e&&"object"==typeof e&&e.nodeType){var r=n(e);if("none"==r.display)return i();var a={};a.width=e.offsetWidth,a.height=e.offsetHeight;for(var d=a.isBorderBox="border-box"==r.boxSizing,l=0;u>l;l++){var c=h[l],f=r[c],m=parseFloat(f);a[c]=isNaN(m)?0:m}var p=a.paddingLeft+a.paddingRight,g=a.paddingTop+a.paddingBottom,y=a.marginLeft+a.marginRight,v=a.marginTop+a.marginBottom,_=a.borderLeftWidth+a.borderRightWidth,z=a.borderTopWidth+a.borderBottomWidth,E=d&&s,b=t(r.width);b!==!1&&(a.width=b+(E?0:p+_));var x=t(r.height);return x!==!1&&(a.height=x+(E?0:g+z)),a.innerWidth=a.width-(p+_),a.innerHeight=a.height-(g+z),a.outerWidth=a.width+y,a.outerHeight=a.height+v,a}}var s,a="undefined"==typeof console?e:function(t){console.error(t)},h=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"],u=h.length,d=!1;return r}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("desandro-matches-selector/matches-selector",e):"object"==typeof module&&module.exports?module.exports=e():t.matchesSelector=e()}(window,function(){"use strict";var t=function(){var t=window.Element.prototype;if(t.matches)return"matches";if(t.matchesSelector)return"matchesSelector";for(var e=["webkit","moz","ms","o"],i=0;i<e.length;i++){var n=e[i],o=n+"MatchesSelector";if(t[o])return o}}();return function(e,i){return e[t](i)}}),function(t,e){"function"==typeof define&&define.amd?define("fizzy-ui-utils/utils",["desandro-matches-selector/matches-selector"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("desandro-matches-selector")):t.fizzyUIUtils=e(t,t.matchesSelector)}(window,function(t,e){var i={};i.extend=function(t,e){for(var i in e)t[i]=e[i];return t},i.modulo=function(t,e){return(t%e+e)%e};var n=Array.prototype.slice;i.makeArray=function(t){if(Array.isArray(t))return t;if(null===t||void 0===t)return[];var e="object"==typeof t&&"number"==typeof t.length;return e?n.call(t):[t]},i.removeFrom=function(t,e){var i=t.indexOf(e);-1!=i&&t.splice(i,1)},i.getParent=function(t,i){for(;t.parentNode&&t!=document.body;)if(t=t.parentNode,e(t,i))return t},i.getQueryElement=function(t){return"string"==typeof t?document.querySelector(t):t},i.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},i.filterFindElements=function(t,n){t=i.makeArray(t);var o=[];return t.forEach(function(t){if(t instanceof HTMLElement){if(!n)return void o.push(t);e(t,n)&&o.push(t);for(var i=t.querySelectorAll(n),r=0;r<i.length;r++)o.push(i[r])}}),o},i.debounceMethod=function(t,e,i){i=i||100;var n=t.prototype[e],o=e+"Timeout";t.prototype[e]=function(){var t=this[o];clearTimeout(t);var e=arguments,r=this;this[o]=setTimeout(function(){n.apply(r,e),delete r[o]},i)}},i.docReady=function(t){var e=document.readyState;"complete"==e||"interactive"==e?setTimeout(t):document.addEventListener("DOMContentLoaded",t)},i.toDashed=function(t){return t.replace(/(.)([A-Z])/g,function(t,e,i){return e+"-"+i}).toLowerCase()};var o=t.console;return i.htmlInit=function(e,n){i.docReady(function(){var r=i.toDashed(n),s="data-"+r,a=document.querySelectorAll("["+s+"]"),h=document.querySelectorAll(".js-"+r),u=i.makeArray(a).concat(i.makeArray(h)),d=s+"-options",l=t.jQuery;u.forEach(function(t){var i,r=t.getAttribute(s)||t.getAttribute(d);try{i=r&&JSON.parse(r)}catch(a){return void(o&&o.error("Error parsing "+s+" on "+t.className+": "+a))}var h=new e(t,i);l&&l.data(t,n,h)})})},i}),function(t,e){"function"==typeof define&&define.amd?define("outlayer/item",["ev-emitter/ev-emitter","get-size/get-size"],e):"object"==typeof module&&module.exports?module.exports=e(require("ev-emitter"),require("get-size")):(t.Outlayer={},t.Outlayer.Item=e(t.EvEmitter,t.getSize))}(window,function(t,e){"use strict";function i(t){for(var e in t)return!1;return e=null,!0}function n(t,e){t&&(this.element=t,this.layout=e,this.position={x:0,y:0},this._create())}function o(t){return t.replace(/([A-Z])/g,function(t){return"-"+t.toLowerCase()})}var r=document.documentElement.style,s="string"==typeof r.transition?"transition":"WebkitTransition",a="string"==typeof r.transform?"transform":"WebkitTransform",h={WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[s],u={transform:a,transition:s,transitionDuration:s+"Duration",transitionProperty:s+"Property",transitionDelay:s+"Delay"},d=n.prototype=Object.create(t.prototype);d.constructor=n,d._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},d.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},d.getSize=function(){this.size=e(this.element)},d.css=function(t){var e=this.element.style;for(var i in t){var n=u[i]||i;e[n]=t[i]}},d.getPosition=function(){var t=getComputedStyle(this.element),e=this.layout._getOption("originLeft"),i=this.layout._getOption("originTop"),n=t[e?"left":"right"],o=t[i?"top":"bottom"],r=parseFloat(n),s=parseFloat(o),a=this.layout.size;-1!=n.indexOf("%")&&(r=r/100*a.width),-1!=o.indexOf("%")&&(s=s/100*a.height),r=isNaN(r)?0:r,s=isNaN(s)?0:s,r-=e?a.paddingLeft:a.paddingRight,s-=i?a.paddingTop:a.paddingBottom,this.position.x=r,this.position.y=s},d.layoutPosition=function(){var t=this.layout.size,e={},i=this.layout._getOption("originLeft"),n=this.layout._getOption("originTop"),o=i?"paddingLeft":"paddingRight",r=i?"left":"right",s=i?"right":"left",a=this.position.x+t[o];e[r]=this.getXValue(a),e[s]="";var h=n?"paddingTop":"paddingBottom",u=n?"top":"bottom",d=n?"bottom":"top",l=this.position.y+t[h];e[u]=this.getYValue(l),e[d]="",this.css(e),this.emitEvent("layout",[this])},d.getXValue=function(t){var e=this.layout._getOption("horizontal");return this.layout.options.percentPosition&&!e?t/this.layout.size.width*100+"%":t+"px"},d.getYValue=function(t){var e=this.layout._getOption("horizontal");return this.layout.options.percentPosition&&e?t/this.layout.size.height*100+"%":t+"px"},d._transitionTo=function(t,e){this.getPosition();var i=this.position.x,n=this.position.y,o=t==this.position.x&&e==this.position.y;if(this.setPosition(t,e),o&&!this.isTransitioning)return void this.layoutPosition();var r=t-i,s=e-n,a={};a.transform=this.getTranslate(r,s),this.transition({to:a,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},d.getTranslate=function(t,e){var i=this.layout._getOption("originLeft"),n=this.layout._getOption("originTop");return t=i?t:-t,e=n?e:-e,"translate3d("+t+"px, "+e+"px, 0)"},d.goTo=function(t,e){this.setPosition(t,e),this.layoutPosition()},d.moveTo=d._transitionTo,d.setPosition=function(t,e){this.position.x=parseFloat(t),this.position.y=parseFloat(e)},d._nonTransition=function(t){this.css(t.to),t.isCleaning&&this._removeStyles(t.to);for(var e in t.onTransitionEnd)t.onTransitionEnd[e].call(this)},d.transition=function(t){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(t);var e=this._transn;for(var i in t.onTransitionEnd)e.onEnd[i]=t.onTransitionEnd[i];for(i in t.to)e.ingProperties[i]=!0,t.isCleaning&&(e.clean[i]=!0);if(t.from){this.css(t.from);var n=this.element.offsetHeight;n=null}this.enableTransition(t.to),this.css(t.to),this.isTransitioning=!0};var l="opacity,"+o(a);d.enableTransition=function(){if(!this.isTransitioning){var t=this.layout.options.transitionDuration;t="number"==typeof t?t+"ms":t,this.css({transitionProperty:l,transitionDuration:t,transitionDelay:this.staggerDelay||0}),this.element.addEventListener(h,this,!1)}},d.onwebkitTransitionEnd=function(t){this.ontransitionend(t)},d.onotransitionend=function(t){this.ontransitionend(t)};var c={"-webkit-transform":"transform"};d.ontransitionend=function(t){if(t.target===this.element){var e=this._transn,n=c[t.propertyName]||t.propertyName;if(delete e.ingProperties[n],i(e.ingProperties)&&this.disableTransition(),n in e.clean&&(this.element.style[t.propertyName]="",delete e.clean[n]),n in e.onEnd){var o=e.onEnd[n];o.call(this),delete e.onEnd[n]}this.emitEvent("transitionEnd",[this])}},d.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(h,this,!1),this.isTransitioning=!1},d._removeStyles=function(t){var e={};for(var i in t)e[i]="";this.css(e)};var f={transitionProperty:"",transitionDuration:"",transitionDelay:""};return d.removeTransitionStyles=function(){this.css(f)},d.stagger=function(t){t=isNaN(t)?0:t,this.staggerDelay=t+"ms"},d.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this])},d.remove=function(){return s&&parseFloat(this.layout.options.transitionDuration)?(this.once("transitionEnd",function(){this.removeElem()}),void this.hide()):void this.removeElem()},d.reveal=function(){delete this.isHidden,this.css({display:""});var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("visibleStyle");e[i]=this.onRevealTransitionEnd,this.transition({from:t.hiddenStyle,to:t.visibleStyle,isCleaning:!0,onTransitionEnd:e})},d.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal")},d.getHideRevealTransitionEndProperty=function(t){var e=this.layout.options[t];if(e.opacity)return"opacity";for(var i in e)return i},d.hide=function(){this.isHidden=!0,this.css({display:""});var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("hiddenStyle");e[i]=this.onHideTransitionEnd,this.transition({from:t.visibleStyle,to:t.hiddenStyle,isCleaning:!0,onTransitionEnd:e})},d.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"))},d.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},n}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("outlayer/outlayer",["ev-emitter/ev-emitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(i,n,o,r){return e(t,i,n,o,r)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):t.Outlayer=e(t,t.EvEmitter,t.getSize,t.fizzyUIUtils,t.Outlayer.Item)}(window,function(t,e,i,n,o){"use strict";function r(t,e){var i=n.getQueryElement(t);if(!i)return void(h&&h.error("Bad element for "+this.constructor.namespace+": "+(i||t)));this.element=i,u&&(this.$element=u(this.element)),this.options=n.extend({},this.constructor.defaults),this.option(e);var o=++l;this.element.outlayerGUID=o,c[o]=this,this._create();var r=this._getOption("initLayout");r&&this.layout()}function s(t){function e(){t.apply(this,arguments)}return e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e}function a(t){if("number"==typeof t)return t;var e=t.match(/(^\d*\.?\d*)(\w*)/),i=e&&e[1],n=e&&e[2];if(!i.length)return 0;i=parseFloat(i);var o=m[n]||1;return i*o}var h=t.console,u=t.jQuery,d=function(){},l=0,c={};r.namespace="outlayer",r.Item=o,r.defaults={containerStyle:{position:"relative"},initLayout:!0,originLeft:!0,originTop:!0,resize:!0,resizeContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}};var f=r.prototype;n.extend(f,e.prototype),f.option=function(t){n.extend(this.options,t)},f._getOption=function(t){var e=this.constructor.compatOptions[t];return e&&void 0!==this.options[e]?this.options[e]:this.options[t]},r.compatOptions={initLayout:"isInitLayout",horizontal:"isHorizontal",layoutInstant:"isLayoutInstant",originLeft:"isOriginLeft",originTop:"isOriginTop",resize:"isResizeBound",resizeContainer:"isResizingContainer"},f._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),n.extend(this.element.style,this.options.containerStyle);var t=this._getOption("resize");t&&this.bindResize()},f.reloadItems=function(){this.items=this._itemize(this.element.children)},f._itemize=function(t){for(var e=this._filterFindItemElements(t),i=this.constructor.Item,n=[],o=0;o<e.length;o++){var r=e[o],s=new i(r,this);n.push(s)}return n},f._filterFindItemElements=function(t){return n.filterFindElements(t,this.options.itemSelector)},f.getItemElements=function(){return this.items.map(function(t){return t.element})},f.layout=function(){this._resetLayout(),this._manageStamps();var t=this._getOption("layoutInstant"),e=void 0!==t?t:!this._isLayoutInited;this.layoutItems(this.items,e),this._isLayoutInited=!0},f._init=f.layout,f._resetLayout=function(){this.getSize()},f.getSize=function(){this.size=i(this.element)},f._getMeasurement=function(t,e){var n,o=this.options[t];o?("string"==typeof o?n=this.element.querySelector(o):o instanceof HTMLElement&&(n=o),this[t]=n?i(n)[e]:o):this[t]=0},f.layoutItems=function(t,e){t=this._getItemsForLayout(t),this._layoutItems(t,e),this._postLayout()},f._getItemsForLayout=function(t){return t.filter(function(t){return!t.isIgnored})},f._layoutItems=function(t,e){if(this._emitCompleteOnItems("layout",t),t&&t.length){var i=[];t.forEach(function(t){var n=this._getItemLayoutPosition(t);n.item=t,n.isInstant=e||t.isLayoutInstant,i.push(n)},this),this._processLayoutQueue(i)}},f._getItemLayoutPosition=function(){return{x:0,y:0}},f._processLayoutQueue=function(t){this.updateStagger(),t.forEach(function(t,e){this._positionItem(t.item,t.x,t.y,t.isInstant,e)},this)},f.updateStagger=function(){var t=this.options.stagger;return null===t||void 0===t?void(this.stagger=0):(this.stagger=a(t),this.stagger)},f._positionItem=function(t,e,i,n,o){n?t.goTo(e,i):(t.stagger(o*this.stagger),t.moveTo(e,i))},f._postLayout=function(){this.resizeContainer()},f.resizeContainer=function(){var t=this._getOption("resizeContainer");if(t){var e=this._getContainerSize();e&&(this._setContainerMeasure(e.width,!0),this._setContainerMeasure(e.height,!1))}},f._getContainerSize=d,f._setContainerMeasure=function(t,e){if(void 0!==t){var i=this.size;i.isBorderBox&&(t+=e?i.paddingLeft+i.paddingRight+i.borderLeftWidth+i.borderRightWidth:i.paddingBottom+i.paddingTop+i.borderTopWidth+i.borderBottomWidth),t=Math.max(t,0),this.element.style[e?"width":"height"]=t+"px"}},f._emitCompleteOnItems=function(t,e){function i(){o.dispatchEvent(t+"Complete",null,[e])}function n(){s++,s==r&&i()}var o=this,r=e.length;if(!e||!r)return void i();var s=0;e.forEach(function(e){e.once(t,n)})},f.dispatchEvent=function(t,e,i){var n=e?[e].concat(i):i;if(this.emitEvent(t,n),u)if(this.$element=this.$element||u(this.element),e){var o=u.Event(e);o.type=t,this.$element.trigger(o,i)}else this.$element.trigger(t,i)},f.ignore=function(t){var e=this.getItem(t);e&&(e.isIgnored=!0)},f.unignore=function(t){var e=this.getItem(t);e&&delete e.isIgnored},f.stamp=function(t){t=this._find(t),t&&(this.stamps=this.stamps.concat(t),t.forEach(this.ignore,this))},f.unstamp=function(t){t=this._find(t),t&&t.forEach(function(t){n.removeFrom(this.stamps,t),this.unignore(t)},this)},f._find=function(t){return t?("string"==typeof t&&(t=this.element.querySelectorAll(t)),t=n.makeArray(t)):void 0},f._manageStamps=function(){this.stamps&&this.stamps.length&&(this._getBoundingRect(),this.stamps.forEach(this._manageStamp,this))},f._getBoundingRect=function(){var t=this.element.getBoundingClientRect(),e=this.size;this._boundingRect={left:t.left+e.paddingLeft+e.borderLeftWidth,top:t.top+e.paddingTop+e.borderTopWidth,right:t.right-(e.paddingRight+e.borderRightWidth),bottom:t.bottom-(e.paddingBottom+e.borderBottomWidth)}},f._manageStamp=d,f._getElementOffset=function(t){var e=t.getBoundingClientRect(),n=this._boundingRect,o=i(t),r={left:e.left-n.left-o.marginLeft,top:e.top-n.top-o.marginTop,right:n.right-e.right-o.marginRight,bottom:n.bottom-e.bottom-o.marginBottom};return r},f.handleEvent=n.handleEvent,f.bindResize=function(){t.addEventListener("resize",this),this.isResizeBound=!0},f.unbindResize=function(){t.removeEventListener("resize",this),this.isResizeBound=!1},f.onresize=function(){this.resize()},n.debounceMethod(r,"onresize",100),f.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},f.needsResizeLayout=function(){var t=i(this.element),e=this.size&&t;return e&&t.innerWidth!==this.size.innerWidth},f.addItems=function(t){var e=this._itemize(t);return e.length&&(this.items=this.items.concat(e)),e},f.appended=function(t){var e=this.addItems(t);e.length&&(this.layoutItems(e,!0),this.reveal(e))},f.prepended=function(t){var e=this._itemize(t);if(e.length){var i=this.items.slice(0);this.items=e.concat(i),this._resetLayout(),this._manageStamps(),this.layoutItems(e,!0),this.reveal(e),this.layoutItems(i)}},f.reveal=function(t){if(this._emitCompleteOnItems("reveal",t),t&&t.length){var e=this.updateStagger();t.forEach(function(t,i){t.stagger(i*e),t.reveal()})}},f.hide=function(t){if(this._emitCompleteOnItems("hide",t),t&&t.length){var e=this.updateStagger();t.forEach(function(t,i){t.stagger(i*e),t.hide()})}},f.revealItemElements=function(t){var e=this.getItems(t);this.reveal(e)},f.hideItemElements=function(t){var e=this.getItems(t);this.hide(e)},f.getItem=function(t){for(var e=0;e<this.items.length;e++){var i=this.items[e];if(i.element==t)return i}},f.getItems=function(t){t=n.makeArray(t);var e=[];return t.forEach(function(t){var i=this.getItem(t);i&&e.push(i)},this),e},f.remove=function(t){var e=this.getItems(t);this._emitCompleteOnItems("remove",e),e&&e.length&&e.forEach(function(t){t.remove(),n.removeFrom(this.items,t)},this)},f.destroy=function(){var t=this.element.style;t.height="",t.position="",t.width="",this.items.forEach(function(t){t.destroy()}),this.unbindResize();var e=this.element.outlayerGUID;delete c[e],delete this.element.outlayerGUID,u&&u.removeData(this.element,this.constructor.namespace)},r.data=function(t){t=n.getQueryElement(t);var e=t&&t.outlayerGUID;return e&&c[e]},r.create=function(t,e){var i=s(r);return i.defaults=n.extend({},r.defaults),n.extend(i.defaults,e),i.compatOptions=n.extend({},r.compatOptions),i.namespace=t,i.data=r.data,i.Item=s(o),n.htmlInit(i,t),u&&u.bridget&&u.bridget(t,i),i};var m={ms:1,s:1e3};return r.Item=o,r}),function(t,e){"function"==typeof define&&define.amd?define(["outlayer/outlayer","get-size/get-size"],e):"object"==typeof module&&module.exports?module.exports=e(require("outlayer"),require("get-size")):t.Masonry=e(t.Outlayer,t.getSize)}(window,function(t,e){var i=t.create("masonry");i.compatOptions.fitWidth="isFitWidth";var n=i.prototype;return n._resetLayout=function(){this.getSize(),this._getMeasurement("columnWidth","outerWidth"),this._getMeasurement("gutter","outerWidth"),this.measureColumns(),this.colYs=[];for(var t=0;t<this.cols;t++)this.colYs.push(0);this.maxY=0,this.horizontalColIndex=0},n.measureColumns=function(){if(this.getContainerWidth(),!this.columnWidth){var t=this.items[0],i=t&&t.element;this.columnWidth=i&&e(i).outerWidth||this.containerWidth}var n=this.columnWidth+=this.gutter,o=this.containerWidth+this.gutter,r=o/n,s=n-o%n,a=s&&1>s?"round":"floor";r=Math[a](r),this.cols=Math.max(r,1)},n.getContainerWidth=function(){var t=this._getOption("fitWidth"),i=t?this.element.parentNode:this.element,n=e(i);this.containerWidth=n&&n.innerWidth},n._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth%this.columnWidth,i=e&&1>e?"round":"ceil",n=Math[i](t.size.outerWidth/this.columnWidth);n=Math.min(n,this.cols);for(var o=this.options.horizontalOrder?"_getHorizontalColPosition":"_getTopColPosition",r=this[o](n,t),s={x:this.columnWidth*r.col,y:r.y},a=r.y+t.size.outerHeight,h=n+r.col,u=r.col;h>u;u++)this.colYs[u]=a;return s},n._getTopColPosition=function(t){var e=this._getTopColGroup(t),i=Math.min.apply(Math,e);return{col:e.indexOf(i),y:i}},n._getTopColGroup=function(t){if(2>t)return this.colYs;for(var e=[],i=this.cols+1-t,n=0;i>n;n++)e[n]=this._getColGroupY(n,t);return e},n._getColGroupY=function(t,e){if(2>e)return this.colYs[t];var i=this.colYs.slice(t,t+e);return Math.max.apply(Math,i)},n._getHorizontalColPosition=function(t,e){var i=this.horizontalColIndex%this.cols,n=t>1&&i+t>this.cols;i=n?0:i;var o=e.size.outerWidth&&e.size.outerHeight;return this.horizontalColIndex=o?i+t:this.horizontalColIndex,{col:i,y:this._getColGroupY(i,t)}},n._manageStamp=function(t){var i=e(t),n=this._getElementOffset(t),o=this._getOption("originLeft"),r=o?n.left:n.right,s=r+i.outerWidth,a=Math.floor(r/this.columnWidth);a=Math.max(0,a);var h=Math.floor(s/this.columnWidth);h-=s%this.columnWidth?0:1,h=Math.min(this.cols-1,h);for(var u=this._getOption("originTop"),d=(u?n.top:n.bottom)+i.outerHeight,l=a;h>=l;l++)this.colYs[l]=Math.max(d,this.colYs[l])},n._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var t={height:this.maxY};return this._getOption("fitWidth")&&(t.width=this._getContainerFitWidth()),t},n._getContainerFitWidth=function(){for(var t=0,e=this.cols;--e&&0===this.colYs[e];)t++;return(this.cols-t)*this.columnWidth-this.gutter},n.needsResizeLayout=function(){var t=this.containerWidth;return this.getContainerWidth(),t!=this.containerWidth},i});
519;
520/*!
521 * imagesLoaded PACKAGED v3.1.8
522 * JavaScript is all like "You images are done yet or what?"
523 * MIT License
524 */
525
526
527/*!
528 * EventEmitter v4.2.6 - git.io/ee
529 * Oliver Caldwell
530 * MIT license
531 * @preserve
532 */
533
534(function () {
535	
536
537	/**
538	 * Class for managing events.
539	 * Can be extended to provide event functionality in other classes.
540	 *
541	 * @class EventEmitter Manages event registering and emitting.
542	 */
543	function EventEmitter() {}
544
545	// Shortcuts to improve speed and size
546	var proto = EventEmitter.prototype;
547	var exports = this;
548	var originalGlobalValue = exports.EventEmitter;
549
550	/**
551	 * Finds the index of the listener for the event in it's storage array.
552	 *
553	 * @param {Function[]} listeners Array of listeners to search through.
554	 * @param {Function} listener Method to look for.
555	 * @return {Number} Index of the specified listener, -1 if not found
556	 * @api private
557	 */
558	function indexOfListener(listeners, listener) {
559		var i = listeners.length;
560		while (i--) {
561			if (listeners[i].listener === listener) {
562				return i;
563			}
564		}
565
566		return -1;
567	}
568
569	/**
570	 * Alias a method while keeping the context correct, to allow for over
vendor: 11,346 bytes, lines 570-878
570writing of target method.
571	 *
572	 * @param {String} name The name of the target method.
573	 * @return {Function} The aliased method
574	 * @api private
575	 */
576	function alias(name) {
577		return function aliasClosure() {
578			return this[name].apply(this, arguments);
579		};
580	}
581
582	/**
583	 * Returns the listener array for the specified event.
584	 * Will initialise the event object and listener arrays if required.
585	 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
586	 * Each property in the object response is an array of listener functions.
587	 *
588	 * @param {String|RegExp} evt Name of the event to return the listeners from.
589	 * @return {Function[]|Object} All listener functions for the event.
590	 */
591	proto.getListeners = function getListeners(evt) {
592		var events = this._getEvents();
593		var response;
594		var key;
595
596		// Return a concatenated array of all matching events if
597		// the selector is a regular expression.
598		if (typeof evt === 'object') {
599			response = {};
600			for (key in events) {
601				if (events.hasOwnProperty(key) && evt.test(key)) {
602					response[key] = events[key];
603				}
604			}
605		}
606		else {
607			response = events[evt] || (events[evt] = []);
608		}
609
610		return response;
611	};
612
613	/**
614	 * Takes a list of listener objects and flattens it into a list of listener functions.
615	 *
616	 * @param {Object[]} listeners Raw listener objects.
617	 * @return {Function[]} Just the listener functions.
618	 */
619	proto.flattenListeners = function flattenListeners(listeners) {
620		var flatListeners = [];
621		var i;
622
623		for (i = 0; i < listeners.length; i += 1) {
624			flatListeners.push(listeners[i].listener);
625		}
626
627		return flatListeners;
628	};
629
630	/**
631	 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
632	 *
633	 * @param {String|RegExp} evt Name of the event to return the listeners from.
634	 * @return {Object} All listener functions for an event in an object.
635	 */
636	proto.getListenersAsObject = function getListenersAsObject(evt) {
637		var listeners = this.getListeners(evt);
638		var response;
639
640		if (listeners instanceof Array) {
641			response = {};
642			response[evt] = listeners;
643		}
644
645		return response || listeners;
646	};
647
648	/**
649	 * Adds a listener function to the specified event.
650	 * The listener will not be added if it is a duplicate.
651	 * If the listener returns true then it will be removed after it is called.
652	 * If you pass a regular expression as the event name then the listener will be added to all events that match it.
653	 *
654	 * @param {String|RegExp} evt Name of the event to attach the listener to.
655	 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
656	 * @return {Object} Current instance of EventEmitter for chaining.
657	 */
658	proto.addListener = function addListener(evt, listener) {
659		var listeners = this.getListenersAsObject(evt);
660		var listenerIsWrapped = typeof listener === 'object';
661		var key;
662
663		for (key in listeners) {
664			if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
665				listeners[key].push(listenerIsWrapped ? listener : {
666					listener: listener,
667					once: false
668				});
669			}
670		}
671
672		return this;
673	};
674
675	/**
676	 * Alias of addListener
677	 */
678	proto.on = alias('addListener');
679
680	/**
681	 * Semi-alias of addListener. It will add a listener that will be
682	 * automatically removed after it's first execution.
683	 *
684	 * @param {String|RegExp} evt Name of the event to attach the listener to.
685	 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
686	 * @return {Object} Current instance of EventEmitter for chaining.
687	 */
688	proto.addOnceListener = function addOnceListener(evt, listener) {
689		return this.addListener(evt, {
690			listener: listener,
691			once: true
692		});
693	};
694
695	/**
696	 * Alias of addOnceListener.
697	 */
698	proto.once = alias('addOnceListener');
699
700	/**
701	 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
702	 * You need to tell it what event names should be matched by a regex.
703	 *
704	 * @param {String} evt Name of the event to create.
705	 * @return {Object} Current instance of EventEmitter for chaining.
706	 */
707	proto.defineEvent = function defineEvent(evt) {
708		this.getListeners(evt);
709		return this;
710	};
711
712	/**
713	 * Uses defineEvent to define multiple events.
714	 *
715	 * @param {String[]} evts An array of event names to define.
716	 * @return {Object} Current instance of EventEmitter for chaining.
717	 */
718	proto.defineEvents = function defineEvents(evts) {
719		for (var i = 0; i < evts.length; i += 1) {
720			this.defineEvent(evts[i]);
721		}
722		return this;
723	};
724
725	/**
726	 * Removes a listener function from the specified event.
727	 * When passed a regular expression as the event name, it will remove the listener from all events that match it.
728	 *
729	 * @param {String|RegExp} evt Name of the event to remove the listener from.
730	 * @param {Function} listener Method to remove from the event.
731	 * @return {Object} Current instance of EventEmitter for chaining.
732	 */
733	proto.removeListener = function removeListener(evt, listener) {
734		var listeners = this.getListenersAsObject(evt);
735		var index;
736		var key;
737
738		for (key in listeners) {
739			if (listeners.hasOwnProperty(key)) {
740				index = indexOfListener(listeners[key], listener);
741
742				if (index !== -1) {
743					listeners[key].splice(index, 1);
744				}
745			}
746		}
747
748		return this;
749	};
750
751	/**
752	 * Alias of removeListener
753	 */
754	proto.off = alias('removeListener');
755
756	/**
757	 * Adds listeners in bulk using the manipulateListeners method.
758	 * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
759	 * You can also pass it a regular expression to add the array of listeners to all events that match it.
760	 * Yeah, this function does quite a bit. That's probably a bad thing.
761	 *
762	 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
763	 * @param {Function[]} [listeners] An optional array of listener functions to add.
764	 * @return {Object} Current instance of EventEmitter for chaining.
765	 */
766	proto.addListeners = function addListeners(evt, listeners) {
767		// Pass through to manipulateListeners
768		return this.manipulateListeners(false, evt, listeners);
769	};
770
771	/**
772	 * Removes listeners in bulk using the manipulateListeners method.
773	 * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
774	 * You can also pass it an event name and an array of listeners to be removed.
775	 * You can also pass it a regular expression to remove the listeners from all events that match it.
776	 *
777	 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
778	 * @param {Function[]} [listeners] An optional array of listener functions to remove.
779	 * @return {Object} Current instance of EventEmitter for chaining.
780	 */
781	proto.removeListeners = function removeListeners(evt, listeners) {
782		// Pass through to manipulateListeners
783		return this.manipulateListeners(true, evt, listeners);
784	};
785
786	/**
787	 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
788	 * The first argument will determine if the listeners are removed (true) or added (false).
789	 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
790	 * You can also pass it an event name and an array of listeners to be added/removed.
791	 * You can also pass it a regular expression to manipulate the listeners of all events that match it.
792	 *
793	 * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
794	 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
795	 * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
796	 * @return {Object} Current instance of EventEmitter for chaining.
797	 */
798	proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
799		var i;
800		var value;
801		var single = remove ? this.removeListener : this.addListener;
802		var multiple = remove ? this.removeListeners : this.addListeners;
803
804		// If evt is an object then pass each of it's properties to this method
805		if (typeof evt === 'object' && !(evt instanceof RegExp)) {
806			for (i in evt) {
807				if (evt.hasOwnProperty(i) && (value = evt[i])) {
808					// Pass the single listener straight through to the singular method
809					if (typeof value === 'function') {
810						single.call(this, i, value);
811					}
812					else {
813						// Otherwise pass back to the multiple function
814						multiple.call(this, i, value);
815					}
816				}
817			}
818		}
819		else {
820			// So evt must be a string
821			// And listeners must be an array of listeners
822			// Loop over it and pass each one to the multiple method
823			i = listeners.length;
824			while (i--) {
825				single.call(this, evt, listeners[i]);
826			}
827		}
828
829		return this;
830	};
831
832	/**
833	 * Removes all listeners from a specified event.
834	 * If you do not specify an event then all listeners will be removed.
835	 * That means every event will be emptied.
836	 * You can also pass a regex to remove all events that match it.
837	 *
838	 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
839	 * @return {Object} Current instance of EventEmitter for chaining.
840	 */
841	proto.removeEvent = function removeEvent(evt) {
842		var type = typeof evt;
843		var events = this._getEvents();
844		var key;
845
846		// Remove different things depending on the state of evt
847		if (type === 'string') {
848			// Remove all listeners for the specified event
849			delete events[evt];
850		}
851		else if (type === 'object') {
852			// Remove all events matching the regex.
853			for (key in events) {
854				if (events.hasOwnProperty(key) && evt.test(key)) {
855					delete events[key];
856				}
857			}
858		}
859		else {
860			// Remove all listeners in all events
861			delete this._events;
862		}
863
864		return this;
865	};
866
867	/**
868	 * Alias of removeEvent.
869	 *
870	 * Added to mirror the node API.
871	 */
872	proto.removeAllListeners = alias('removeEvent');
873
874	/**
875	 * Emits an event of your choice.
876	 * When emitted, every listener attached to that event will be executed.
877	 * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
878	 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
879	 * So they will not arrive within the array on the other side, they will be separate.
880	 * You can also pass a regular expression to emit to all events that match it.
881	 *
882	 * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
883	 * @param {Array} [args] Optional array of arguments to be passed to each listener.
884	 * @return {Object} Current instance of EventEmitter for chaining.
885	 */
886	proto.emitEvent = function emitEvent(evt, args) {
887		var listeners = this.getListenersAsObject(evt);
888		var listener;
889		var i;
890		var key;
891		var response;
892
893		for (key in listeners) {
894			if (listeners.hasOwnProperty(key)) {
895				i = listeners[key].length;
896
897				while (i--) {
898					// If the listener returns true then it shall be removed from the event
899					// The function is executed either with a basic call or an apply if there is an args array
900					listener = listeners[key][i];
901
902					if (listener.once === true) {
903						this.removeListener(evt, listener.listener);
904					}
905
906					response = listener.listener.apply(this, args || []);
907
908					if (response === this._getOnceReturnValue()) {
909						this.removeListener(evt, listener.listener);
910					}
911				}
912			}
913		}
914
915		return this;
916	};
917
918	/**
919	 * Alias of emitEvent
920	 */
921	proto.trigger = alias('emitEvent');
922
923	/**
924	 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
925	 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
926	 *
927	 * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
928	 * @param {...*} Optional additional arguments to be passed to each listener.
929	 * @return {Object} Current instance of EventEmitter for chaining.
930	 */
931	proto.emit = function emit(evt) {
932		var args = Array.prototype.slice.call(arguments, 1);
933		return this.emitEvent(evt, args);
934	};
935
936	/**
937	 * Sets the current value to check against when executing listeners. If a
938	 * listeners return value matches the one set here then it will be removed
939	 * after execution. This value defaults to true.
940	 *
941	 * @param {*} value The new value to check for when executing listeners.
942	 * @return {Object} Current instance of EventEmitter for chaining.
943	 */
944	proto.setOnceReturnValue = function setOnceReturnValue(value) {
945		this._onceReturnValue = value;
946		return this;
947	};
948
949	/**
950	 * Fetches the current value to check against when executing listeners. If
951	 * the listeners return value matches this one then it should be removed
952	 * automatically. It will return true by default.
953	 *
954	 * @return {*|Boolean} The current value to check for or the default, true.
955	 * @api private
956	 */
957	proto._getOnceReturnValue = function _getOnceReturnValue() {
958		if (this.hasOwnProperty('_onceReturnValue')) {
959			return this._onceReturnValue;
960		}
961		else {
962			return true;
963		}
964	};
965
966	/**
967	 * Fetches the events object and creates one if required.
968	 *
969	 * @return {Object} The events storage object.
970	 * @api private
971	 */
972	proto._getEvents = function _getEvents() {
973		return this._events || (this._events = {});
974	};
975
976	/**
977	 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
978	 *
979	 * @return {Function} Non conflicting EventEmitter class.
980	 */
981	EventEmitter.noConflict = function noConflict() {
982		exports.EventEmitter = originalGlobalValue;
983		return EventEmitter;
984	};
985
986	// Expose the class either via AMD, CommonJS or the global object
987	if (typeof define === 'function' && define.amd) {
988		define('eventEmitter/EventEmitter',[],function () {
989			return EventEmitter;
990		});
991	}
992	else if (typeof module === 'object' && module.exports){
993		module.exports = EventEmitter;
994	}
995	else {
996		this.EventEmitter = EventEmitter;
997	}
998}.call(this));
999
1000/*!
1001 * eventie v1.0.4
1002 * event binding helper
1003 *   eventie.bind( elem, 'click', myFn )
1004 *   eventie.unbind( elem, 'click', myFn )
1005 */
1006
1007/*jshint browser: true, undef: true, unused: true */
1008/*global define: false */
1009
1010( function( window ) {
1011
1012
1013
1014var docElem = document.documentElement;
1015
1016var bind = function() {};
1017
1018function getIEEvent( obj ) {
1019  var event = window.event;
1020  // add event.target
1021  event.target = event.target || event.srcElement || obj;
1022  return event;
1023}
1024
1025if ( docElem.addEventListener ) {
1026  bind = function( obj, type, fn ) {
1027    obj.addEventListener( type, fn, false );
1028  };
1029} else if ( docElem.attachEvent ) {
1030  bind = function( obj, type, fn ) {
1031    obj[ type + fn ] = fn.handleEvent ?
1032      function() {
1033        var event = getIEEvent( obj );
1034        fn.handleEvent.call( fn, event );
1035      } :
1036      function() {
1037        var event = getIEEvent( obj );
1038        fn.call( obj, event );
1039      };
1040    obj.attachEvent( "on" + type, obj[ type + fn ] );
1041  };
1042}
1043
1044var unbind = function() {};
1045
1046if ( docElem.removeEventListener ) {
1047  unbind = function( obj, type, fn ) {
1048    obj.removeEventListener( type, fn, false );
1049  };
1050} else if ( docElem.detachEvent ) {
1051  unbind = function( obj, type, fn ) {
1052    obj.detachEvent( "on" + type, obj[ type + fn ] );
1053    try {
1054      delete obj[ type + fn ];
1055    } catch ( err ) {
1056      // can't delete window object properties
1057      obj[ type + fn ] = undefined;
1058    }
1059  };
1060}
1061
1062var eventie = {
1063  bind: bind,
1064  unbind: unbind
1065};
1066
1067// transport
1068if ( typeof define === 'function' && define.amd ) {
1069  // AMD
1070  define( 'eventie/eventie',eventie );
1071} else {
1072  // browser global
1073  window.eventie = eventie;
1074}
1075
1076})( this );
1077
1078/*!
1079 * imagesLoaded v3.1.8
1080 * JavaScript is all like "You images are done yet or what?"
1081 * MIT License
1082 */
1083
1084( function( window, factory ) { 
1085  // universal module definition
1086
1087  /*global define: false, module: false, require: false */
1088
1089  if ( typeof define === 'function' && define.amd ) {
1090    // AMD
1091    define( [
1092      'eventEmitter/EventEmitter',
1093      'eventie/eventie'
1094    ], function( EventEmitter, eventie ) {
1095      return factory( window, EventEmitter, eventie );
1096    });
1097  } else if ( typeof exports === 'object' ) {
1098    // CommonJS
1099    module.exports = factory(
1100      window,
1101      require('wolfy87-eventemitter'),
1102      require('eventie')
1103    );
1104  } else {
1105    // browser global
1106    window.imagesLoaded = factory(
1107      window,
1108      window.EventEmitter,
1109      window.eventie
1110    );
1111  }
1112
1113})( window,
1114
1115// --------------------------  factory -------------------------- //
1116
1117function factory( window, EventEmitter, eventie ) {
1118
1119
1120
1121var $ = window.jQuery;
1122var console = window.console;
1123var hasConsole = typeof console !== 'undefined';
1124
1125// -------------------------- helpers -------------------------- //
1126
1127// extend objects
1128function extend( a, b ) {
1129  for ( var prop in b ) {
1130    a[ prop ] = b[ prop ];
1131  }
1132  return a;
1133}
1134
1135var objToString = Object.prototype.toString;
1136function isArray( obj ) {
1137  return objToString.call( obj ) === '[object Array]';
1138}
1139
1140// turn element or nodeList into an array
1141function makeArray( obj ) {
1142  var ary = [];
1143  if ( isArray( obj ) ) {
1144    // use object if already an array
1145    ary = obj;
1146  } else if ( typeof obj.length === 'number' ) {
1147    // convert nodeList to array
1148    for ( var i=0, len = obj.length; i < len; i++ ) {
1149      ary.push( obj[i] );
1150    }
1151  } else {
1152    // array of single index
1153    ary.push( obj );
1154  }
1155  return ary;
1156}
1157
1158  // -------------------------- imagesLoaded -------------------------- //
1159
1160  /**
1161   * @param {Array, Element, NodeList, String} elem
1162   * @param {Object or Function} options - if function, use as callback
1163   * @param {Function} onAlways - callback function
1164   */
1165  function ImagesLoaded( elem, options, onAlways ) {
1166    // coerce ImagesLoaded() without new, to be new ImagesLoaded()
1167    if ( !( this instanceof ImagesLoaded ) ) {
1168      return new ImagesLoaded( elem, options );
1169    }
1170    // use elem as selector string
1171    if ( typeof elem === 'string' ) {
1172      elem = document.querySelectorAll( elem );
1173    }
1174
1175    this.elements = makeArray( elem );
1176    this.options = extend( {}, this.options );
1177
1178    if ( typeof options === 'function' ) {
1179      onAlways = options;
1180    } else {
1181      extend( this.options, options );
1182    }
1183
1184    if ( onAlways ) {
1185      this.on( 'always', onAlways );
1186    }
1187
1188    this.getImages();
1189
1190    if ( $ ) {
1191      // add jQuery Deferred object
1192      this.jqDeferred = new $.Deferred();
1193    }
1194
1195    // HACK check async to allow time to bind listeners
1196    var _this = this;
1197    setTimeout( function() {
1198      _this.check();
1199    });
1200  }
1201
1202  ImagesLoaded.prototype = new EventEmitter();
1203
1204  ImagesLoaded.prototype.options = {};
1205
1206  ImagesLoaded.prototype.getImages = function() {
1207    this.images = [];
1208
1209    // filter & find items if we have an item selector
1210    for ( var i=0, len = this.elements.length; i < len; i++ ) {
1211      var elem = this.elements[i];
1212      // filter siblings
1213      if ( elem.nodeName === 'IMG' ) {
1214        this.addImage( elem );
1215      }
1216      // find children
1217      // no non-element nodes, #143
1218      var nodeType = elem.nodeType;
1219      if ( !nodeType || !( nodeType === 1 || nodeType === 9 || nodeType === 11 ) ) {
1220        continue;
1221      }
1222      var childElems = elem.querySelectorAll('img');
1223      // concat childElems to filterFound array
1224      for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
1225        var img = childElems[j];
1226        this.addImage( img );
1227      }
1228    }
1229  };
1230
1231  /**
1232   * @param {Image} img
1233   */
1234  ImagesLoaded.prototype.addImage = function( img ) {
1235    var loadingImage = new LoadingImage( img );
1236    this.images.push( loadingImage );
1237  };
1238
1239  ImagesLoaded.prototype.check = function() {
1240    var _this = this;
1241    var checkedCount = 0;
1242    var length = this.images.length;
1243    this.hasAnyBroken = false;
1244    // complete if no images
1245    if ( !length ) {
1246      this.complete();
1247      return;
1248    }
1249
1250    function onConfirm( image, message ) {
1251      if ( _this.options.debug && hasConsole ) {
1252        console.log( 'confirm', image, message );
1253      }
1254
1255      _this.progress( image );
1256      checkedCount++;
1257      if ( checkedCount === length ) {
1258        _this.complete();
1259      }
1260      return true; // bind once
1261    }
1262
1263    for ( var i=0; i < length; i++ ) {
1264      var loadingImage = this.images[i];
1265      loadingImage.on( 'confirm', onConfirm );
1266      loadingImage.check();
1267    }
1268  };
1269
1270  ImagesLoaded.prototype.progress = function( image ) {
1271    this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
1272    // HACK - Chrome triggers event before object properties have changed. #83
1273    var _this = this;
1274    setTimeout( function() {
1275      _this.emit( 'progress', _this, image );
1276      if ( _this.jqDeferred && _this.jqDeferred.notify ) {
1277        _this.jqDeferred.notify( _this, image );
1278      }
1279    });
1280  };
1281
1282  ImagesLoaded.prototype.complete = function() {
1283    var eventName = this.hasAnyBroken ? 'fail' : 'done';
1284    this.isComplete = true;
1285    var _this = this;
1286    // HACK - another setTimeout so that confirm happens after progress
1287    setTimeout( function() {
1288      _this.emit( eventName, _this );
1289      _this.emit( 'always', _this );
1290      if ( _this.jqDeferred ) {
1291        var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve';
1292        _this.jqDeferred[ jqMethod ]( _this );
1293      }
1294    });
1295  };
1296
1297  // -------------------------- jquery -------------------------- //
1298
1299  if ( $ ) {
1300    $.fn.imagesLoaded = function( options, callback ) {
1301      var instance = new ImagesLoaded( this, options, callback );
1302      return instance.jqDeferred.promise( $(this) );
1303    };
1304  }
1305
1306
1307  // --------------------------  -------------------------- //
1308
1309  function LoadingImage( img ) {
1310    this.img = img;
1311  }
1312
1313  LoadingImage.prototype = new EventEmitter();
1314
1315  LoadingImage.prototype.check = function() {
1316    // first check cached any previous images that have same src
1317    var resource = cache[ this.img.src ] || new Resource( this.img.src );
1318    if ( resource.isConfirmed ) {
1319      this.confirm( resource.isLoaded, 'cached was confirmed' );
1320      return;
1321    }
1322
1323    // If complete is true and browser supports natural sizes,
1324    // try to check for image status manually.
1325    if ( this.img.complete && this.img.naturalWidth !== undefined ) {
1326      // report based on naturalWidth
1327      this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
1328      return;
1329    }
1330
1331    // If none of the checks above matched, simulate loading on detached element.
1332    var _this = this;
1333    resource.on( 'confirm', function( resrc, message ) {
1334      _this.confirm( resrc.isLoaded, message );
1335      return true;
1336    });
1337
1338    resource.check();
1339  };
1340
1341  LoadingImage.prototype.confirm = function( isLoaded, message ) {
1342    this.isLoaded = isLoaded;
1343    this.emit( 'confirm', this, message );
1344  };
1345
1346  // -------------------------- Resource -------------------------- //
1347
1348  // Resource checks each src, only once
1349  // separate class from LoadingImage to prevent memory leaks. See #115
1350
1351  var cache = {};
1352
1353  function Resource( src ) {
1354    this.src = src;
1355    // add to cache
1356    cache[ src ] = this;
1357  }
1358
1359  Resource.prototype = new EventEmitter();
1360
1361  Resource.prototype.check = function() {
1362    // only trigger checking once
1363    if ( this.isChecked ) {
1364      return;
1365    }
1366    // simulate loading on detached element
1367    var proxyImage = new Image();
1368    eventie.bind( proxyImage, 'load', this );
1369    eventie.bind( proxyImage, 'error', this );
1370    proxyImage.src = this.src;
1371    // set flag
1372    this.isChecked = true;
1373  };
1374
1375  // ----- events ----- //
1376
1377  // trigger specified handler for event type
1378  Resource.prototype.handleEvent = function( event ) {
1379    var method = 'on' + event.type;
1380    if ( this[ method ] ) {
1381      this[ method ]( event );
1382    }
1383  };
1384
1385  Resource.prototype.onload = function( event ) {
1386    this.confirm( true, 'onload' );
1387    this.unbindProxyEvents( event );
1388  };
1389
1390  Resource.prototype.onerror = function( event ) {
1391    this.confirm( false, 'onerror' );
1392    this.unbindProxyEvents( event );
1393  };
1394
1395  // ----- confirm ----- //
1396
1397  Resource.prototype.confirm = function( isLoaded, message ) {
1398    this.isConfirmed = true;
1399    this.isLoaded = isLoaded;
1400    this.emit( 'confirm', this, message );
1401  };
1402
1403  Resource.prototype.unbindProxyEvents = function( event ) {
1404    eventie.unbind( event.target, 'load', this );
1405    eventie.unbind( event.target, 'error', this );
1406  };
1407
1408  // -----  ----- //
1409
1410  return ImagesLoaded;
1411
1412});;
1413/*!
1414 * hoverIntent v1.8.0 // 2014.06.29 // jQuery v1.9.1+
1415 * http://cherne.net/brian/resources/jquery.hoverIntent.html
1416 *
1417 * You may use hoverIntent under the terms of the MIT license. Basically that
1418 * means you are free to use hoverIntent as long as this header is left intact.
1419 * Copyright 2007, 2014 Brian Cherne
1420 */
1421 
1422/* hoverIntent is similar to jQuery's built-in "hover" method except that
1423 * instead of firing the handlerIn function immediately, hoverIntent checks
1424 * to see if the user's mouse has slowed down (beneath the sensitivity
1425 * threshold) before firing the event. The handlerOut function is only
1426 * called after a matching handlerIn.
1427 *
1428 * // basic usage ... just like .hover()
1429 * .hoverIntent( handlerIn, handlerOut )
1430 * .hoverIntent( handlerInOut )
1431 *
1432 * // basic usage ... with event delegation!
1433 * .hoverIntent( handlerIn, handlerOut, selector )
1434 * .hoverIntent( handlerInOut, selector )
1435 *
1436 * // using a basic configuration object
1437 * .hoverIntent( config )
1438 *
1439 * @param  handlerIn   function OR configuration object
1440 * @param  handlerOut  function OR selector for delegation OR undefined
1441 * @param  selector    selector OR undefined
1442 * @author Brian Cherne <brian(at)cherne(dot)net>
1443 */
1444(function($) {
1445    $.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
1446
1447        // default configuration values
1448        var cfg = {
1449            interval: 100,
1450            sensitivity: 6,
1451            timeout: 0
1452        };
1453
1454        if ( typeof handlerIn === "object" ) {
1455            cfg = $.extend(cfg, handlerIn );
1456        } else if ($.isFunction(handlerOut)) {
1457            cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
1458        } else {
1459            cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
1460        }
1461
1462        // instantiate variables
1463        // cX, cY = current X and Y position of mouse, updated by mousemove event
1464        // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
1465        var cX, cY, pX, pY;
1466
1467        // A private function for getting mouse position
1468        var track = function(ev) {
1469            cX = ev.pageX;
1470            cY = ev.pageY;
1471        };
1472
1473        // A private function for comparing current and previous mouse position
1474        var compare = function(ev,ob) {
1475            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
1476            // compare mouse positions to see if they've crossed the threshold
1477            if ( Math.sqrt( (pX-cX)*(pX-cX) + (pY-cY)*(pY-cY) ) < cfg.sensitivity ) {
1478                $(ob).off("mousemove.hoverIntent",track);
1479                // set hoverIntent state to true (so mouseOut can be called)
1480                ob.hoverIntent_s = true;
1481                return cfg.over.apply(ob,[ev]);
1482            } else {
1483                // set previous coordinates for next time
1484                pX = cX; pY = cY;
1485                // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
1486                ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
1487            }
1488        };
1489
1490        // A private function for delaying the mouseOut function
1491        var delay = function(ev,ob) {
1492            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
1493            ob.hoverIntent_s = false;
1494            return cfg.out.apply(ob,[ev]);
1495        };
1496
1497        // A private function for handling mouse 'hovering'
1498        var handleHover = function(e) {
1499            // copy objects to be passed into t (required for event object to be passed in IE)
1500            var ev = $.extend({},e);
1501            var ob = this;
1502
1503            // cancel hoverIntent timer if it exists
1504            if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
1505
1506            // if e.type === "mouseenter"
1507            if (e.type === "mouseenter") {
1508                // set "previous" X and Y position based on initial entry point
1509                pX = ev.pageX; pY = ev.pageY;
1510                // update "current" X and Y position based on mousemove
1511                $(ob).on("mousemove.hoverIntent",track);
1512                // start polling interval (self-calling timeout) to compare mouse coordinates over time
1513                if (!ob.hoverIntent_s) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
1514
1515                // else e.type == "mouseleave"
1516            } else {
1517                // unbind expensive mousemove event
1518                $(ob).off("mousemove.hoverIntent",track);
1519                // if hoverIntent state is true, then call the mouseOut function after the specified delay
1520                if (ob.hoverIntent_s) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
1521            }
1522        };
1523
1524        // listen for mouseenter and mouseleave
1525        return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
1526    };
1527})(jQuery);;
1528/*! VelocityJS.org (1.1.0). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */
1529
1530/*************************
1531   Velocity jQuery Shim
1532*************************/
1533
vendor: 9,456 bytes, lines 1534-1877
1534/*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */
1535
1536/* 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. */
1537/* These shimmed functions are only used if jQuery isn't present. If both this shim and jQuery are loaded, Velocity defaults to jQuery proper. */
1538/* Browser support: Using this shim instead of jQuery proper removes support for IE8. */
1539
1540;(function (window) {
1541    /***************
1542         Setup
1543    ***************/
1544
1545    /* If jQuery is already loaded, there's no point in loading this shim. */
1546    if (window.jQuery) {
1547        return;
1548    }
1549
1550    /* jQuery base. */
1551    var $ = function (selector, context) {
1552        return new $.fn.init(selector, context);
1553    };
1554
1555    /********************
1556       Private Methods
1557    ********************/
1558
1559    /* jQuery */
1560    $.isWindow = function (obj) {
1561        /* jshint eqeqeq: false */
1562        return obj != null && obj == obj.window;
1563    };
1564
1565    /* jQuery */
1566    $.type = function (obj) {
1567        if (obj == null) {
1568            return obj + "";
1569        }
1570
1571        return typeof obj === "object" || typeof obj === "function" ?
1572            class2type[toString.call(obj)] || "object" :
1573            typeof obj;
1574    };
1575
1576    /* jQuery */
1577    $.isArray = Array.isArray || function (obj) {
1578        return $.type(obj) === "array";
1579    };
1580
1581    /* jQuery */
1582    function isArraylike (obj) {
1583        var length = obj.length,
1584            type = $.type(obj);
1585
1586        if (type === "function" || $.isWindow(obj)) {
1587            return false;
1588        }
1589
1590        if (obj.nodeType === 1 && length) {
1591            return true;
1592        }
1593
1594        return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj;
1595    }
1596
1597    /***************
1598       $ Methods
1599    ***************/
1600
1601    /* jQuery: Support removed for IE<9. */
1602    $.isPlainObject = function (obj) {
1603        var key;
1604
1605        if (!obj || $.type(obj) !== "object" || obj.nodeType || $.isWindow(obj)) {
1606            return false;
1607        }
1608
1609        try {
1610            if (obj.constructor &&
1611                !hasOwn.call(obj, "constructor") &&
1612                !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
1613                return false;
1614            }
1615        } catch (e) {
1616            return false;
1617        }
1618
1619        for (key in obj) {}
1620
1621        return key === undefined || hasOwn.call(obj, key);
1622    };
1623
1624    /* jQuery */
1625    $.each = function(obj, callback, args) {
1626        var value,
1627            i = 0,
1628            length = obj.length,
1629            isArray = isArraylike(obj);
1630
1631        if (args) {
1632            if (isArray) {
1633                for (; i < length; i++) {
1634                    value = callback.apply(obj[i], args);
1635
1636                    if (value === false) {
1637                        break;
1638                    }
1639                }
1640            } else {
1641                for (i in obj) {
1642                    value = callback.apply(obj[i], args);
1643
1644                    if (value === false) {
1645                        break;
1646                    }
1647                }
1648            }
1649
1650        } else {
1651            if (isArray) {
1652                for (; i < length; i++) {
1653                    value = callback.call(obj[i], i, obj[i]);
1654
1655                    if (value === false) {
1656                        break;
1657                    }
1658                }
1659            } else {
1660                for (i in obj) {
1661                    value = callback.call(obj[i], i, obj[i]);
1662
1663                    if (value === false) {
1664                        break;
1665                    }
1666                }
1667            }
1668        }
1669
1670        return obj;
1671    };
1672
1673    /* Custom */
1674    $.data = function (node, key, value) {
1675        /* $.getData() */
1676        if (value === undefined) {
1677            var id = node[$.expando],
1678                store = id && cache[id];
1679
1680            if (key === undefined) {
1681                return store;
1682            } else if (store) {
1683                if (key in store) {
1684                    return store[key];
1685                }
1686            }
1687        /* $.setData() */
1688        } else if (key !== undefined) {
1689            var id = node[$.expando] || (node[$.expando] = ++$.uuid);
1690
1691            cache[id] = cache[id] || {};
1692            cache[id][key] = value;
1693
1694            return value;
1695        }
1696    };
1697
1698    /* Custom */
1699    $.removeData = function (node, keys) {
1700        var id = node[$.expando],
1701            store = id && cache[id];
1702
1703        if (store) {
1704            $.each(keys, function(_, key) {
1705                delete store[key];
1706            });
1707        }
1708    };
1709
1710    /* jQuery */
1711    $.extend = function () {
1712        var src, copyIsArray, copy, name, options, clone,
1713            target = arguments[0] || {},
1714            i = 1,
1715            length = arguments.length,
1716            deep = false;
1717
1718        if (typeof target === "boolean") {
1719            deep = target;
1720
1721            target = arguments[i] || {};
1722            i++;
1723        }
1724
1725        if (typeof target !== "object" && $.type(target) !== "function") {
1726            target = {};
1727        }
1728
1729        if (i === length) {
1730            target = this;
1731            i--;
1732        }
1733
1734        for (; i < length; i++) {
1735            if ((options = arguments[i]) != null) {
1736                for (name in options) {
1737                    src = target[name];
1738                    copy = options[name];
1739
1740                    if (target === copy) {
1741                        continue;
1742                    }
1743
1744                    if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
1745                        if (copyIsArray) {
1746                            copyIsArray = false;
1747                            clone = src && $.isArray(src) ? src : [];
1748
1749                        } else {
1750                            clone = src && $.isPlainObject(src) ? src : {};
1751                        }
1752
1753                        target[name] = $.extend(deep, clone, copy);
1754
1755                    } else if (copy !== undefined) {
1756                        target[name] = copy;
1757                    }
1758                }
1759            }
1760        }
1761
1762        return target;
1763    };
1764
1765    /* jQuery 1.4.3 */
1766    $.queue = function (elem, type, data) {
1767        function $makeArray (arr, results) {
1768            var ret = results || [];
1769
1770            if (arr != null) {
1771                if (isArraylike(Object(arr))) {
1772                    /* $.merge */
1773                    (function(first, second) {
1774                        var len = +second.length,
1775                            j = 0,
1776                            i = first.length;
1777
1778                        while (j < len) {
1779                            first[i++] = second[j++];
1780                        }
1781
1782                        if (len !== len) {
1783                            while (second[j] !== undefined) {
1784                                first[i++] = second[j++];
1785                            }
1786                        }
1787
1788                        first.length = i;
1789
1790                        return first;
1791                    })(ret, typeof arr === "string" ? [arr] : arr);
1792                } else {
1793                    [].push.call(ret, arr);
1794                }
1795            }
1796
1797            return ret;
1798        }
1799
1800        if (!elem) {
1801            return;
1802        }
1803
1804        type = (type || "fx") + "queue";
1805
1806        var q = $.data(elem, type);
1807
1808        if (!data) {
1809            return q || [];
1810        }
1811
1812        if (!q || $.isArray(data)) {
1813            q = $.data(elem, type, $makeArray(data));
1814        } else {
1815            q.push(data);
1816        }
1817
1818        return q;
1819    };
1820
1821    /* jQuery 1.4.3 */
1822    $.dequeue = function (elems, type) {
1823        /* Custom: Embed element iteration. */
1824        $.each(elems.nodeType ? [ elems ] : elems, function(i, elem) {
1825            type = type || "fx";
1826
1827            var queue = $.queue(elem, type),
1828                fn = queue.shift();
1829
1830            if (fn === "inprogress") {
1831                fn = queue.shift();
1832            }
1833
1834            if (fn) {
1835                if (type === "fx") {
1836                    queue.unshift("inprogress");
1837                }
1838
1839                fn.call(elem, function() {
1840                    $.dequeue(elem, type);
1841                });
1842            }
1843        });
1844    };
1845
1846    /******************
1847       $.fn Methods
1848    ******************/
1849
1850    /* jQuery */
1851    $.fn = $.prototype = {
1852        init: function (selector) {
1853            /* Just return the element wrapped inside an array; don't proceed with the actual jQuery node wrapping process. */
1854            if (selector.nodeType) {
1855                this[0] = selector;
1856
1857                return this;
1858            } else {
1859                throw new Error("Not a DOM node.");
1860            }
1861        },
1862
1863        offset: function () {
1864            /* jQuery altered code: Dropped disconnected DOM node checking. */
1865            var box = this[0].getBoundingClientRect ? this[0].getBoundingClientRect() : { top: 0, left: 0 };
1866
1867            return {
1868                top: box.top + (window.pageYOffset || document.scrollTop  || 0)  - (document.clientTop  || 0),
1869                left: box.left + (window.pageXOffset || document.scrollLeft  || 0) - (document.clientLeft || 0)
1870            };
1871        },
1872
1873        position: function () {
1874            /* jQuery */
1875            function offsetParent() {
1876                var offsetParent = this.offsetParent || document;
1877
1878                while (offsetParent && (!offsetParent.nodeType.toLowerCase === "html" && offsetParent.style.position === "static")) {
1879                    offsetParent = offsetParent.offsetParent;
1880                }
1881
1882                return offsetParent || document;
1883            }
1884
1885            /* Zepto */
1886            var elem = this[0],
1887                offsetParent = offsetParent.apply(elem),
1888                offset = this.offset(),
1889                parentOffset = /^(?:body|html)$/i.test(offsetParent.nodeName) ? { top: 0, left: 0 } : $(offsetParent).offset()
1890
1891            offset.top -= parseFloat(elem.style.marginTop) || 0;
1892            offset.left -= parseFloat(elem.style.marginLeft) || 0;
1893
1894            if (offsetParent.style) {
1895                parentOffset.top += parseFloat(offsetParent.style.borderTopWidth) || 0
1896                parentOffset.left += parseFloat(offsetParent.style.borderLeftWidth) || 0
1897            }
1898
1899            return {
1900                top: offset.top - parentOffset.top,
1901                left: offset.left - parentOffset.left
1902            };
1903        }
1904    };
1905
1906    /**********************
1907       Private Variables
1908    **********************/
1909
1910    /* For $.data() */
1911    var cache = {};
1912    $.expando = "velocity" + (new Date().getTime());
1913    $.uuid = 0;
1914
1915    /* For $.queue() */
1916    var class2type = {},
1917        hasOwn = class2type.hasOwnProperty,
1918        toString = class2type.toString;
1919
1920    var types = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
1921    for (var i = 0; i < types.length; i++) {
1922        class2type["[object " + types[i] + "]"] = types[i].toLowerCase();
1923    }
1924
1925    /* Makes $(node) possible, without having to call init. */
1926    $.fn.init.prototype = $.fn;
1927
1928    /* Globalize Velocity onto the window, and assign its Utilities property. */
1929    window.Velocity = { Utilities: $ };
1930})(window);
1931
1932/******************
1933    Velocity.js
1934******************/
1935
1936;(function (factory) {
1937    /* CommonJS module. */
1938    if (typeof module === "object" && typeof module.exports === "object") {
1939        module.exports = factory();
1940    /* AMD module. */
1941    } else if (typeof define === "function" && define.amd) {
1942        define(factory);
1943    /* Browser globals. */
1944    } else {
1945        factory();
1946    }
1947}(function() {
1948return function (global, window, document, undefined) {
1949
1950    /***************
1951        Summary
1952    ***************/
1953
1954    /*
1955    - CSS: CSS stack that works independently from the rest of Velocity.
1956    - animate(): Core animation method that iterates over the targeted elements and queues the incoming call onto each element individually.
1957      - Pre-Queueing: Prepare the element for animation by instantiating its data cache and processing the call's options.
1958      - Queueing: The logic that runs once the call has reached its point of execution in the element's $.queue() stack.
1959                  Most logic is placed here to avoid risking it becoming stale (if the element's properties have changed).
1960      - Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container.
1961    - tick(): The single requestAnimationFrame loop responsible for tweening all in-progress calls.
1962    - completeCall(): Handles the cleanup process for each Velocity call.
1963    */
1964
1965    /*********************
1966       Helper Functions
1967    *********************/
1968
1969    /* IE detection. Gist: https://gist.github.com/julianshapiro/9098609 */
1970    var IE = (function() {
1971        if (document.documentMode) {
1972            return document.documentMode;
1973        } else {
1974            for (var i = 7; i > 4; i--) {
1975                var div = document.createElement("div");
1976
1977                div.innerHTML = "<!--[if IE " + i + "]><span></span><![endif]-->";
1978
1979                if (div.getElementsByTagName("span").length) {
1980                    div = null;
1981
1982                    return i;
1983                }
1984            }
1985        }
1986
1987        return undefined;
1988    })();
1989
1990    /* rAF shim. Gist: https://gist.github.com/julianshapiro/9497513 */
1991    var rAFShim = (function() {
1992        var timeLast = 0;
1993
1994        return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
1995            var timeCurrent = (new Date()).getTime(),
1996                timeDelta;
1997
1998            /* Dynamically set delay on a per-tick basis to match 60fps. */
1999            /* Technique by Erik Moller. MIT license: https://gist.github.com/paulirish/1579671 */
2000            timeDelta = Math.max(0, 16 - (timeCurrent - timeLast));
2001            timeLast = timeCurrent + timeDelta;
2002
2003            return setTimeout(function() { callback(timeCurrent + timeDelta); }, timeDelta);
2004        };
2005    })();
2006
2007    /* Array compacting. Copyright Lo-Dash. MIT License: https://github.com/lodash/lodash/blob/master/LICENSE.txt */
2008    function compactSparseArray (array) {
2009        var index = -1,
2010            length = array ? array.length : 0,
2011            result = [];
2012
2013        while (++index < length) {
2014            var value = array[index];
2015
2016            if (value) {
2017                result.push(value);
2018            }
2019        }
2020
2021        return result;
2022    }
2023
2024    function sanitizeElements (elements) {
2025        /* Unwrap jQuery/Zepto objects. */
2026        if (Type.isWrapped(elements)) {
2027            elements = [].slice.call(elements);
2028        /* Wrap a single element in an array so that $.each() can iterate with the element instead of its node's children. */
2029        } else if (Type.isNode(elements)) {
2030            elements = [ elements ];
2031        }
2032
2033        return elements;
2034    }
2035
2036    var Type = {
2037        isString: function (variable) {
2038            return (typeof variable === "string");
2039        },
2040        isArray: Array.isArray || function (variable) {
2041            return Object.prototype.toString.call(variable) === "[object Array]";
2042        },
2043        isFunction: function (variable) {
2044            return Object.prototype.toString.call(variable) === "[object Function]";
2045        },
2046        isNode: function (variable) {
2047            return variable && variable.nodeType;
2048        },
2049        /* Copyright Martin Bohm. MIT License: https://gist.github.com/Tomalak/818a78a226a0738eaade */
2050        isNodeList: function (variable) {
2051            return typeof variable === "object" &&
2052                /^\[object (HTMLCollection|NodeList|Object)\]$/.test(Object.prototype.toString.call(variable)) &&
2053                variable.length !== undefined &&
2054                (variable.length === 0 || (typeof variable[0] === "object" && variable[0].nodeType > 0));
2055        },
2056        /* Determine if variable is a wrapped jQuery or Zepto element. */
2057        isWrapped: function (variable) {
2058            return variable && (variable.jquery || (window.Zepto && window.Zepto.zepto.isZ(variable)));
2059        },
2060        isSVG: function (variable) {
2061            return window.SVGElement && (variable instanceof window.SVGElement);
2062        },
2063        isEmptyObject: function (variable) {
2064            for (var name in variable) {
2065                return false;
vendor: 7,701 bytes, lines 2066-2232
2066            }
2067
2068            return true;
2069        }
2070    };
2071
2072    /*****************
2073       Dependencies
2074    *****************/
2075
2076    var $,
2077        isJQuery = false;
2078
2079    if (global.fn && global.fn.jquery) {
2080        $ = global;
2081        isJQuery = true;
2082    } else {
2083        $ = window.Velocity.Utilities;
2084    }
2085
2086    if (IE <= 8 && !isJQuery) {
2087        throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity.");
2088    } else if (IE <= 7) {
2089        /* Revert to jQuery's $.animate(), and lose Velocity's extra features. */
2090        jQuery.fn.velocity = jQuery.fn.animate;
2091
2092        /* Now that $.fn.velocity is aliased, abort this Velocity declaration. */
2093        return;
2094    }
2095
2096    /*****************
2097        Constants
2098    *****************/
2099
2100    var DURATION_DEFAULT = 400,
2101        EASING_DEFAULT = "swing";
2102
2103    /*************
2104        State
2105    *************/
2106
2107    /* Note: The global object also doubles as a publicly-accessible data store for the purposes of unit testing. */
2108    /* Note: Alias the lowercase and uppercase variants of "velocity" to minimize user confusion due to the lowercase nature of the $.fn extension. */
2109    var Velocity = {
2110        /* Container for page-wide Velocity state data. */
2111        State: {
2112            /* Detect mobile devices to determine if mobileHA should be turned on. */
2113            isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
2114            /* The mobileHA option's behavior changes on older Android devices (Gingerbread, versions 2.3.3-2.3.7). */
2115            isAndroid: /Android/i.test(navigator.userAgent),
2116            isGingerbread: /Android 2\.3\.[3-7]/i.test(navigator.userAgent),
2117            isChrome: window.chrome,
2118            isFirefox: /Firefox/i.test(navigator.userAgent),
2119            /* Create a cached element for re-use when checking for CSS property prefixes. */
2120            prefixElement: document.createElement("div"),
2121            /* Cache every prefix match to avoid repeating lookups. */
2122            prefixMatches: {},
2123            /* Cache the anchor used for animating window scrolling. */
2124            scrollAnchor: null,
2125            /* Cache the property names associated with the scroll anchor. */
2126            scrollPropertyLeft: null,
2127            scrollPropertyTop: null,
2128            /* Keep track of whether our RAF tick is running. */
2129            isTicking: false,
2130            /* Container for every in-progress call to Velocity. */
2131            calls: []
2132        },
2133        /* Velocity's custom CSS stack. Made global for unit testing. */
2134        CSS: { /* Defined below. */ },
2135        /* Defined by Velocity's optional jQuery shim. */
2136        Utilities: $,
2137        /* Container for the user's custom animation redirects that are referenced by name in place of a properties map object. */
2138        Redirects: { /* Manually registered by the user. */ },
2139        Easings: { /* Defined below. */ },
2140        /* Attempt to use ES6 Promises by default. Users can override this with a third-party promises library. */
2141        Promise: window.Promise,
2142        /* Page-wide option defaults, which can be overriden by the user. */
2143        defaults: {
2144            queue: "",
2145            duration: DURATION_DEFAULT,
2146            easing: EASING_DEFAULT,
2147            begin: undefined,
2148            complete: undefined,
2149            progress: undefined,
2150            display: undefined,
2151            visibility: undefined,
2152            loop: false,
2153            delay: false,
2154            mobileHA: true,
2155            /* Set to false to prevent property values from being cached between consecutive Velocity-initiated chain calls. */
2156            _cacheValues: true
2157        },
2158        /* A design goal of Velocity is to cache data wherever possible in order to avoid DOM requerying.
2159           Accordingly, each element has a data cache instantiated on it. */
2160        init: function (element) {
2161            $.data(element, "velocity", {
2162                /* Store whether this is an SVG element, since its properties are retrieved and updated differently than standard HTML elements. */
2163                isSVG: Type.isSVG(element),
2164                /* Keep track of whether the element is currently being animated by Velocity.
2165                   This is used to ensure that property values are not transferred between non-consecutive (stale) calls. */
2166                isAnimating: false,
2167                /* A reference to the element's live computedStyle object. Learn more here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */
2168                computedStyle: null,
2169                /* Tween data is cached for each animation on the element so that data can be passed across calls --
2170                   in particular, end values are used as subsequent start values in consecutive Velocity calls. */
2171                tweensContainer: null,
2172                /* The full root property values of each CSS hook being animated on this element are cached so that:
2173                   1) Concurrently-animating hooks sharing the same root can have their root values' merged into one while tweening.
2174                   2) Post-hook-injection root values can be transferred over to consecutively chained Velocity calls as starting root values. */
2175                rootPropertyValueCache: {},
2176                /* A cache for transform updates, which must be manually flushed via CSS.flushTransformCache(). */
2177                transformCache: {}
2178            });
2179        },
2180        /* A parallel to jQuery's $.css(), used for getting/setting Velocity's hooked CSS properties. */
2181        hook: null, /* Defined below. */
2182        /* Velocity-wide animation time remapping for testing purposes. */
2183        mock: false,
2184        version: { major: 1, minor: 1, patch: 0 },
2185        /* Set to 1 or 2 (most verbose) to output debug info to console. */
2186        debug: false
2187    };
2188
2189    /* Retrieve the appropriate scroll anchor and property name for the browser: https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY */
2190    if (window.pageYOffset !== undefined) {
2191        Velocity.State.scrollAnchor = window;
2192        Velocity.State.scrollPropertyLeft = "pageXOffset";
2193        Velocity.State.scrollPropertyTop = "pageYOffset";
2194    } else {
2195        Velocity.State.scrollAnchor = document.documentElement || document.body.parentNode || document.body;
2196        Velocity.State.scrollPropertyLeft = "scrollLeft";
2197        Velocity.State.scrollPropertyTop = "scrollTop";
2198    }
2199
2200    /* Shorthand alias for jQuery's $.data() utility. */
2201    function Data (element) {
2202        /* Hardcode a reference to the plugin name. */
2203        var response = $.data(element, "velocity");
2204
2205        /* jQuery <=1.4.2 returns null instead of undefined when no match is found. We normalize this behavior. */
2206        return response === null ? undefined : response;
2207    };
2208
2209    /**************
2210        Easing
2211    **************/
2212
2213    /* Step easing generator. */
2214    function generateStep (steps) {
2215        return function (p) {
2216            return Math.round(p * steps) * (1 / steps);
2217        };
2218    }
2219
2220    /* Bezier curve function generator. Copyright Gaetan Renaudeau. MIT License: http://en.wikipedia.org/wiki/MIT_License */
2221    function generateBezier (mX1, mY1, mX2, mY2) {
2222        var NEWTON_ITERATIONS = 4,
2223            NEWTON_MIN_SLOPE = 0.001,
2224            SUBDIVISION_PRECISION = 0.0000001,
2225            SUBDIVISION_MAX_ITERATIONS = 10,
2226            kSplineTableSize = 11,
2227            kSampleStepSize = 1.0 / (kSplineTableSize - 1.0),
2228            float32ArraySupported = "Float32Array" in window;
2229
2230        /* Must contain four arguments. */
2231        if (arguments.length !== 4) {
2232            return false;
2233        }
2234
2235        /* Arguments must be numbers. */
2236        for (var i = 0; i < 4; ++i) {
2237            if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) {
2238                return false;
2239            }
2240        }
2241
2242        /* X values must be in the [0, 1] range. */
2243        mX1 = Math.min(mX1, 1);
2244        mX2 = Math.min(mX2, 1);
2245        mX1 = Math.max(mX1, 0);
2246        mX2 = Math.max(mX2, 0);
2247
2248        var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
2249
2250        function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
2251        function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
2252        function C (aA1)      { return 3.0 * aA1; }
2253
2254        function calcBezier (aT, aA1, aA2) {
2255            return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
2256        }
2257
2258        function getSlope (aT, aA1, aA2) {
2259            return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
2260        }
2261
2262        function newtonRaphsonIterate (aX, aGuessT) {
2263            for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
2264                var currentSlope = getSlope(aGuessT, mX1, mX2);
2265
2266                if (currentSlope === 0.0) return aGuessT;
2267
2268                var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
2269                aGuessT -= currentX / currentSlope;
2270            }
2271
2272            return aGuessT;
2273        }
2274
2275        function calcSampleValues () {
2276            for (var i = 0; i < kSplineTableSize; ++i) {
2277                mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
2278            }
2279        }
2280
2281        function binarySubdivide (aX, aA, aB) {
2282            var currentX, currentT, i = 0;
2283
2284            do {
2285                currentT = aA + (aB - aA) / 2.0;
2286                currentX = calcBezier(currentT, mX1, mX2) - aX;
2287                if (currentX > 0.0) {
2288                  aB = currentT;
2289                } else {
2290                  aA = currentT;
2291                }
2292            } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
2293
2294            return currentT;
2295        }
2296
2297        function getTForX (aX) {
2298            var intervalStart = 0.0,
2299                currentSample = 1,
2300                lastSample = kSplineTableSize - 1;
2301
2302            for (; currentSample != lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
2303                intervalStart += kSampleStepSize;
2304            }
2305
2306            --currentSample;
2307
2308            var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample+1] - mSampleValues[currentSample]),
2309                guessForT = intervalStart + dist * kSampleStepSize,
2310                initialSlope = getSlope(guessForT, mX1, mX2);
2311
2312            if (initialSlope >= NEWTON_MIN_SLOPE) {
2313                return newtonRaphsonIterate(aX, guessForT);
2314            } else if (initialSlope == 0.0) {
2315                return guessForT;
2316            } else {
2317                return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize);
2318            }
2319        }
2320
2321        var _precomputed = false;
2322
2323        function precompute() {
2324            _precomputed = true;
2325            if (mX1 != mY1 || mX2 != mY2) calcSampleValues();
2326        }
2327
2328        var f = function (aX) {
2329            if (!_precomputed) precompute();
2330            if (mX1 === mY1 && mX2 === mY2) return aX;
2331            if (aX === 0) return 0;
2332            if (aX === 1) return 1;
2333
2334            return calcBezier(getTForX(aX), mY1, mY2);
2335        };
2336
2337        f.getControlPoints = function() { return [{ x: mX1, y: mY1 }, { x: mX2, y: mY2 }]; };
2338
2339        var str = "generateBezier(" + [mX1, mY1, mX2, mY2] + ")";
2340        f.toString = function () { return str; };
2341
2342        return f;
2343    }
2344
2345    /* Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */
2346    /* 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
2347       then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */
2348    var generateSpringRK4 = (function () {
2349        function springAccelerationForState (state) {
2350            return (-state.tension * state.x) - (state.friction * state.v);
2351        }
2352
2353        function springEvaluateStateWithDerivative (initialState, dt, derivative) {
2354            var state = {
2355                x: initialState.x + derivative.dx * dt,
2356                v: initialState.v + derivative.dv * dt,
2357                tension: initialState.tension,
2358                friction: initialState.friction
2359            };
2360
2361            return { dx: state.v, dv: springAccelerationForState(state) };
2362        }
2363
2364        function springIntegrateState (state, dt) {
2365            var a = {
2366                    dx: state.v,
2367                    dv: springAccelerationForState(state)
2368                },
2369                b = springEvaluateStateWithDerivative(state, dt * 0.5, a),
2370                c = springEvaluateStateWithDerivative(state, dt * 0.5, b),
2371                d = springEvaluateStateWithDerivative(state, dt, c),
2372                dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),
2373                dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);
2374
2375            state.x = state.x + dxdt * dt;
2376            state.v = state.v + dvdt * dt;
2377
2378            return state;
2379        }
2380
2381        return function springRK4Factory (tension, friction, duration) {
2382
2383            var initState = {
2384                    x: -1,
2385                    v: 0,
2386                    tension: null,
2387                    friction: null
2388                },
2389                path = [0],
vendor: 9,606 bytes, lines 2390-2578
2390                time_lapsed = 0,
2391                tolerance = 1 / 10000,
2392                DT = 16 / 1000,
2393                have_duration, dt, last_state;
2394
2395            tension = parseFloat(tension) || 500;
2396            friction = parseFloat(friction) || 20;
2397            duration = duration || null;
2398
2399            initState.tension = tension;
2400            initState.friction = friction;
2401
2402            have_duration = duration !== null;
2403
2404            /* Calculate the actual time it takes for this animation to complete with the provided conditions. */
2405            if (have_duration) {
2406                /* Run the simulation without a duration. */
2407                time_lapsed = springRK4Factory(tension, friction);
2408                /* Compute the adjusted time delta. */
2409                dt = time_lapsed / duration * DT;
2410            } else {
2411                dt = DT;
2412            }
2413
2414            while (true) {
2415                /* Next/step function .*/
2416                last_state = springIntegrateState(last_state || initState, dt);
2417                /* Store the position. */
2418                path.push(1 + last_state.x);
2419                time_lapsed += 16;
2420                /* If the change threshold is reached, break. */
2421                if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {
2422                    break;
2423                }
2424            }
2425
2426            /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the
2427               computed path and returns a snapshot of the position according to a given percentComplete. */
2428            return !have_duration ? time_lapsed : function(percentComplete) { return path[ (percentComplete * (path.length - 1)) | 0 ]; };
2429        };
2430    }());
2431
2432    /* jQuery easings. */
2433    Velocity.Easings = {
2434        linear: function(p) { return p; },
2435        swing: function(p) { return 0.5 - Math.cos( p * Math.PI ) / 2 },
2436        /* Bonus "spring" easing, which is a less exaggerated version of easeInOutElastic. */
2437        spring: function(p) { return 1 - (Math.cos(p * 4.5 * Math.PI) * Math.exp(-p * 6)); }
2438    };
2439
2440    /* CSS3 and Robert Penner easings. */
2441    $.each(
2442        [
2443            [ "ease", [ 0.25, 0.1, 0.25, 1.0 ] ],
2444            [ "ease-in", [ 0.42, 0.0, 1.00, 1.0 ] ],
2445            [ "ease-out", [ 0.00, 0.0, 0.58, 1.0 ] ],
2446            [ "ease-in-out", [ 0.42, 0.0, 0.58, 1.0 ] ],
2447            [ "easeInSine", [ 0.47, 0, 0.745, 0.715 ] ],
2448            [ "easeOutSine", [ 0.39, 0.575, 0.565, 1 ] ],
2449            [ "easeInOutSine", [ 0.445, 0.05, 0.55, 0.95 ] ],
2450            [ "easeInQuad", [ 0.55, 0.085, 0.68, 0.53 ] ],
2451            [ "easeOutQuad", [ 0.25, 0.46, 0.45, 0.94 ] ],
2452            [ "easeInOutQuad", [ 0.455, 0.03, 0.515, 0.955 ] ],
2453            [ "easeInCubic", [ 0.55, 0.055, 0.675, 0.19 ] ],
2454            [ "easeOutCubic", [ 0.215, 0.61, 0.355, 1 ] ],
2455            [ "easeInOutCubic", [ 0.645, 0.045, 0.355, 1 ] ],
2456            [ "easeInQuart", [ 0.895, 0.03, 0.685, 0.22 ] ],
2457            [ "easeOutQuart", [ 0.165, 0.84, 0.44, 1 ] ],
2458            [ "easeInOutQuart", [ 0.77, 0, 0.175, 1 ] ],
2459            [ "easeInQuint", [ 0.755, 0.05, 0.855, 0.06 ] ],
2460            [ "easeOutQuint", [ 0.23, 1, 0.32, 1 ] ],
2461            [ "easeInOutQuint", [ 0.86, 0, 0.07, 1 ] ],
2462            [ "easeInExpo", [ 0.95, 0.05, 0.795, 0.035 ] ],
2463            [ "easeOutExpo", [ 0.19, 1, 0.22, 1 ] ],
2464            [ "easeInOutExpo", [ 1, 0, 0, 1 ] ],
2465            [ "easeInCirc", [ 0.6, 0.04, 0.98, 0.335 ] ],
2466            [ "easeOutCirc", [ 0.075, 0.82, 0.165, 1 ] ],
2467            [ "easeInOutCirc", [ 0.785, 0.135, 0.15, 0.86 ] ]
2468        ], function(i, easingArray) {
2469            Velocity.Easings[easingArray[0]] = generateBezier.apply(null, easingArray[1]);
2470        });
2471
2472    /* Determine the appropriate easing type given an easing input. */
2473    function getEasing(value, duration) {
2474        var easing = value;
2475
2476        /* The easing option can either be a string that references a pre-registered easing,
2477           or it can be a two-/four-item array of integers to be converted into a bezier/spring function. */
2478        if (Type.isString(value)) {
2479            /* Ensure that the easing has been assigned to jQuery's Velocity.Easings object. */
2480            if (!Velocity.Easings[value]) {
2481                easing = false;
2482            }
2483        } else if (Type.isArray(value) && value.length === 1) {
2484            easing = generateStep.apply(null, value);
2485        } else if (Type.isArray(value) && value.length === 2) {
2486            /* springRK4 must be passed the animation's duration. */
2487            /* Note: If the springRK4 array contains non-numbers, generateSpringRK4() returns an easing
2488               function generated with default tension and friction values. */
2489            easing = generateSpringRK4.apply(null, value.concat([ duration ]));
2490        } else if (Type.isArray(value) && value.length === 4) {
2491            /* Note: If the bezier array contains non-numbers, generateBezier() returns false. */
2492            easing = generateBezier.apply(null, value);
2493        } else {
2494            easing = false;
2495        }
2496
2497        /* Revert to the Velocity-wide default easing type, or fall back to "swing" (which is also jQuery's default)
2498           if the Velocity-wide default has been incorrectly modified. */
2499        if (easing === false) {
2500            if (Velocity.Easings[Velocity.defaults.easing]) {
2501                easing = Velocity.defaults.easing;
2502            } else {
2503                easing = EASING_DEFAULT;
2504            }
2505        }
2506
2507        return easing;
2508    }
2509
2510    /*****************
2511        CSS Stack
2512    *****************/
2513
2514    /* The CSS object is a highly condensed and performant CSS stack that fully replaces jQuery's.
2515       It handles the validation, getting, and setting of both standard CSS properties and CSS property hooks. */
2516    /* Note: A "CSS" shorthand is aliased so that our code is easier to read. */
2517    var CSS = Velocity.CSS = {
2518
2519        /*************
2520            RegEx
2521        *************/
2522
2523        RegEx: {
2524            isHex: /^#([A-f\d]{3}){1,2}$/i,
2525            /* 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". */
2526            valueUnwrap: /^[A-z]+\((.*)\)$/i,
2527            wrappedValueAlreadyExtracted: /[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/,
2528            /* 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" ]. */
2529            valueSplit: /([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/ig
2530        },
2531
2532        /************
2533            Lists
2534        ************/
2535
2536        Lists: {
2537            colors: [ "fill", "stroke", "stopColor", "color", "backgroundColor", "borderColor", "borderTopColor", "borderRightColor", "borderBottomColor", "borderLeftColor", "outlineColor" ],
2538            transformsBase: [ "translateX", "translateY", "scale", "scaleX", "scaleY", "skewX", "skewY", "rotateZ" ],
2539            transforms3D: [ "transformPerspective", "translateZ", "scaleZ", "rotateX", "rotateY" ]
2540        },
2541
2542        /************
2543            Hooks
2544        ************/
2545
2546        /* Hooks allow a subproperty (e.g. "boxShadowBlur") of a compound-value CSS property
2547           (e.g. "boxShadow: X Y Blur Spread Color") to be animated as if it were a discrete property. */
2548        /* Note: Beyond enabling fine-grained property animation, hooking is necessary since Velocity only
2549           tweens properties with single numeric values; unlike CSS transitions, Velocity does not interpolate compound-values. */
2550        Hooks: {
2551            /********************
2552                Registration
2553            ********************/
2554
2555            /* Templates are a concise way of indicating which subproperties must be individually registered for each compound-value CSS property. */
2556            /* Each template consists of the compound-value's base name, its constituent subproperty names, and those subproperties' default values. */
2557            templates: {
2558                "textShadow": [ "Color X Y Blur", "black 0px 0px 0px" ],
2559                /* Todo: Add support for inset boxShadows. (webkit places it last whereas IE places it first.) */
2560                "boxShadow": [ "Color X Y Blur Spread", "black 0px 0px 0px 0px" ],
2561                "clip": [ "Top Right Bottom Left", "0px 0px 0px 0px" ],
2562                "backgroundPosition": [ "X Y", "0% 0%" ],
2563                "transformOrigin": [ "X Y Z", "50% 50% 0px" ],
2564                "perspectiveOrigin": [ "X Y", "50% 50%" ]
2565            },
2566
2567            /* A "registered" hook is one that has been converted from its template form into a live,
2568               tweenable property. It contains data to associate it with its root property. */
2569            registered: {
2570                /* Note: A registered hook looks like this ==> textShadowBlur: [ "textShadow", 3 ],
2571                   which consists of the subproperty's name, the associated root property's name,
2572                   and the subproperty's position in the root's value. */
2573            },
2574            /* Convert the templates into individual hooks then append them to the registered object above. */
2575            register: function () {
2576                /* Color hooks registration: Colors are defaulted to white -- as opposed to black -- since colors that are
2577                   currently set to "transparent" default to their respective template below when color-animated,
2578                   and white is typically a closer match to transparent than black 
2578is. An exception is made for text ("color"),
2579                   which is almost always set closer to black than white. */
2580                for (var i = 0; i < CSS.Lists.colors.length; i++) {
2581                    var rgbComponents = (CSS.Lists.colors[i] === "color") ? "0 0 0 1" : "255 255 255 1";
2582                    CSS.Hooks.templates[CSS.Lists.colors[i]] = [ "Red Green Blue Alpha", rgbComponents ];
2583                }
2584
2585                var rootProperty,
2586                    hookTemplate,
2587                    hookNames;
2588
2589                /* In IE, color values inside compound-value properties are positioned at the end the value instead of at the beginning.
2590                   Thus, we re-arrange the templates accordingly. */
2591                if (IE) {
2592                    for (rootProperty in CSS.Hooks.templates) {
2593                        hookTemplate = CSS.Hooks.templates[rootProperty];
2594                        hookNames = hookTemplate[0].split(" ");
2595
2596                        var defaultValues = hookTemplate[1].match(CSS.RegEx.valueSplit);
2597
2598                        if (hookNames[0] === "Color") {
2599                            /* Reposition both the hook's name and its default value to the end of their respective strings. */
2600                            hookNames.push(hookNames.shift());
2601                            defaultValues.push(defaultValues.shift());
2602
2603                            /* Replace the existing template for the hook's root property. */
2604                            CSS.Hooks.templates[rootProperty] = [ hookNames.join(" "), defaultValues.join(" ") ];
2605                        }
2606                    }
2607                }
2608
2609                /* Hook registration. */
2610                for (rootProperty in CSS.Hooks.templates) {
2611                    hookTemplate = CSS.Hooks.templates[rootProperty];
2612                    hookNames = hookTemplate[0].split(" ");
2613
2614                    for (var i in hookNames) {
2615                        var fullHookName = rootProperty + hookNames[i],
2616                            hookPosition = i;
2617
2618                        /* For each hook, register its full name (e.g. textShadowBlur) with its root property (e.g. textShadow)
2619                           and the hook's position in its template's default value string. */
2620                        CSS.Hooks.registered[fullHookName] = [ rootProperty, hookPosition ];
2621                    }
2622                }
2623            },
2624
2625            /*****************************
2626               Injection and Extraction
2627            *****************************/
2628
2629            /* Look up the root property associated with the hook (e.g. return "textShadow" for "textShadowBlur"). */
2630            /* 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. */
2631            getRoot: function (property) {
2632                var hookData = CSS.Hooks.registered[property];
2633
2634                if (hookData) {
2635                    return hookData[0];
2636                } else {
2637                    /* If there was no hook match, return the property name untouched. */
2638                    return property;
2639                }
2640            },
2641            /* Convert any rootPropertyValue, null or otherwise, into a space-delimited list of hook values so that
2642               the targeted hook can be injected or extracted at its standard position. */
2643            cleanRootPropertyValue: function(rootProperty, rootPropertyValue) {
2644                /* If the rootPropertyValue is wrapped with "rgb()", "clip()", etc., remove the wrapping to normalize the value before manipulation. */
2645                if (CSS.RegEx.valueUnwrap.test(rootPropertyValue)) {
2646                    rootPropertyValue = rootPropertyValue.match(CSS.RegEx.valueUnwrap)[1];
2647                }
2648
2649                /* If rootPropertyValue is a CSS null-value (from which there's inherently no hook value to extract),
2650                   default to the root's default value as defined in CSS.Hooks.templates. */
2651                /* Note: CSS null-values include "none", "auto", and "transparent". They must be converted into their
2652                   zero-values (e.g. textShadow: "none" ==> textShadow: "0px 0px 0px black") for hook manipulation to proceed. */
2653                if (CSS.Values.isCSSNullValue(rootPropertyValue)) {
2654                    rootPropertyValue = CSS.Hooks.templates[rootProperty][1];
2655                }
2656
2657                return rootPropertyValue;
2658            },
2659            /* Extracted the hook's value from its root property's value. This is used to get the starting value of an animating hook. */
2660            extractValue: function (fullHookName, rootPropertyValue) {
2661                var hookData = CSS.Hooks.registered[fullHookName];
2662
2663                if (hookData) {
2664                    var hookRoot = hookData[0],
2665                        hookPosition = hookData[1];
2666
2667                    rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue);
2668
2669                    /* Split rootPropertyValue into its constituent hook values then grab the desired hook at its standard position. */
2670                    return rootPropertyValue.toString().match(CSS.RegEx.valueSplit)[hookPosition];
2671                } else {
2672                    /* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */
2673                    return rootPropertyValue;
2674                }
2675            },
2676            /* Inject the hook's value into its root property's value. This is used to piece back together the root property
2677               once Velocity has updated one of its individually hooked values through tweening. */
2678            injectValue: function (fullHookName, hookValue, rootPropertyValue) {
2679                var hookData = CSS.Hooks.registered[fullHookName];
2680
2681                if (hookData) {
2682                    var hookRoot = hookData[0],
2683                        hookPosition = hookData[1],
2684                        rootPropertyValueParts,
2685                        rootPropertyValueUpdated;
2686
2687                    rootPropertyValue = CSS.Hooks.cleanRootPropertyValue(hookRoot, rootPropertyValue);
2688
2689                    /* Split rootPropertyValue into its individual hook values, replace the targeted value with hookValue,
2690                       then reconstruct the rootPropertyValue string. */
2691                    rootPropertyValueParts = rootPropertyValue.toString().match(CSS.RegEx.valueSplit);
2692                    rootPropertyValueParts[hookPosition] = hookValue;
2693                    rootPropertyValueUpdated = rootPropertyValueParts.join(" ");
2694
2695                    return rootPropertyValueUpdated;
2696                } else {
2697                    /* If the provided fullHookName isn't a registered hook, return the rootPropertyValue that was passed in. */
2698                    return rootPropertyValue;
2699                }
2700            }
2701        },
2702
2703        /*******************
2704           Normalizations
2705        *******************/
2706
2707        /* Normalizations standardize CSS property manipulation by pollyfilling browser-specific implementations (e.g. opacity)
2708           and reformatting special properties (e.g. clip, rgba) to look like standard ones. */
2709        Normalizations: {
2710            /* Normalizations are passed a normalization target (either the property's name, its extracted value, or its injected value),
2711               the targeted element (which may need to be queried), and the targeted property value. */
2712            registered: {
2713                clip: function (type, element, propertyValue) {
2714                    switch (type) {
2715                        case "name":
2716                            return "clip";
2717                        /* Clip needs to be unwrapped and stripped of its commas during extraction. */
2718                        case "extract":
2719                            var extracted;
2720
2721                            /* If Velocity also extracted this value, skip extraction. */
2722                            if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
2723                                extracted = propertyValue;
2724                            } else {
2725                                /* Remove the "rect()" wrapper. */
2726                                extracted = propertyValue.toString().match(CSS.RegEx.valueUnwrap
vendor: 8,245 bytes, lines 2726-2860
2726);
2727
2728                                /* Strip off commas. */
2729                                extracted = extracted ? extracted[1].replace(/,(\s+)?/g, " ") : propertyValue;
2730                            }
2731
2732                            return extracted;
2733                        /* Clip needs to be re-wrapped during injection. */
2734                        case "inject":
2735                            return "rect(" + propertyValue + ")";
2736                    }
2737                },
2738
2739                blur: function(type, element, propertyValue) {
2740                    switch (type) {
2741                        case "name":
2742                            return "-webkit-filter";
2743                        case "extract":
2744                            var extracted = parseFloat(propertyValue);
2745
2746                            /* If extracted is NaN, meaning the value isn't already extracted. */
2747                            if (!(extracted || extracted === 0)) {
2748                                var blurComponent = propertyValue.toString().match(/blur\(([0-9]+[A-z]+)\)/i);
2749
2750                                /* If the filter string had a blur component, return just the blur value and unit type. */
2751                                if (blurComponent) {
2752                                    extracted = blurComponent[1];
2753                                /* If the component doesn't exist, default blur to 0. */
2754                                } else {
2755                                    extracted = 0;
2756                                }
2757                            }
2758
2759                            return extracted;
2760                        /* Blur needs to be re-wrapped during injection. */
2761                        case "inject":
2762                            /* For the blur effect to be fully de-applied, it needs to be set to "none" instead of 0. */
2763                            if (!parseFloat(propertyValue)) {
2764                                return "none";
2765                            } else {
2766                                return "blur(" + propertyValue + ")";
2767                            }
2768                    }
2769                },
2770
2771                /* <=IE8 do not support the standard opacity property. They use filter:alpha(opacity=INT) instead. */
2772                opacity: function (type, element, propertyValue) {
2773                    if (IE <= 8) {
2774                        switch (type) {
2775                            case "name":
2776                                return "filter";
2777                            case "extract":
2778                                /* <=IE8 return a "filter" value of "alpha(opacity=\d{1,3})".
2779                                   Extract the value and convert it to a decimal value to match the standard CSS opacity property's formatting. */
2780                                var extracted = propertyValue.toString().match(/alpha\(opacity=(.*)\)/i);
2781
2782                                if (extracted) {
2783                                    /* Convert to decimal value. */
2784                                    propertyValue = extracted[1] / 100;
2785                                } else {
2786                                    /* When extracting opacity, default to 1 since a null value means opacity hasn't been set. */
2787                                    propertyValue = 1;
2788                                }
2789
2790                                return propertyValue;
2791                            case "inject":
2792                                /* Opacified elements are required to have their zoom property set to a non-zero value. */
2793                                element.style.zoom = 1;
2794
2795                                /* Setting the filter property on elements with certain font property combinations can result in a
2796                                   highly unappealing ultra-bolding effect. There's no way to remedy this throughout a tween, but dropping the
2797                                   value altogether (when opacity hits 1) at leasts ensures that the glitch is gone post-tweening. */
2798                                if (parseFloat(propertyValue) >= 1) {
2799                                    return "";
2800                                } else {
2801                                  /* As per the filter property's spec, convert the decimal value to a whole number and wrap the value. */
2802                                  return "alpha(opacity=" + parseInt(parseFloat(propertyValue) * 100, 10) + ")";
2803                                }
2804                        }
2805                    /* With all other browsers, normalization is not required; return the same values that were passed in. */
2806                    } else {
2807                        switch (type) {
2808                            case "name":
2809                                return "opacity";
2810                            case "extract":
2811                                return propertyValue;
2812                            case "inject":
2813                                return propertyValue;
2814                        }
2815                    }
2816                }
2817            },
2818
2819            /*****************************
2820                Batched Registrations
2821            *****************************/
2822
2823            /* Note: Batched normalizations extend the CSS.Normalizations.registered object. */
2824            register: function () {
2825
2826                /*****************
2827                    Transforms
2828                *****************/
2829
2830                /* Transforms are the subproperties contained by the CSS "transform" property. Transforms must undergo normalization
2831                   so that they can be referenced in a properties map by their individual names. */
2832                /* Note: When transforms are "set", they are actually assigned to a per-element transformCache. When all transform
2833                   setting is complete complete, CSS.flushTransformCache() must be manually called to flush the values to the DOM.
2834                   Transform setting is batched in this way to improve performance: the transform style only needs to be updated
2835                   once when multiple transform subproperties are being animated simultaneously. */
2836                /* Note: IE9 and Android Gingerbread have support for 2D -- but not 3D -- transforms. Since animating unsupported
2837                   transform properties results in the browser ignoring the *entire* transform string, we prevent these 3D values
2838                   from being normalized for these browsers so that tweening skips these properties altogether
2839                   (since it will ignore them as being unsupported by the browser.) */
2840                if (!(IE <= 9) && !Velocity.State.isGingerbread) {
2841                    /* Note: Since the standalone CSS "perspective" property and the CSS transform "perspective" subproperty
2842                    share the same name, the latter is given a unique token within Velocity: "transformPerspective". */
2843                    CSS.Lists.transformsBase = CSS.Lists.transformsBase.concat(CSS.Lists.transforms3D);
2844                }
2845
2846                for (var i = 0; i < CSS.Lists.transformsBase.length; i++) {
2847                    /* Wrap the dynamically generated normalization function in a new scope so that transformName's value is
2848                    paired with its respective function. (Otherwise, all functions would take the final for loop's transformName.) */
2849                    (function() {
2850                        var transformName = CSS.Lists.transformsBase[i];
2851
2852                        CSS.Normalizations.registered[transformName] = function (type, element, propertyValue) {
2853                            switch (type) {
2854                                /* The normalized property name is the parent "transform" property -- the property that is actually set in CSS. */
2855                                case "name":
2856                                    return "transform";
2857                                /* Transform values are cached onto a per-element transformCache object. */
2858                                case "extract":
2859                                    /* If this transform has yet to be assigned a value, return its null value. */
2860                                    if (Data(element) === undefined || Data(element).transformCache[transformName] === undefined) {
2861                                        /* Scale CSS.Lists.transformsBase default to 1 whereas all other transform properties default to 0. */
2862                                        return /^scale/i.test(transformName) ? 1 : 0;
2863                                    /* When transform values are set, they are wrapped in parentheses as per the CSS spec.
2864                                       Thus, when extracting their values (for tween calculations), we strip off the parentheses. */
2865                                    } else {
2866                                        return Data(element).transformCache[transformName].replace(/[()]/g, "");
2867                                    }
2868                                case "inject":
2869                                    var invalid = false;
2870
2871                                    /* If an individual transform property contains an unsupported unit type, the browser ignores the *entire* transform property.
2872                                       Thus, protect users from themselves by skipping setting for transform values supplied with invalid unit types. */
2873                                    /* Switch on the base transform type; ignore the axis by removing the last letter from the transform's name. */
2874                                    switch (transformName.substr(0, transformName.length - 1)) {
2875                                        /* Whitelist unit types for each transform. */
2876                                        case "translate":
2877                                            invalid = !/(%|px|em|rem|vw|vh|\d)$/i.test(propertyValue);
2878                                            break;
2879                                        /* 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. */
2880                                        case "scal":
2881                                        case "scale":
2882                                            /* Chrome on Android has a bug in which scaled elements blur if their initial scale
2883                                               value is below 1 (which can happen with forcefeeding). Thus, we detect a yet-unset scale property
2884                                               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 */
2885                                            if (Velocity.State.isAndroid && Data(element).transformCache[transformName] === undefined && propertyValue < 1) {
2886                                                propertyValue = 1;
2887                                            }
2888
2889                                            invalid = !/(\d)$/i.test(propertyValue);
2890                                            break;
2891                                        case "skew":
2892                                            invalid = !/(deg|\d)$/i.test(propertyValue);
2893                                            break;
2894                                        case "rotate":
2895                                            invalid = !/(deg|\d)$/i.test(propertyValue);
2896                                            break;
2897                                    }
2898
2899                                    if (!invalid) {
2900                                        /* As per the CSS spec, wrap the value in parentheses. */
2901                                        Data(element).transformCache[transformName] = "(" + propertyValue + ")";
2902                                    }
2903
2904                                    /* Although the value is set on the transformCache object, return the newly-updated value for the calling code to process as normal. */
2905                                    return Data(element).transformCache[transformName];
2906                            }
2907                        };
2908                    })();
2909                }
2910
2911                /*************
2912                    Colors
2913                *************/
2914
2915                /* Since Velocity only animates a single numeric value per property, color animation is achieved by hooking the individual RGBA components of CSS color properties.
2916                   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. */
2917                for (var i = 0; i < CSS.Lists.colors.length; i++) {
2918                    /* Wrap the dynamically generated normalization function in a new scope so that colorName's value is paired with its respective function.
2919                       (Otherwise, all functions would take the final for loop's colorName.) */
2920                    (function () {
2921                        var colorName = CSS.Lists.colors[i];
2922
2923                        /* Note: In IE<=8, which support rgb but not rgba, c
2923olor properties are reverted to rgb by stripping off the alpha component. */
2924                        CSS.Normalizations.registered[colorName] = function(type, element, propertyValue) {
2925                            switch (type) {
2926                                case "name":
2927                                    return colorName;
2928                                /* Convert all color values into the rgb format. (Old IE can return hex values and color names instead of rgb/rgba.) */
2929                                case "extract":
2930                                    var extracted;
2931
2932                                    /* If the color is already in its hookable form (e.g. "255 255 255 1") due to having been previously extracted, skip extraction. */
2933                                    if (CSS.RegEx.wrappedValueAlreadyExtracted.test(propertyValue)) {
2934                                        extracted = propertyValue;
2935                                    } else {
2936                                        var converted,
2937                                            colorNames = {
2938                                                black: "rgb(0, 0, 0)",
2939                                                blue: "rgb(0, 0, 255)",
2940                                                gray: "rgb(128, 128, 128)",
2941                                                green: "rgb(0, 128, 0)",
2942                                                red: "rgb(255, 0, 0)",
2943                                                white: "rgb(255, 255, 255)"
2944                                            };
2945
2946                                        /* Convert color names to rgb. */
2947                                        if (/^[A-z]+$/i.test(propertyValue)) {
2948                                            if (colorNames[propertyValue] !== undefined) {
2949                                                converted = colorNames[propertyValue]
2950                                            } else {
2951                                                /* If an unmatched color name is provided, default to black. */
2952                                                converted = colorNames.black;
2953                                            }
2954                                        /* Convert hex values to rgb. */
2955                                        } else if (CSS.RegEx.isHex.test(propertyValue)) {
2956                                            converted = "rgb(" + CSS.Values.hexToRgb(propertyValue).join(" ") + ")";
2957                                        /* If the provided color doesn't match any of the accepted color formats, default to black. */
2958                                        } else if (!(/^rgba?\(/i.test(propertyValue))) {
2959                                            converted = colorNames.black;
2960                                        }
2961
2962                                        /* Remove the surrounding "rgb/rgba()" string then replace commas with spaces and strip
2963                                           repeated spaces (in case the value included spaces to begin with). */
2964                                        extracted = (converted || propertyValue).toString().match(CSS.RegEx.valueUnwrap)[1].replace(/,(\s+)?/g, " ");
2965                                    }
2966
2967                                    /* So long as this isn't <=IE8, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
2968                                    if (!(IE <= 8) && extracted.split(" ").length === 3) {
2969                                        extracted += " 1";
2970                                    }
2971
2972                                    return extracted;
2973                                case "inject":
2974                                    /* If this is IE<=8 and an alpha component exists, strip it off. */
2975                                    if (IE <= 8) {
2976                                        if (propertyValue.split(" ").length === 4) {
2977                                            propertyValue = propertyValue.split(/\s+/).slice(0, 3).join(" ");
2978                                        }
2979                                    /* Otherwise, add a fourth (alpha) component if it's missing and default it to 1 (visible). */
2980                                    } else if (propertyValue.split(" ").length === 3) {
2981                                        propertyValue += " 1";
2982                                    }
2983
2984                                    /* Re-insert the browser-appropriate wrapper("rgb/rgba()"), insert commas, and strip off decimal units
2985                                       on all values but the fourth (R, G, and B only accept whole numbers). */
2986                                    return (IE <= 8 ? "rgb" : "rgba") + "(" + propertyValue.replace(/\s+/g, ",").replace(/\.(\d)+(?=,)/g, "") + ")";
2987                            }
2988                        };
2989                    })();
2990                }
2991            }
2992        },
2993
2994        /************************
2995           CSS Property Names
2996        ************************/
2997
2998        Names: {
vendor: 5,382 bytes, lines 2999-3096
2999            /* Camelcase a property name into its JavaScript notation (e.g. "background-color" ==> "backgroundColor").
3000               Camelcasing is used to normalize property names between and across calls. */
3001            camelCase: function (property) {
3002                return property.replace(/-(\w)/g, function (match, subMatch) {
3003                    return subMatch.toUpperCase();
3004                });
3005            },
3006
3007            /* For SVG elements, some properties (namely, dimensional ones) are GET/SET via the element's HTML attributes (instead of via CSS styles). */
3008            SVGAttribute: function (property) {
3009                var SVGAttributes = "width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";
3010
3011                /* Certain browsers require an SVG transform to be applied as an attribute. (Otherwise, application via CSS is preferable due to 3D support.) */
3012                if (IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) {
3013                    SVGAttributes += "|transform";
3014                }
3015
3016                return new RegExp("^(" + SVGAttributes + ")$", "i").test(property);
3017            },
3018
3019            /* Determine whether a property should be set with a vendor prefix. */
3020            /* If a prefixed version of the property exists, return it. Otherwise, return the original property name.
3021               If the property is not at all supported by the browser, return a false flag. */
3022            prefixCheck: function (property) {
3023                /* If this property has already been checked, return the cached value. */
3024                if (Velocity.State.prefixMatches[property]) {
3025                    return [ Velocity.State.prefixMatches[property], true ];
3026                } else {
3027                    var vendors = [ "", "Webkit", "Moz", "ms", "O" ];
3028
3029                    for (var i = 0, vendorsLength = vendors.length; i < vendorsLength; i++) {
3030                        var propertyPrefixed;
3031
3032                        if (i === 0) {
3033                            propertyPrefixed = property;
3034                        } else {
3035                            /* Capitalize the first letter of the property to conform to JavaScript vendor prefix notation (e.g. webkitFilter). */
3036                            propertyPrefixed = vendors[i] + property.replace(/^\w/, function(match) { return match.toUpperCase(); });
3037                        }
3038
3039                        /* Check if the browser supports this property as prefixed. */
3040                        if (Type.isString(Velocity.State.prefixElement.style[propertyPrefixed])) {
3041                            /* Cache the match. */
3042                            Velocity.State.prefixMatches[property] = propertyPrefixed;
3043
3044                            return [ propertyPrefixed, true ];
3045                        }
3046                    }
3047
3048                    /* If the browser doesn't support this property in any form, include a false flag so that the caller can decide how to proceed. */
3049                    return [ property, false ];
3050                }
3051            }
3052        },
3053
3054        /************************
3055           CSS Property Values
3056        ************************/
3057
3058        Values: {
3059            /* Hex to RGB conversion. Copyright Tim Down: http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb */
3060            hexToRgb: function (hex) {
3061                var shortformRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i,
3062                    longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,
3063                    rgbParts;
3064
3065                hex = hex.replace(shortformRegex, function (m, r, g, b) {
3066                    return r + r + g + g + b + b;
3067                });
3068
3069                rgbParts = longformRegex.exec(hex);
3070
3071                return rgbParts ? [ parseInt(rgbParts[1], 16), parseInt(rgbParts[2], 16), parseInt(rgbParts[3], 16) ] : [ 0, 0, 0 ];
3072            },
3073
3074            isCSSNullValue: function (value) {
3075                /* The browser defaults CSS values that have not been set to either 0 or one of several possible null-value strings.
3076                   Thus, we check for both falsiness and these special strings. */
3077                /* Null-value checking is performed to default the special strings to 0 (for the sake of tweening) or their hook
3078                   templates as defined as CSS.Hooks (for the sake of hook injection/extraction). */
3079                /* Note: Chrome returns "rgba(0, 0, 0, 0)" for an undefined color whereas IE returns "transparent". */
3080                return (value == 0 || /^(none|auto|transparent|(rgba\(0, ?0, ?0, ?0\)))$/i.test(value));
3081            },
3082
3083            /* Retrieve a property's default unit type. Used for assigning a unit type when one is not supplied by the user. */
3084            getUnitType: function (property) {
3085                if (/^(rotate|skew)/i.test(property)) {
3086                    return "deg";
3087                } else if (/(^(scale|scaleX|scaleY|scaleZ|alpha|flexGrow|flexHeight|zIndex|fontWeight)$)|((opacity|red|green|blue|alpha)$)/i.test(property)) {
3088                    /* The above properties are unitless. */
3089                    return "";
3090                } else {
3091                    /* Default to px for all other properties. */
3092                    return "px";
3093                }
3094            },
3095
3096            /* HTML elements default to an associated display type when they're not set to display:none. */
3097            /* Note: This function is used for correctly setting the non-"none" display value in certain Velocity redirects, such as fadeIn/Out. */
3098            getDisplayType: function (element) {
3099                var tagName = element && element.tagName.toString().toLowerCase();
3100
3101                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)) {
3102                    return "inline";
3103                } else if (/^(li)$/i.test(tagName)) {
3104                    return "list-item";
3105                } else if (/^(tr)$/i.test(tagName)) {
3106                    return "table-row";
3107                /* Default to "block" when no match is found. */
3108                } else {
3109                    return "block";
3110                }
3111            },
3112
3113            /* The class add/remove functions are used to temporarily apply a "velocity-animating" class to elements while they're animating. */
3114            addClass: function (element, className) {
3115                if (element.classList) {
3116                    element.classList.add(className);
3117                } else {
3118                    element.className += (element.className.length ? " " : "") + className;
3119                }
3120            },
3121
3122            removeClass: function (element, className) {
3123                if (element.classList) {
3124                    element.classList.remove(className);
3125                } else {
3126                    element.className = element.className.toString().replace(new RegExp("(^|\\s)" + className.split(" ").join("|") + "(\\s|$)", "gi"), " ");
3127                }
3128            }
3129        },
3130
3131        /****************************
3132           Style Getting & Setting
3133        ****************************/
3134
3135        /* The singular getPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */
3136        getPropertyValue: function (element, property, rootPropertyValue, forceStyleLookup) {
3137            /* Get an element's computed property value. */
3138            /* Note: Retrieving the value of a CSS property cannot simply be performed by checking an element's
3139               style attribute (which only reflects user-defined values). Instead, the browser must be queried for a property's
3140               *computed* value. You can read more about getComputedStyle here: https://developer.mozilla.org/en/docs/Web/API/window.getComputedStyle */
3141            function computePropertyValue (element, property) {
3142                /* When box-sizing isn't set to border-box, height and width style values are incorrectly computed when an
3143                   element's scrollbars are visible (which expands the element's dimensions). Thus, we defer to the more accurate
3144                   offsetHeight/Width property, which includes the total dimensions for interior, border, padding, and scrollbar.
3145                   We subtract border and padding to get the sum of interior + scrollbar. */
3146                var computedValue = 0;
3147
3148                /* IE<=8 doesn't support window.getComputedStyle, thus we defer to jQuery, which has an extensive array
3149                   of hacks to accurately retrieve IE8 property values. Re-implementing that logic here is not worth bloating the
3150                   codebase for a dying browser. The performance repercussions of using jQuery here are minimal since
3151                   Velocity is optimized to rarely (and sometimes never) query the DOM. Further, the $.css() codepath isn't that slow. */
3152                if (IE <= 8) {
3153                    computedValue = $.css(element, property); /* GET */
3154                /* All other browsers support getComputedStyle. The returned live object reference is cached onto its
3155                   associated element so that it does not need to be refetched upon every GET. */
3156                } else {
3157                    /* Browsers do not return height and width values for elements that are set to display:"none". Thus, we temporarily
3158                       toggle display to the element type's default value. */
3159                    var toggleDisplay = false;
vendor: 7,262 bytes, lines 3160-3265
3160
3161                    if (/^(width|height)$/.test(property) && CSS.getPropertyValue(element, "display") === 0) {
3162                        toggleDisplay = true;
3163                        CSS.setPropertyValue(element, "display", CSS.Values.getDisplayType(element));
3164                    }
3165
3166                    function revertDisplay () {
3167                        if (toggleDisplay) {
3168                            CSS.setPropertyValue(element, "display", "none");
3169                        }
3170                    }
3171
3172                    if (!forceStyleLookup) {
3173                        if (property === "height" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") {
3174                            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);
3175                            revertDisplay();
3176
3177                            return contentBoxHeight;
3178                        } else if (property === "width" && CSS.getPropertyValue(element, "boxSizing").toString().toLowerCase() !== "border-box") {
3179                            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);
3180                            revertDisplay();
3181
3182                            return contentBoxWidth;
3183                        }
3184                    }
3185
3186                    var computedStyle;
3187
3188                    /* For elements that Velocity hasn't been called on directly (e.g. when Velocity queries the DOM on behalf
3189                       of a parent of an element its animating), perform a direct getComputedStyle lookup since the object isn't cached. */
3190                    if (Data(element) === undefined) {
3191                        computedStyle = window.getComputedStyle(element, null); /* GET */
3192                    /* If the computedStyle object has yet to be cached, do so now. */
3193                    } else if (!Data(element).computedStyle) {
3194                        computedStyle = Data(element).computedStyle = window.getComputedStyle(element, null); /* GET */
3195                    /* If computedStyle is cached, use it. */
3196                    } else {
3197                        computedStyle = Data(element).computedStyle;
3198                    }
3199
3200                    /* IE and Firefox do not return a value for the generic borderColor -- they only return individual values for each border side's color.
3201                       As a polyfill for querying individual border side colors, just return the top border's color. */
3202                    if ((IE || Velocity.State.isFirefox) && property === "borderColor") {
3203                        property = "borderTopColor";
3204                    }
3205
3206                    /* IE9 has a bug in which the "filter" property must be accessed from computedStyle using the getPropertyValue method
3207                       instead of a direct property lookup. The getPropertyValue method is slower than a direct lookup, which is why we avoid it by default. */
3208                    if (IE === 9 && property === "filter") {
3209                        computedValue = computedStyle.getPropertyValue(property); /* GET */
3210                    } else {
3211                        computedValue = computedStyle[property];
3212                    }
3213
3214                    /* Fall back to the property's style value (if defined) when computedValue returns nothing,
3215                       which can happen when the element hasn't been painted. */
3216                    if (computedValue === "" || computedValue === null) {
3217                        computedValue = element.style[property];
3218                    }
3219
3220                    revertDisplay();
3221                }
3222
3223                /* For top, right, bottom, and left (TRBL) values that are set to "auto" on elements of "fixed" or "absolute" position,
3224                   defer to jQuery for converting "auto" to a numeric value. (For elements with a "static" or "relative" position, "auto" has the same
3225                   effect as being set to 0, so no conversion is necessary.) */
3226                /* An example of why numeric conversion is necessary: When an element with "position:absolute" has an untouched "left"
3227                   property, which reverts to "auto", left's value is 0 relative to its parent element, but is often non-zero relative
3228                   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"). */
3229                if (computedValue === "auto" && /^(top|right|bottom|left)$/i.test(property)) {
3230                    var position = computePropertyValue(element, "position"); /* GET */
3231
3232                    /* For absolute positioning, jQuery's $.position() only returns values for top and left;
3233                       right and bottom will have their "auto" value reverted to 0. */
3234                    /* Note: A jQuery object must be created here since jQuery doesn't have a low-level alias for $.position().
3235                       Not a big deal since we're currently in a GET batch anyway. */
3236                    if (position === "fixed" || (position === "absolute" && /top|left/i.test(property))) {
3237                        /* Note: jQuery strips the pixel unit from its returned values; we re-add it here to conform with computePropertyValue's behavior. */
3238                        computedValue = $(element).position()[property] + "px"; /* GET */
3239                    }
3240                }
3241
3242                return computedValue;
3243            }
3244
3245            var propertyValue;
3246
3247            /* If this is a hooked property (e.g. "clipLeft" instead of the root property of "clip"),
3248               extract the hook's value from a normalized rootPropertyValue using CSS.Hooks.extractValue(). */
3249            if (CSS.Hooks.registered[property]) {
3250                var hook = property,
3251                    hookRoot = CSS.Hooks.getRoot(hook);
3252
3253                /* If a cached rootPropertyValue wasn't passed in (which Velocity always attempts to do in order to avoid requerying the DOM),
3254                   query the DOM for the root property's value. */
3255                if (rootPropertyValue === undefined) {
3256                    /* Since the browser is now being directly queried, use the official post-prefixing property name for this lookup. */
3257                    rootPropertyValue = CSS.getPropertyValue(element, CSS.Names.prefixCheck(hookRoot)[0]); /* GET */
3258                }
3259
3260                /* If this root has a normalization registered, peform the associated normalization extraction. */
3261                if (CSS.Normalizations.registered[hookRoot]) {
3262                    rootPropertyValue = CSS.Normalizations.registered[hookRoot]("extract", element, rootPropertyValue);
3263                }
3264
3265                /* Extract the hook's value. */
3266                propertyValue = CSS.Hooks.extractValue(hook, rootPropertyValue);
3267
3268            /* If this is a normalized property (e.g. "opacity" becomes "filter" in <=IE8) or "translateX" becomes "transform"),
3269               normalize the property's name and value, and handle the special case of transforms. */
3270            /* Note: Normalizing a property is mutually exclusive from hooking a property since hook-extracted values are strictly
3271               numerical and therefore do not require normalization extraction. */
3272            } else if (CSS.Normalizations.registered[property]) {
3273                var normalizedPropertyName,
3274                    normalizedPropertyValue;
3275
3276                normalizedPropertyName = CSS.Normalizations.registered[property]("name", element);
3277
3278                /* Transform values are calculated via normalization extraction (see below), which checks against the element's transformCache.
3279                   At no point do transform GETs ever actually query the DOM; initial stylesheet values are never processed.
3280                   This is because parsing 3D transform matrices is not always accurate and would bloat our codebase;
3281                   thus, normalization extraction defaults initial transform values to their zero-values (e.g. 1 for scaleX and 0 for translateX). */
3282                if (normalizedPropertyName !== "transform") {
3283                    normalizedPropertyValue = computePropertyValue(element, CSS.Names.prefixCheck(normalizedPropertyName)[0]); /* GET */
3284
3285                    /* 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. */
3286                    if (CSS.Values.isCSSNullValue(normalizedPropertyValue) && CSS.Hooks.templates[property]) {
3287                        normalizedPropertyValue = CSS.Hooks.templates[property][1];
3288                    }
3289                }
3290
3291                propertyValue = CSS.Normalizations.registered[property]("extract", element, normalizedPropertyValue);
3292            }
3293
3294            /* If a (numeric) value wasn't produced via hook extraction or normalization, query the DOM. */
3295            if (!/^[\d-]/.test(propertyValue)) {
3296                /* For SVG elements, dimensional properties (which SVGAttribute() detects) are tweened via
3297                   their HTML attribute values instead of their CSS style values. */
3298                if (Data(element) && Data(element).isSVG && CSS.Names.SVGAttribute(property)) {
3299                    /* Since the height/width attribute values must be set manually, they don't reflect computed values.
3300                       Thus, we use use getBBox() to ensure we always get values for elements with undefined height/width attributes. */
3301                    if (/^(height|width)$/i.test(property)) {
3302                        propertyValue = element.getBBox()[property];
3303                    /* Otherwise, access the attribute value directly. */
3304                    } else {
3305                        propertyValue = element.getAttribute(property);
3306                    }
3307                } else {
3308                    propertyValue = computePropertyValue(element, CSS.Names.prefixCheck(property)[0]); /* GET */
3309                }
3310            }
3311
3312            /* Since property lookups are for animation purposes (which entails computing the numeric delta between start and end values),
3313               convert CSS null-values to an integer of value 0. */
3314            if (CSS.Values.isCSSNullValue(propertyValue)) {
3315                propertyValue = 0;
3316            }
3317
3318            if (Velocity.debug >= 2) console.log("Get " + property + ": " + propertyValue);
3319
3320            return propertyValue;
3321        },
3322
3323        /* The singular setPropertyValue, which routes the logic for all normalizations, hooks, and standard CSS properties. */
3324        setPropertyValue: function(element, property, propertyValue, rootPropertyValue, scrollData) {
3325            var propertyName = property;
3326
3327            /* 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. */
3328            if (property === "scroll") {
3329                /* If a container option is present, scroll the container instead of the browser window. */
3330                if (scrollData.container) {
3331                    scrollData.container["scroll" + scrollData.direction] = propertyValue;
3332                /* Otherwise, Velocity defaults to scrolling the browser window. */
3333                } else {
3334                    if (scrollData.direction === "Left") {
3335                        window.scrollTo(propertyValue, scrollData.alternateValue);
3336                    } else {
3337                        window.scrollTo(scrollData.alternateValue, propertyValue);
3338                    }
3339                }
3340            } else {
3341                /* Transforms (translateX, rotateZ, etc.) are applied to a per-element transformCache object, which is manually flushed via flushTransformCache().
3342                   Thus, for now, we merely cache transforms being SET. */
3343                if (CSS.Normalizations.registered[property] && CSS.Normalizations.registered[property]("name", element) === "transform") {
3344                    /* Perform a normalization injection. */
3345                    /* Note: The normalization logic handles the transformCache updating. */
3346                    CSS.Normalizations.registered[property]("inject", element, propertyValue);
3347
3348                    propertyName = "transform";
3349                    propertyValue = Data(element).transformCache[property];
3350                } else {
3351                    /* Inject hooks. */
3352                    if (CSS.Hooks.registered[property]) {
3353                        var hookName = property,
3354                            hookRoot = CSS.Hooks.getRoot(property);
3355
3356                        /* If a cached rootPropertyValue was not provided, query the DOM for the hookRoot's current value. */
3357                        rootPropertyValue = rootPropertyValue || CSS.getPropertyValue(element, hookRoot); /* GET */
3358
3359                        propertyValue = CSS.Hooks.injectValue(ho
3359okName, propertyValue, rootPropertyValue);
3360                        property = hookRoot;
3361                    }
3362
3363                    /* Normalize names and values. */
3364                    if (CSS.Normalizations.registered[property]) {
3365                        propertyValue = CSS.Normalizations.registered[property]("inject", element, propertyValue);
3366                        property = CSS.Normalizations.registered[property]("name", element);
3367                    }
3368
3369                    /* Assign the appropriate vendor prefix before performing an official style update. */
3370                    propertyName = CSS.Names.prefixCheck(property)[0];
3371
3372                    /* A try/catch is used for IE<=8, which throws an error when "invalid" CSS values are set, e.g. a negative width.
3373                       Try/catch is avoided for other browsers since it incurs a performance overhead. */
3374                    if (IE <= 8) {
3375                        try {
3376                            element.style[propertyName] = propertyValue;
3377                        } catch (error) { if (Velocity.debug) console.log("Browser does not support [" + propertyValue + "] for [" + propertyName + "]"); }
3378                    /* SVG elements have their dimensional properties (width, height, x, y, cx, etc.) applied directly as attributes instead of as styles. */
3379                    /* Note: IE8 does not support SVG elements, so it's okay that we skip it for SVG animation. */
3380                    } else if (Data(element) && Data(element).isSVG && CSS.Names.SVGAttribute(property)) {
3381                        /* Note: For SVG attributes, vendor-prefixed property names are never used. */
3382                        /* Note: Not all CSS properties can be animated via attributes, but the browser won't throw an error for unsupported properties. */
3383                        element.setAttribute(property, propertyValue);
3384                    } else {
3385                        element.style[propertyName] = propertyValue;
3386                    }
3387
3388                    if (Velocity.debug >= 2) console.log("Set " + property + " (" + propertyName + "): " + propertyValue);
3389                }
3390            }
3391
3392            /* 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. */
3393            return [ propertyName, propertyValue ];
3394        },
3395
3396        /* To increase performance by batching transform updates into a single SET, transforms are not directly applied to an element until flushTransformCache() is called. */
3397        /* Note: Velocity applies transform properties in the same order that they are chronogically introduced to the element's CSS styles. */
3398        flushTransformCache: function(element) {
3399            var transformString = "";
3400
3401            /* 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
3402               (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). */
3403            if ((IE || (Velocity.State.isAndroid && !Velocity.State.isChrome)) && Data(element).isSVG) {
3404                /* Since transform values are stored in their parentheses-wrapped form, we use a helper function to strip out their numeric values.
3405                   Further, SVG transform properties only take unitless (representing pixels) values, so it's okay that parseFloat() strips the unit suffixed to the float value. */
3406                function getTransformFloat (transformProperty) {
3407                    return parseFloat(CSS.getPropertyValue(element, transformProperty));
3408                }
3409
3410                /* Create an object to organize all the transforms that we'll apply to the SVG element. To keep the logic simple,
3411                   we process *all* transform properties -- even those that may not be explicitly applied (since they default to their zero-values anyway). */
3412                var SVGTransforms = {
3413                    translate: [ getTransformFloat("translateX"), getTransformFloat("translateY") ],
3414                    skewX: [ getTransformFloat("skewX") ], skewY: [ getTransformFloat("skewY") ],
vendor: 6,513 bytes, lines 3415-3544
3415                    /* If the scale property is set (non-1), use that value for the scaleX and scaleY values
3416                       (this behavior mimics the result of animating all these properties at once on HTML elements). */
3417                    scale: getTransformFloat("scale") !== 1 ? [ getTransformFloat("scale"), getTransformFloat("scale") ] : [ getTransformFloat("scaleX"), getTransformFloat("scaleY") ],
3418                    /* Note: SVG's rotate transform takes three values: rotation degrees followed by the X and Y values
3419                       defining the rotation's origin point. We ignore the origin values (default them to 0). */
3420                    rotate: [ getTransformFloat("rotateZ"), 0, 0 ]
3421                };
3422
3423                /* Iterate through the transform properties in the user-defined property map order.
3424                   (This mimics the behavior of non-SVG transform animation.) */
3425                $.each(Data(element).transformCache, function(transformName) {
3426                    /* Except for with skewX/Y, revert the axis-specific transform subproperties to their axis-free master
3427                       properties so that they match up with SVG's accepted transform properties. */
3428                    if (/^translate/i.test(transformName)) {
3429                        transformName = "translate";
3430                    } else if (/^scale/i.test(transformName)) {
3431                        transformName = "scale";
3432                    } else if (/^rotate/i.test(transformName)) {
3433                        transformName = "rotate";
3434                    }
3435
3436                    /* Check that we haven't yet deleted the property from the SVGTransforms container. */
3437                    if (SVGTransforms[transformName]) {
3438                        /* Append the transform property in the SVG-supported transform format. As per the spec, surround the space-delimited values in parentheses. */
3439                        transformString += transformName + "(" + SVGTransforms[transformName].join(" ") + ")" + " ";
3440
3441                        /* After processing an SVG transform property, delete it from the SVGTransforms container so we don't
3442                           re-insert the same master property if we encounter another one of its axis-specific properties. */
3443                        delete SVGTransforms[transformName];
3444                    }
3445                });
3446            } else {
3447                var transformValue,
3448                    perspective;
3449
3450                /* Transform properties are stored as members of the transformCache object. Concatenate all the members into a string. */
3451                $.each(Data(element).transformCache, function(transformName) {
3452                    transformValue = Data(element).transformCache[transformName];
3453
3454                    /* Transform's perspective subproperty must be set first in order to take effect. Store it temporarily. */
3455                    if (transformName === "transformPerspective") {
3456                        perspective = transformValue;
3457                        return true;
3458                    }
3459
3460                    /* IE9 only supports one rotation type, rotateZ, which it refers to as "rotate". */
3461                    if (IE === 9 && transformName === "rotateZ") {
3462                        transformName = "rotate";
3463                    }
3464
3465                    transformString += transformName + transformValue + " ";
3466                });
3467
3468                /* If present, set the perspective subproperty first. */
3469                if (perspective) {
3470                    transformString = "perspective" + perspective + " " + transformString;
3471                }
3472            }
3473
3474            CSS.setPropertyValue(element, "transform", transformString);
3475        }
3476    };
3477
3478    /* Register hooks and normalizations. */
3479    CSS.Hooks.register();
3480    CSS.Normalizations.register();
3481
3482    /* Allow hook setting in the same fashion as jQuery's $.css(). */
3483    Velocity.hook = function (elements, arg2, arg3) {
3484        var value = undefined;
3485
3486        elements = sanitizeElements(elements);
3487
3488        $.each(elements, function(i, element) {
3489            /* Initialize Velocity's per-element data cache if this element hasn't previously been animated. */
3490            if (Data(element) === undefined) {
3491                Velocity.init(element);
3492            }
3493
3494            /* Get property value. If an element set was passed in, only return the value for the first element. */
3495            if (arg3 === undefined) {
3496                if (value === undefined) {
3497                    value = Velocity.CSS.getPropertyValue(element, arg2);
3498                }
3499            /* Set property value. */
3500            } else {
3501                /* sPV returns an array of the normalized propertyName/propertyValue pair used to update the DOM. */
3502                var adjustedSet = Velocity.CSS.setPropertyValue(element, arg2, arg3);
3503
3504                /* Transform properties don't automatically set. They have to be flushed to the DOM. */
3505                if (adjustedSet[0] === "transform") {
3506                    Velocity.CSS.flushTransformCache(element);
3507                }
3508
3509                value = adjustedSet;
3510            }
3511        });
3512
3513        return value;
3514    };
3515
3516    /*****************
3517        Animation
3518    *****************/
3519
3520    var animate = function() {
3521
3522        /******************
3523            Call Chain
3524        ******************/
3525
3526        /* Logic for determining what to return to the call stack when exiting out of Velocity. */
3527        function getChain () {
3528            /* If we are using the utility function, attempt to return this call's promise. If no promise library was detected,
3529               default to null instead of returning the targeted elements so that utility function's return value is standardized. */
3530            if (isUtility) {
3531                return promiseData.promise || null;
3532            /* Otherwise, if we're using $.fn, return the jQuery-/Zepto-wrapped element set. */
3533            } else {
3534                return elementsWrapped;
3535            }
3536        }
3537
3538        /*************************
3539           Arguments Assignment
3540        *************************/
3541
3542        /* To allow for expressive CoffeeScript code, Velocity supports an alternative syntax in which "properties" and "options"
3543           objects are defined on a container object that's passed in as Velocity's sole argument. */
3544        /* Note: Some browsers automatically populate arguments with a "properties" object. We detect it by checking for its default "n
3544ames" property. */
3545        var syntacticSugar = (arguments[0] && (($.isPlainObject(arguments[0].properties) && !arguments[0].properties.names) || Type.isString(arguments[0].properties))),
3546            /* Whether Velocity was called via the utility function (as opposed to on a jQuery/Zepto object). */
3547            isUtility,
3548            /* When Velocity is called via the utility function ($.Velocity()/Velocity()), elements are explicitly
3549               passed in as the first parameter. Thus, argument positioning varies. We normalize them here. */
3550            elementsWrapped,
3551            argumentIndex;
3552
3553        var elements,
3554            propertiesMap,
3555            options;
3556
3557        /* Detect jQuery/Zepto elements being animated via the $.fn method. */
3558        if (Type.isWrapped(this)) {
3559            isUtility = false;
3560
3561            argumentIndex = 0;
3562            elements = this;
3563            elementsWrapped = this;
3564        /* Otherwise, raw elements are being animated via the utility function. */
3565        } else {
3566            isUtility = true;
3567
3568            argumentIndex = 1;
3569            elements = syntacticSugar ? arguments[0].elements : arguments[0];
3570        }
3571
3572        elements = sanitizeElements(elements);
3573
3574        if (!elements) {
3575            return;
3576        }
3577
3578        if (syntacticSugar) {
3579            propertiesMap = arguments[0].properties;
3580            options = arguments[0].options;
3581        } else {
3582            propertiesMap = arguments[argumentIndex];
3583            options = arguments[argumentIndex + 1];
3584        }
3585
3586        /* The length of the element set (in the form of a nodeList or an array of elements) is defaulted to 1 in case a
3587           single raw DOM element is passed in (which doesn't contain a length property). */
3588        var elementsLength = elements.length,
3589            elementsIndex = 0;
3590
3591        /***************************
3592            Argument Overloading
3593        ***************************/
3594
3595        /* Support is included for jQuery's argument overloading: $.animate(propertyMap [, duration] [, easing] [, complete]).
3596           Overloading is detected by checking for the absence of an object being passed into options. */
3597        /* Note: The stop action does not accept animation options, and is therefore excluded from this check. */
3598        if (propertiesMap !== "stop" && !$.isPlainObject(options)) {
3599            /* The utility function shifts all arguments one position to the right, so we adjust for that offset. */
3600            var startingArgumentPosition = argumentIndex + 1;
3601
3602            options = {};
3603
3604            /* Iterate through all options arguments */
3605            for (var i = startingArgumentPosition; i < arguments.length; i++) {
3606                /* Treat a number as a duration. Parse it out. */
3607                /* Note: The following RegEx will return true if passed an array with a number as its first item.
3608                   Thus, arrays are skipped from this check. */
3609                if (!Type.isArray(arguments[i]) && (/^(fast|normal|slow)$/i.test(arguments[i]) || /^\d/.test(arguments[i]))) {
3610                    options.duration = arguments[i];
3611                /* Treat strings and arrays as easings. */
3612                } else if (Type.isString(arguments[i]) || Type.isArray(arguments[i])) {
3613                    options.easing = arguments[i];
3614                /* Treat a function as a complete callback. */
3615                } else if (Type.isFunction(arguments[i])) {
3616                    options.complete = arguments[i];
3617                }
3618            }
3619        }
3620
3621        /***************
3622            Promises
3623        ***************/
3624
3625        var promiseData = {
3626                promise: null,
3627                resolver: null,
3628                rejecter: null
3629            };
3630
3631        /* 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
3632           promise support was detected, create a promise object for this call and store references to its resolver and rejecter methods. The resolve
3633           method is used when a call completes naturally or is prematurely stopped by the user. In both cases, completeCall() handles the associated
3634           call cleanup and promise resolving logic. The reject method is used when an invali
3634d set of arguments is passed into a Velocity call. */
3635        /* Note: Velocity employs a call-based queueing architecture, which means that stopping an animating element actually stops the full call that
3636           triggered it -- not that one element exclusively. Similarly, there is one promise per call, and all elements targeted by a Velocity call are
3637           grouped together for the purposes of resolving and rejecting a promise. */
3638        if (isUtility && Velocity.Promise) {
3639            promiseData.promise = new Velocity.Promise(function (resolve, reject) {
3640                promiseData.resolver = resolve;
3641                promiseData.rejecter = reject;
3642            });
3643        }
3644
3645        /*********************
3646           Action Detection
3647        *********************/
3648
3649        /* Velocity's behavior is categorized into "actions": Elements can either be specially scrolled into view,
3650           or they can be started, stopped, or reversed. If a literal or referenced properties map is passed in as Velocity's
3651           first argument, the associated action is "start". Alternatively, "scroll", "reverse", or "stop" can be passed in instead of a properties map. */
3652        var action;
3653
3654        switch (propertiesMap) {
3655            case "scroll":
3656                action = "scroll";
3657                break;
3658
3659            case "reverse":
3660                action = "reverse";
3661                break;
3662
3663            case "stop":
3664                /*******************
3665                    Action: Stop
3666                *******************/
3667
3668                /* Clear the currently-active delay on each targeted element. */
3669                $.each(elements, function(i, element) {
3670                    if (Data(element) && Data(element).delayTimer) {
3671                        /* Stop the timer from triggering its cached next() function. */
3672                        clearTimeout(Data(element).delayTimer.setTimeout);
3673
3674                        /* Manually call the next() function so that the subsequent queue items can progress. */
3675                        if (Data(element).delayTimer.next) {
3676                            Data(element).delayTimer.next();
3677                        }
3678
3679                        delete Data(element).delayTimer;
3680                    }
3681                });
3682
3683                var callsToStop = [];
3684
3685                /* When the stop action is triggered, the elements' currently active call is immediately stopped. The active call might have
3686                   been applied to multiple elements, in which case all of the call's elements will be subjected to stopping. When an element
3687                   is stopped, the next item in its animation queue is immediately triggered. */
3688                /* An additional argument may be passed in to clear an element's remaining queued calls. Either true (which defaults to the "fx" queue)
3689                   or a custom queue string can be passed in. */
3690                /* Note: The stop command runs prior to Queueing since its behavior is intended to take effect *immediately*,
3691                   regardless of the element's current queue state. */
3692
3693                /* Iterate through every active call. */
3694                $.each(Velocity.State.calls, function(i, activeCall) {
3695                    /* Inactive calls are set to false by the logic inside completeCall(). Skip them. */
3696                    if (activeCall) {
3697                        /* Iterate through the active call's targeted elements. */
3698                        $.each(activeCall[1], function(k, activeElement) {
3699                            var queueName = Type.isString(options) ? options : "";
3700
3701                            if (options !== undefined && activeCall[2].queue !== queueName) {
3702                                return true;
3703                            }
3704
3705                            /* Iterate through the calls targeted by the stop command. */
3706                            $.each(elements, function(l, element) {
3707                                /* Check that this call was applied to the target element. */
3708                                if (element === activeElement) {
3709                                    /* Optionally clear the remaining queued calls. */
3710                                    if (options !== undefined) {
3711                                        /* Iterate through the items in the element's queue. */
3712                                        $.each($.queue(element, queueName), function(_, item) {
3713                                            /* The queue array can contain an "inprogress" string, which we skip. */
3714                                            if (Type.isFunction(item)) {
3715                                                /* Pass the item's callback a flag indicating that we want to abort from the queue call.
3716                                                   (Specifically, the queue will resolve the call's associated promise then abort.)  */
3717                                                item(null, true);
3718                                            }
3719                                        });
3720
3721                                        /* Clearing the $.queue() array is achieved by resetting it to []. */
3722                                        $.queue(element, queueName, []);
3723                                    }
3724
3725                                    if (Data(element) && queueName === "") {
3726                                        /* Since "reverse" uses cached start values (the previous call's endValues),
3727                                           these values must be changed to reflect the final value that the elements were actually tweened to. */
3728                                        $.each(Data(element).tweensContainer, function(m, activeTween) {
3729                                            activeTween.endValue = activeTween.currentValue;
3730                                        });
3731                                    }
3732
3733                                    callsToStop.push(i);
3734                                }
3735                            });
3736                        });
3737                    }
3738                });
3739
3740                /* Prematurely call completeCall() on each matched active call, passing an additional flag to indicate
3741                   that the complete callback and display:none setting should be skipped since we're completing prematurely. */
3742                $.each(callsToStop, function(i, j) {
3743                    completeCall(j, true);
3744                });
3745
3746                if (promiseData.promise) {
3747                    /* Immediately resolve the promise associated with this stop call since stop runs synchronously. */
3748                    promiseData.resolver(elements);
3749                }
3750
3751                /* Since we're stopping, and not proceeding with queueing, exit out of Velocity. */
3752                return getChain();
3753
3754            default:
3755                /* Treat a non-empty plain object as a literal properties map. */
3756                if ($.isPlainObject(propertiesMap) && !Type.isEmptyObject(propertiesMap)) {
3757                    action = "start";
3758
3759                /****************
3760                    Redirects
3761                ****************/
3762
3763                /* Check if a string matches a registered redirect (see Redirects above). */
3764                } else if (Type.isString(propertiesMap) && Velocity.Redirects[propertiesMap]) {
3765                    var opts = $.extend({}, options),
3766                        durationOriginal = opts.duration,
3767                        delayOriginal = opts.delay || 0;
3768
3769                    /* If the backwards option was passed in, reverse the element set so that elements animate from the last to the first. */
3770                    if (opts.backwards === true) {
3771                        elements = $.extend(true, [], elements).reverse();
3772                    }
3773
3774                    /* Individually trigger the redirect for each element in the set to prevent users from having to handle iteration logic in their redirect. */
3775                    $.each(elements, function(elementIndex, element) {
3776                        /* If the stagger option was passed in, successively delay each element by the stagger value (in ms). Retain the original delay value. */
3777                        if (parseFloat(opts.stagger)) {
vendor: 18,569 bytes, lines 3778-4084
3778                            opts.delay = delayOriginal + (parseFloat(opts.stagger) * elementIndex);
3779                        } else if (Type.isFunction(opts.stagger)) {
3780                            opts.delay = delayOriginal + opts.stagger.call(element, elementIndex, elementsLength);
3781                        }
3782
3783                        /* If the drag option was passed in, successively increase/decrease (depending on the presense of opts.backwards)
3784                           the duration of each element's animation, using floors to prevent producing very short durations. */
3785                        if (opts.drag) {
3786                            /* Default the duration of UI pack effects (callouts and transitions) to 1000ms instead of the usual default duration of 400ms. */
3787                            opts.duration = parseFloat(durationOriginal) || (/^(callout|transition)/.test(propertiesMap) ? 1000 : DURATION_DEFAULT);
3788
3789                            /* For each element, take the greater duration of: A) animation completion percentage relative to the original duration,
3790                               B) 75% of the original duration, or C) a 200ms fallback (in case duration is already set to a low value).
3791                               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. */
3792                            opts.duration = Math.max(opts.duration * (opts.backwards ? 1 - elementIndex/elementsLength : (elementIndex + 1) / elementsLength), opts.duration * 0.75, 200);
3793                        }
3794
3795                        /* 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
3796                           reduce the opts checking logic required inside the redirect. */
3797                        Velocity.Redirects[propertiesMap].call(element, element, opts || {}, elementIndex, elementsLength, elements, promiseData.promise ? promiseData : undefined);
3798                    });
3799
3800                    /* Since the animation logic resides within the redirect's own code, abort the remainder of this call.
3801                       (The performance overhead up to this point is virtually non-existant.) */
3802                    /* Note: The jQuery call chain is kept intact by returning the complete element set. */
3803                    return getChain();
3804                } else {
3805                    var abortError = "Velocity: First argument (" + propertiesMap + ") was not a property map, a known action, or a registered redirect. Aborting.";
3806
3807                    if (promiseData.promise) {
3808                        promiseData.rejecter(new Error(abortError));
3809                    } else {
3810                        console.log(abortError);
3811                    }
3812
3813                    return getChain();
3814                }
3815        }
3816
3817        /**************************
3818            Call-Wide Variables
3819        **************************/
3820
3821        /* A container for CSS unit conversion ratios (e.g. %, rem, and em ==> px) that is used to cache ratios across all elements
3822           being animated in a single Velocity call. Calculating unit ratios necessitates DOM querying and updating, and is therefore
3823           avoided (via caching) wherever possible. This container is call-wide instead of page-wide to avoid the risk of using stale
3824           conversion metrics across Velocity animations that are not immediately consecutively chained. */
3825        var callUnitConversionData = {
3826                lastParent: null,
3827                lastPosition: null,
3828                lastFontSize: null,
3829                lastPercentToPxWidth: null,
3830                lastPercentToPxHeight: null,
3831                lastEmToPx: null,
3832                remToPx: null,
3833                vwToPx: null,
3834                vhToPx: null
3835            };
3836
3837        /* A container for all the ensuing tween data and metadata associated with this call. This container gets pushed to the page-wide
3838           Velocity.State.calls array that is processed during animation ticking. */
3839        var call = [];
3840
3841        /************************
3842           Element Processing
3843        ************************/
3844
3845        /* 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):
3846           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.
3847           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.
3848           3) Pushing: Consolidation of the tween data followed by its push onto the global in-progress calls container.
3849        */
3850
3851        function processElement () {
3852
3853            /*************************
3854               Part I: Pre-Queueing
3855            *************************/
3856
3857            /***************************
3858               Element-Wide Variables
3859            ***************************/
3860
3861            var element = this,
3862                /* The runtime opts object is the extension of the current call's options and Velocity's page-wide option defaults. */
3863                opts = $.extend({}, Velocity.defaults, options),
3864                /* A container for the processed data associated with each property in the propertyMap.
3865                   (Each property in the map produces its own "tween".) */
3866                tweensContainer = {},
3867                elementUnitConversionData;
3868
3869            /******************
3870               Element Init
3871            ******************/
3872
3873            if (Data(element) === undefined) {
3874                Velocity.init(element);
3875            }
3876
3877            /******************
3878               Option: Delay
3879            ******************/
3880
3881            /* Since queue:false doesn't respect the item's existing queue, we avoid injecting its delay here (it's set later on). */
3882            /* Note: Velocity rolls its own delay function since jQuery doesn't have a utility alias for $.fn.delay()
3883               (and thus requires jQuery element creation, which we avoid since its overhead includes DOM querying). */
3884            if (parseFloat(opts.delay) && opts.queue !== false) {
3885                $.queue(element, opts.queue, function(next) {
3886                    /* 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. */
3887                    Velocity.velocityQueueEntryFlag = true;
3888
3889                    /* The ensuing queue item (which is assigned to the "next" argument that $.queue() automatically passes in) will be triggered after a setTimeout delay.
3890                       The setTimeout is stored so that it can be subjected to clearTimeout() if this animation is prematurely stopped via Velocity's "stop" command. */
3891                    Data(element).delayTimer = {
3892                        setTimeout: setTimeout(next, parseFloat(opts.delay)),
3893                        next: next
3894                    };
3895                });
3896            }
3897
3898            /*********************
3899               Option: Duration
3900            *********************/
3901
3902            /* Support for jQuery's named durations. */
3903            switch (opts.duration.toString().toLowerCase()) {
3904                case "fast":
3905                    opts.duration = 200;
3906                    break;
3907
3908                case "normal":
3909                    opts.duration = DURATION_DEFAULT;
3910                    break;
3911
3912                case "slow":
3913                    opts.duration = 600;
3914                    break;
3915
3916                default:
3917                    /* 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). */
3918                    opts.duration = parseFloat(opts.duration) || 1;
3919            }
3920
3921            /************************
3922               Global Option: Mock
3923            ************************/
3924
3925            if (Velocity.mock !== false) {
3926                /* In mock mode, all animations are forced to 1ms so that they occur immediately upon the next rAF tick.
3927                   Alternatively, a multiplier can be passed in to time remap all delays and durations. */
3928                if (Velocity.mock === true) {
3929                    opts.duration = opts.delay = 1;
3930                } else {
3931                    opts.duration *= parseFloat(Velocity.mock) || 1;
3932                    opts.delay *= parseFloat(Velocity.mock) || 1;
3933                }
3934            }
3935
3936            /*******************
3937               Option: Easing
3938            *******************/
3939
3940            opts.easing = getEasing(opts.easing, opts.duration);
3941
3942            /**********************
3943               Option: Callbacks
3944            **********************/
3945
3946            /* Callbacks must functions. Otherwise, default to null. */
3947            if (opts.begin && !Type.isFunction(opts.begin)) {
3948                opts.begin = null;
3949            }
3950
3951            if (opts.progress && !Type.isFunction(opts.progress)) {
3952                opts.progress = null;
3953            }
3954
3955            if (opts.complete && !Type.isFunction(opts.complete)) {
3956                opts.complete = null;
3957            }
3958
3959            /*********************************
3960               Option: Display & Visibility
3961            *********************************/
3962
3963            /* Refer to Velocity's documentation (VelocityJS.org/#displayAndVisibility) for a description of the display and visibility options' behavior. */
3964            /* Note: We strictly check for undefined instead of falsiness because display accepts an empty string value. */
3965            if (opts.display !== undefined && opts.display !== null) {
3966                opts.display = opts.display.toString().toLowerCase();
3967
3968                /* Users can pass in a special "auto" value to instruct Velocity to set the element to its default display value. */
3969                if (opts.display === "auto") {
3970                    opts.display = Velocity.CSS.Values.getDisplayType(element);
3971                }
3972            }
3973
3974            if (opts.visibility !== undefined && opts.visibility !== null) {
3975                opts.visibility = opts.visibility.toString().toLowerCase();
3976            }
3977
3978            /**********************
3979               Option: mobileHA
3980            **********************/
3981
3982            /* When set to true, and if this is a mobile device, mobileHA automatically enables hardware acceleration (via a null transform hack)
3983               on animating elements. HA is removed from the element at the completion of its animation. */
3984            /* 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. */
3985            /* Note: You can read more about the use of mobileHA in Velocity's documentation: VelocityJS.org/#mobileHA. */
3986            opts.mobileHA = (opts.mobileHA && Velocity.State.isMobile && !Velocity.State.isGingerbread);
3987
3988            /***********************
3989               Part II: Queueing
3990            ***********************/
3991
3992            /* 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.
3993               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. */
3994            /* 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,
3995               the call array is pushed to Velocity.State.calls for live processing by the requestAnimationFrame tick. */
3996            function buildQueue (next) {
3997
3998                /*******************
3999                   Option: Begin
4000                *******************/
4001
4002                /* 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. */
4003                if (opts.begin && elementsIndex === 0) {
4004                    /* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */
4005                    try {
4006                        opts.begin.call(elements, elements);
4007                    } catch (error) {
4008                        setTimeout(function() { throw error; }, 1);
4009                    }
4010                }
4011
4012                /*****************************************
4013                   Tween Data Construction (for Scroll)
4014                *****************************************/
4015
4016                /* 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. */
4017                if (action === "scroll") {
4018                    /* The scroll action uniquely takes an optional "offset" option -- specified in pixels -- that offsets the targeted scroll position. */
4019                    var scrollDirection = (/^x$/i.test(opts.axis) ? "Left" : "Top"),
4020                        scrollOffset = parseFloat(opts.offset) || 0,
4021                        scrollPositionCurrent,
4022                        scrollPositionCurrentAlternate,
4023                        scrollPositionEnd;
4024
4025                    /* Scroll also uniquely takes an optional "container" option, which indicates the parent element that should be scrolled --
4026                       as opposed to the browser window itself. This is useful for scrolling toward an element that's inside an overflowing parent element. */
4027                    if (opts.container) {
4028                        /* Ensure that either a jQuery object or a raw DOM element was passed in. */
4029                        if (Type.isWrapped(opts.container) || Type.isNode(opts.container)) {
4030                            /* Extract the raw DOM element from the jQuery wrapper. */
4031                            opts.container = opts.container[0] || opts.container;
4032                            /* Note: Unlike other properties in Velocity, the browser's scroll position is never cached since it so frequently changes
4033                               (due to the user's natural interaction with the page). */
4034                            scrollPositionCurrent = opts.container["scroll" + scrollDirection]; /* GET */
4035
4036                            /* $.position() values are relative to the container's currently viewable area (without taking into account the container's true dimensions
4037                               -- say, for example, if the container was not overflowing). Thus, the scroll end value is the sum of the child element's position *and*
4038                               the scroll container's current scroll position. */
4039                            /* Note: jQuery does not offer a utility alias for $.position(), so we have to incur jQuery object conversion here.
4040                               This syncs up with an ensuing batch of GETs, so it fortunately does not trigger layout thrashing. */
4041                            scrollPositionEnd = (scrollPositionCurrent + $(element).position()[scrollDirection.toLowerCase()]) + scrollOffset; /* GET */
4042                        /* 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. */
4043                        } else {
4044                            opts.container = null;
4045                        }
4046                    } else {
4047                        /* If the window itself is being scrolled -- not a containing element -- perform a live scroll position lookup using
4048                           the appropriate cached property names (which differ based on browser type). */
4049                        scrollPositionCurrent = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + scrollDirection]]; /* GET */
4050                        /* 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. */
4051                        scrollPositionCurrentAlternate = Velocity.State.scrollAnchor[Velocity.State["scrollProperty" + (scrollDirection === "Left" ? "Top" : "Left")]]; /* GET */
4052
4053                        /* Unlike $.position(), $.offset() values are relative to the browser window's true dimensions -- not merely its currently viewable area --
4054                           and therefore end values do not need to be compounded onto current values. */
4055                        scrollPositionEnd = $(element).offset()[scrollDirection.toLowerCase()] + scrollOffset; /* GET */
4056                    }
4057
4058                    /* Since there's only one format that scroll's associated tweensContainer can take, we create it manually. */
4059                    tweensContainer = {
4060                        scroll: {
4061                            rootPropertyValue: false,
4062                            startValue: scrollPositionCurrent,
4063                            currentValue: scrollPositionCurrent,
4064                            endValue: scrollPositionEnd,
4065                            unitType: "",
4066                            easing: opts.easing,
4067                            scrollData: {
4068                                container: opts.container,
4069                                direction: scrollDirection,
4070                                alternateValue: scrollPositionCurrentAlternate
4071                            }
4072                        },
4073                        element: element
4074                    };
4075
4076                    if (Velocity.debug) console.log("tweensContainer (scroll): ", tweensContainer.scroll, element);
4077
4078                /******************************************
4079                   Tween Data Construction (for Reverse)
4080                ******************************************/
4081
4082                /* Reverse acts like a "start" action in that a property map is animated toward. The only difference is
4083                   that the property map used for reverse is the inverse of the map used in the previous call. Thus, we manipulate
4084                   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. */
4085                /* 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.) */
4086                /* Note: Reverse calls do not need to be consecutively chained onto a currently-animating element in order to operate on cached values;
4087                   there is no harm to reverse being called on a potentially stale data cache since reverse's behavior is simply defined
4088                   as reverting to the element's values as they were prior to the previous *Velocity* call. */
4089                } else if (action === "reverse") {
4090                    /* Abort if there is no prior animation data to reverse to. */
4091                    if (!Data(element).tweensContainer) {
4092                        /* Dequeue the element so that this queue entry releases itself immediately, allowing subsequent queue entries to run. */
4093                        $.dequeue(element, opts.queue);
4094
4095                        return;
4096                    } else {
4097                        /*********************
4098                           Options Parsing
4099                        *********************/
4100
4101                        /* If the element was hidden via the display option in the previous call,
4102                           revert display to "auto" prior to reversal so that the element is visible again. */
4103                        if (Data(element).opts.display === "none") {
4104                            Data(element).opts.display = "auto";
4105                        }
4106
4107                        if (Data(element).opts.visibility === "hidden") {
4108                            Data(element).opts.visibility = "visible";
4109                        }
4110
4111                        /* If the loop option was set in the previous call, disable it so that "reverse" calls aren't recursively generated.
4112                           Further, remove the previous call's callback options; typically, users do not want these to be refired. */
4113                        Data(element).opts.loop = false;
4114                        Data(element).opts.begin = null;
4115                        Data(element).opts.complete = null;
4116
4117                        /* Since we're extending an opts object that has already been extended with the defaults options object,
4118                           we remove non-explicitly-defined properties that are auto-assigned values. */
4119                        if (!options.easing) {
4120                            delete opts.easing;
4121                        }
4122
4123                        if (!options.duration) {
4124                            delete opts.duration;
4125                        }
4126
4127                        /* The opts object used for reversal is an extension of the options object optionally passed into this
4128                           reverse call plus the options used in the previous Velocity call. */
4129                        opts = $.extend({}, Data(element).opts, opts);
4130
4131                        /*************************************
4132                           Tweens Container Reconstruction
4133                        *************************************/
4134
4135                        /* Create a deepy copy (indicated via the true flag) of the previous call's tweensContainer. */
4136                        var lastTweensContainer = $.extend(true, {}, Data(element).tweensContainer);
4137
4138                        /* Manipulate the previous tweensContainer by replacing its end values and currentValues with its start values. */
4139                        for (var lastTween in lastTweensContainer) {
4140                            /* In addition to tween data, tweensContainers contain an element property that we ignore here. */
4141                            if (lastTween !== "element") {
4142                                var lastStartValue = lastTweensContainer[lastTween].startValue;
4143
4144                                lastTweensContainer[lastTween].startValue = lastTweensContainer[lastTween].currentValue = lastTweensContainer[lastTween].endValue;
4145                                lastTweensContainer[lastTween].endValue = lastStartValue;
4146
4147                                /* Easing is the only option that embeds into the individual tween data (since it can be defined on a per-property basis).
4148                                   Accordingly, every property's easing value must be updated when an options object is passed in with a reverse call.
4149                                   The side effect of this extensibility is that all per-property easing values are forcefully reset to the new value. */
4150                                if (!Type.isEmptyObject(options)) {
4151                                    lastTweensContainer[lastTween].easing = opts.easing;
4152                                }
4153
4154                                if (Velocity.debug) console.log("reverse tweensContainer (" + lastTween + "): " + JSON.stringify(lastTweensContainer[lastTween]), element);
4155                            }
4156                        }
4157
4158                        tweensContainer = lastTweensContainer;
4159                    }
4160
4161                /*****************************************
4162                   Tween Data Construction (for Start)
4163                *****************************************/
4164
4165                } else if (action === "start") {
4166
4167                    /*************************
4168                        Value Transferring
4169                    *************************/
4170
4171                    /* If this queue entry follows a previous Velocity-initiated queue entry *and* if this entry was created
4172                       while the element was in the process of being animated by Velocity, then this current call is safe to use
4173                       the end values from the prior call as its start values. Velocity attempts to perform this value transfer
4174                       process whenever possible in order to avoid requerying the DOM. */
4175                    /* If values aren't transferred from a prior call and start values were not forcefed by the user (more on this below),
4176                       then the DOM is queried for the element's current values as a last resort. */
4177                    /* Note: Conversely, animation reversal (and looping) *always* perform inter-call value transfers; they never requery the DOM. */
4178                    var lastTweensContainer;
4179
4180                    /* The per-element isAnimating flag is used to indicate whether it's safe (i.e. the data isn't stale)
4181                       to transfer over end values to use as start values. If it's set to true and there is a previous
4182                       Velocity call to pull values from, do so. */
4183                    if (Data(element).tweensContainer && Data(element).isAnimating === true) {
4184                        lastTweensContainer = Data(element).tweensContainer;
4185                    }
4186
4187                    /***************************
4188                       Tween Data Calculation
4189                    ***************************/
4190
4191                    /* This function parses property data and defaults endValue, easing, and startValue as appropriate. */
4192                    /* Property map values can either take the form of 1) a single value representing the end value,
4193                       or 2) an array in the form of [ endValue, [, easing] [, startValue] ].
4194                       The optional third parameter is a forcefed startValue to be used instead of querying the DOM for
4195                       the element's current value. Read Velocity's docmentation to learn more about forcefeeding: VelocityJS.org/#forcefeeding */
4196                    function parsePropertyValue (valueData, skipResolvingEasing) {
4197                        var endValue = undefined,
4198                            easing = undefined,
4199                            startValue = undefined;
4200
4201                        /* Handle the array format, which can be structured as one of three potential overloads:
4202                           A) [ endValue, easing, startValue ], B) [ endValue, easing ], or C) [ endValue, startValue ] */
4203                        if (Type.isArray(valueData)) {
4204                            /* endValue is always the first item in the array. Don't bother validating endValue's value now
4205                               since the ensuing property cycling logic does that. */
4206                            endValue = valueData[0];
4207
4208                            /* Two-item array format: If the second item is a number, function, or hex string, treat it as a
4209                               start value since easings can only be non-hex strings or arrays. */
4210                            if ((!Type.isArray(valueData[1]) && /^[\d-]/.test(valueData[1])) || Type.isFunction(valueData[1]) || CSS.RegEx.isHex.test(valueData[1])) {
4211                                startValue = valueData[1];
4212                            /* Two or three-item array: If the second item is a non-hex string or an array, treat it as an easing. */
4213                            } else if ((Type.isString(valueData[1]) && !CSS.RegEx.isHex.test(valueData[1])) || Type.isArray(valueData[1])) {
4214                                easing = skipResolvingEasing ? valueData[1] : getEasing(valueData[1], opts.duration);
4215
4216                                /* Don't bother validating startValue's value now since the ensuing property cycling logic inherently does that. */
4217                                if (valueData[2] !== undefined) {
4218                                    startValue = valueData[2];
4219                                }
4220                            }
4221                        /* Handle the single-value format. */
4222                        } else {
4223                            endValue = valueData;
4224                        }
4225
4226                        /* Default to the call's easing if a per-property easing type was not defined. */
4227                        if (!skipResolvingEasing) {
4228                            easing = easing || opts.easing;
4229                        }
4230
4231                        /* If functions were passed in as values, pass the function the current element as its context,
4232                           plus the element's index and the element set's size as arguments. Then, assign the returned value. */
4233                        if (Type.isFunction(endValue)) {
4234                            endValue = endValue.call(element, elementsIndex, elementsLength);
4235                        }
4236
4237                        if (Type.isFunction(startValue)) {
4238                            startValue = startValue.call(element, elementsIndex, elementsLength);
4239                        }
4240
4241                        /* Allow startValue to be left as undefined to indicate to the ensuing code that its value was not forcefed. */
4242                        return [ endValue || 0, easing, startValue ];
4243                    }
4244
4245                    /* Cycle through each property in the map, looking for shorthand color properties (e.g. "color" as opposed to "colorRed"). Inject the corresponding
4246                       colorRed, colorGreen, and colorBlue RGB component tweens into the propertiesMap (which Velocity understands) and remove the shorthand property. */
4247                    $.each(propertiesMap, function(property, value) {
4248                        /* Find shorthand color properties that have been passed a hex string. */
4249                        if (RegExp("^" + CSS.Lists.colors.join("$|^") + "$").test(property)) {
4250                            /* Parse the value data for each shorthand. */
4251                            var valueData = parsePropertyValue(value, true),
4252                                endValue = valueData[0],
4253                                easing = valueData[1],
4254                                startValue = valueData[2];
4255
4256                            if (CSS.RegEx.isHex.test(endValue)) {
4257                                /* Convert the hex strings into their RGB component arrays. */
4258                                var colorComponents = [ "Red", "Green", "Blue" ],
4259                                    endValueRGB = CSS.Values.hexToRgb(endValue),
4260                                    startValueRGB = startValue ? CSS.Values.hexToRgb(startValue) : undefined;
4261
4262                                /* Inject the RGB component tweens into propertiesMap. */
4263                                for (var i = 0; i < colorComponents.length; i++) {
4264                                    var dataArray = [ endValueRGB[i] ];
4265
4266                                    if (easing) {
4267                                        dataArray.push(easing);
4268                                    }
4269
4270                                    if (startValueRGB !== undefined) {
4271                                        dataArray.push(startValueRGB[i]);
4272                                    }
4273
4274                                    propertiesMap[property + colorComponents[i]] = dataArray;
4275                                }
4276
4277                                /* Remove the intermediary shorthand property entry now that we've processed it. */
4278                                delete propertiesMap[property];
4279                            }
4280                        }
4281                    });
4282
4283                    /* Create a tween out of each property, and append its associated data to tweensContainer. */
4284                    for (var property in propertiesMap) {
4285
4286                        /**************************
4287                           Start Value Sourcing
4288                        **************************/
4289
4290                        /* Parse out endValue, easing, and startValue from the property's data. */
4291                        var valueData = parsePropertyValue(propertiesMap[property]),
4292                            endValue = valueData[0],
4293                            easing = valueData[1],
4294                            startValue = valueData[2];
4295
4296                        /* Now that the original property name's format has been used for the parsePropertyValue() lookup above,
4297                           we force the property to its camelCase styling to normalize it for manipulation. */
4298                        property = CSS.Names.camelCase(property);
4299
4300                        /* 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. */
4301                        var rootProperty = CSS.Hooks.getRoot(property),
4302                            rootPropertyValue = false;
4303
4304                        /* Properties that are not supported by the browser (and do not have an associated normalization) will
4305                           inherently produce no style changes when set, so they are skipped in order to decrease animation tick overhead.
4306                           Property support is determined via prefixCheck(), which returns a false flag when no supported is detected. */
4307                        /* Note: Since SVG elements have some of their properties directly applied as HTML attributes,
4308                           there is no way to check for their explicit browser support, and so we skip skip this check for them. */
4309                        if (!Data(element).isSVG && CSS.Names.prefixCheck(rootProperty)[1] === false && CSS.Normalizations.registered[rootProperty] === undefined) {
4310                            if (Velocity.debug) console.log("Skipping [" + rootProperty + "] due to a lack of browser support.");
4311
4312                            continue;
4313                        }
4314
4315                        /* If the display option is being set to a non-"none" (e.g. "block") and opacity (filter on IE<=8) is being
4316                           animated to an endValue of non-zero, the user's intention is to fade in from invisible, thus we forcefeed opacity
4317                           a startValue of 0 if its startValue hasn't already been sourced by value transferring or prior forcefeeding. */
4318                        if (((opts.display !== undefined && opts.display !== null && opts.display !== "none") || (opts.visibility !== undefined && opts.visibility !== "hidden")) && /opacity|filter/.test(property) && !startValue && endValue !== 0) {
4319                            startValue = 0;
4320                        }
4321
4322                        /* If values have been transferred from the previous Velocity call, extract the endValue and rootPropertyValue
4323                           for all of the current call's properties that were *also* animated in the previous call. */
4324                        /* Note: Value transferring can optionally be disabled by the user via the _cacheValues option. */
4325                        if (opts._cacheValues && lastTweensContainer && lastTweensContainer[property]) {
4326                            if (startValue === undefined) {
4327                                startValue = lastTweensContainer[property].endValue + lastTweensContainer[property].unitType;
4328                            }
4329
4330                            /* The previous call's rootPropertyValue is extracted from the element's data cache since that's the
4331                               instance of rootPropertyValue that gets freshly updated by the tweening process, whereas the rootPropertyValue
4332                               attached to the incoming lastTweensContainer is equal to the root property's value prior to any tweening. */
4333                            rootPropertyValue = Data(element).rootPropertyValueCache[rootProperty];
4334                        /* If values were not transferred from a previous Velocity call, query the DOM as needed. */
4335                        } else {
4336                            /* Handle hooked properties. */
4337                            if (CSS.Hooks.registered[property]) {
4338                               if (startValue === undefined) {
4339                                    rootPropertyValue = CSS.getPropertyValue(element, rootProperty); /* GET */
4340                                    /* Note: The following getPropertyValue() call does not actually trigger a DOM query;
4341                                       getPropertyValue() will extract the hook from rootPropertyValue. */
4342                                    startValue = CSS.getPropertyValue(element, property, rootPropertyValue);
4343                                /* If startValue is already defined via forcefeeding, do not query the DOM for the root property's value;
4344                                   just grab rootProperty's zero-value template from CSS.Hooks. This overwrites the element's actual
4345                                   root property value (if one is set), but this is acceptable since the primary reason users forcefeed is
4346                                   to avoid DOM queries, and thus we likewise avoid querying the DOM for the root property's value. */
4347                                } else {
4348                                    /* Grab this hook's zero-value template, e.g. "0px 0px 0px black". */
4349                                    rootPropertyValue = CSS.Hooks.templates[rootProperty][1];
4350                                }
4351                            /* Handle non-hooked properties that haven't already been defined via forcefeeding. */
4352                            } else if (startValue === undefined) {
4353                                startValue = CSS.getPropertyValue(element, property); /* GET */
4354                            }
4355                        }
4356
4357                        /**************************
4358                           Value Data Extraction
4359                        **************************/
4360
4361                        var separatedValue,
4362                            endValueUnitType,
4363                            startValueUnitType,
4364                            operator = false;
vendor: 4,539 bytes, lines 4365-4440
4365
4366                        /* Separates a property value into its numeric value and its unit type. */
4367                        function separateValue (property, value) {
4368                            var unitType,
4369                                numericValue;
4370
4371                            numericValue = (value || "0")
4372                                .toString()
4373                                .toLowerCase()
4374                                /* Match the unit type at the end of the value. */
4375                                .replace(/[%A-z]+$/, function(match) {
4376                                    /* Grab the unit type. */
4377                                    unitType = match;
4378
4379                                    /* Strip the unit type off of value. */
4380                                    return "";
4381                                });
4382
4383                            /* If no unit type was supplied, assign one that is appropriate for this property (e.g. "deg" for rotateZ or "px" for width). */
4384                            if (!unitType) {
4385                                unitType = CSS.Values.getUnitType(property);
4386                            }
4387
4388                            return [ numericValue, unitType ];
4389                        }
4390
4391                        /* Separate startValue. */
4392                        separatedValue = separateValue(property, startValue);
4393                        startValue = separatedValue[0];
4394                        startValueUnitType = separatedValue[1];
4395
4396                        /* Separate endValue, and extract a value operator (e.g. "+=", "-=") if one exists. */
4397                        separatedValue = separateValue(property, endValue);
4398                        endValue = separatedValue[0].replace(/^([+-\/*])=/, function(match, subMatch) {
4399                            operator = subMatch;
4400
4401                            /* Strip the operator off of the value. */
4402                            return "";
4403                        });
4404                        endValueUnitType = separatedValue[1];
4405
4406                        /* Parse float values from endValue and startValue. Default to 0 if NaN is returned. */
4407                        startValue = parseFloat(startValue) || 0;
4408                        endValue = parseFloat(endValue) || 0;
4409
4410                        /***************************************
4411                           Property-Specific Value Conversion
4412                        ***************************************/
4413
4414                        /* Custom support for properties that don't actually accept the % unit type, but where pollyfilling is trivial and relatively foolproof. */
4415                        if (endValueUnitType === "%") {
4416                            /* A %-value fontSize/lineHeight is relative to the parent's fontSize (as opposed to the parent's dimensions),
4417                               which is identical to the em unit's behavior, so we piggyback off of that. */
4418                            if (/^(fontSize|lineHeight)$/.test(property)) {
4419                                /* Convert % into an em decimal value. */
4420                                endValue = endValue / 100;
4421                                endValueUnitType = "em";
4422                            /* For scaleX and scaleY, convert the value into its decimal format and strip off the unit type. */
4423                            } else if (/^scale/.test(property)) {
4424                                endValue = endValue / 100;
4425                                endValueUnitType = "";
4426                            /* For RGB components, take the defined percentage of 255 and strip off the unit type. */
4427                            } else if (/(Red|Green|Blue)$/i.test(property)) {
4428                                endValue = (endValue / 100) * 255;
4429                                endValueUnitType = "";
4430                            }
4431                        }
4432
4433                        /***************************
4434                           Unit Ratio Calculation
4435                        ***************************/
4436
4437                        /* When queried, the browser returns (most) CSS property values in pixels. Therefore, if an endValue with a unit type of
4438                           %, em, or rem is animated toward, startValue must be converted from pixels into the same unit type as endValue in order
4439                           for value manipulation logic (increment/decrement) to proceed. Further, if the startValue was forcefed or transferred
4440                           from a previous call, startValue may al
4440so not be in pixels. Unit conversion logic therefore consists of two steps:
4441                           1) Calculating the ratio of %/em/rem/vh/vw relative to pixels
4442                           2) Converting startValue into the same unit of measurement as endValue based on these ratios. */
4443                        /* Unit conversion ratios are calculated by inserting a sibling node next to the target node, copying over its position property,
4444                           setting values with the target unit type then comparing the returned pixel value. */
4445                        /* Note: Even if only one of these unit types is being animated, all unit ratios are calculated at once since the overhead
4446                           of batching the SETs and GETs together upfront outweights the potential overhead
4447                           of layout thrashing caused by re-querying for uncalculated ratios for subsequently-processed properties. */
4448                        /* Todo: Shift this logic into the calls' first tick instance so that it's synced with RAF. */
4449                        function calculateUnitRatios () {
4450
4451                            /************************
4452                                Same Ratio Checks
4453                            ************************/
4454
4455                            /* The properties below are used to determine whether the element differs sufficiently from this call's
4456                               previously iterated element to also differ in its unit conversion ratios. If the properties match up with those
4457                               of the prior element, the prior element's conversion ratios are used. Like most optimizations in Velocity,
4458                               this is done to minimize DOM querying. */
4459                            var sameRatioIndicators = {
4460                                    myParent: element.parentNode || document.body, /* GET */
4461                                    position: CSS.getPropertyValue(element, "position"), /* GET */
4462                                    fontSize: CSS.getPropertyValue(element, "fontSize") /* GET */
4463                                },
4464                                /* Determine if the same % ratio can be used. % is based on the element's position value and its parent's width and height dimensions. */
4465                                samePercentRatio = ((sameRatioIndicators.position === callUnitConversionData.lastPosition) && (sameRatioIndicators.myParent === callUnitConversionData.lastParent)),
4466                                /* Determine if the same em ratio can be used. em is relative to the element's fontSize. */
4467                                sameEmRatio = (sameRatioIndicators.fontSize === callUnitConversionData.lastFontSize);
4468
4469                            /* Store these ratio indicators call-wide for the next element to compare against. */
4470                            callUnitConversionData.lastParent = sameRatioIndicators.myParent;
4471                            callUnitConversionData.lastPosition = sameRatioIndicators.position;
4472                            callUnitConversionData.lastFontSize = sameRatioIndicators.fontSize;
4473
4474                            /***************************
4475                               Element-Specific Units
4476                            ***************************/
4477
4478                            /* Note: IE8 rounds to the nearest pixel when returning CSS values, thus we perform conversions using a measurement
4479                               of 100 (instead of 1) to give our ratios a precision of at least 2 decimal values. */
4480                            var measurement = 100,
4481                                unitRatios = {};
4482
4483                            if (!sameEmRatio || !samePercentRatio) {
4484                                var dummy = Data(element).isSVG ? document.createElementNS("http://www.w3.org/2000/svg", "rect") : document.createElement("div");
4485
4486                                Velocity.init(dummy);
4487                                sameRatioIndicators.myParent.appendChild(dummy);
4488
4489                                /* To accurately and consistently calculate conversion ratios, the element's cascaded overflow and box-sizing are stripped.
4490                                   Similarly, since width/height can be artificially constrained by their min-/max- equivalents, these are controlled for as well. */
4491                                /* Note: Overflow must be also be c
4491ontrolled for per-axis since the overflow property overwrites its per-axis values. */
4492                                $.each([ "overflow", "overflowX", "overflowY" ], function(i, property) {
4493                                    Velocity.CSS.setPropertyValue(dummy, property, "hidden");
4494                                });
4495                                Velocity.CSS.setPropertyValue(dummy, "position", sameRatioIndicators.position);
4496                                Velocity.CSS.setPropertyValue(dummy, "fontSize", sameRatioIndicators.fontSize);
4497                                Velocity.CSS.setPropertyValue(dummy, "boxSizing", "content-box");
4498
4499                                /* width and height act as our proxy properties for measuring the horizontal and vertical % ratios. */
4500                                $.each([ "minWidth", "maxWidth", "width", "minHeight", "maxHeight", "height" ], function(i, property) {
4501                                    Velocity.CSS.setPropertyValue(dummy, property, measurement + "%");
4502                                });
4503                                /* paddingLeft arbitrarily acts as our proxy property for the em ratio. */
4504                                Velocity.CSS.setPropertyValue(dummy, "paddingLeft", measurement + "em");
4505
4506                                /* 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. */
4507                                unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth = (parseFloat(CSS.getPropertyValue(dummy, "width", null, true)) || 1) / measurement; /* GET */
4508                                unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight = (parseFloat(CSS.getPropertyValue(dummy, "height", null, true)) || 1) / measurement; /* GET */
4509                                unitRatios.emToPx = callUnitConversionData.lastEmToPx = (parseFloat(CSS.getPropertyValue(dummy, "paddingLeft")) || 1) / measurement; /* GET */
4510
4511                                sameRatioIndicators.myParent.removeChild(dummy);
4512                            } else {
4513                                unitRatios.emToPx = callUnitConversionData.lastEmToPx;
4514                                unitRatios.percentToPxWidth = callUnitConversionData.lastPercentToPxWidth;
4515                                unitRatios.percentToPxHeight = callUnitConversionData.lastPercentToPxHeight;
4516                            }
4517
4518                            /***************************
4519                               Element-Agnostic Units
4520                            ***************************/
4521
4522                            /* Whereas % and em ratios are determined on a per-element basis, the rem unit only needs to be checked
4523                               once per call since it's exclusively dependant upon document.body's fontSize. If this is the first time
4524                               that calculateUnitRatios() is being run during this call, remToPx will still be set to its default value of null,
4525                               so we calculate it now. */
4526                            if (callUnitConversionData.remToPx === null) {
4527                                /* Default to browsers' default fontSize of 16px in the case of 0. */
4528                                callUnitConversionData.remToPx = parseFloat(CSS.getPropertyValue(document.body, "fontSize")) || 16; /* GET */
4529                            }
4530
4531                            /* Similarly, viewport units are %-relative to the window's inner dimensions. */
4532                            if (callUnitConversionData.vwToPx === null) {
4533                                callUnitConversionData.vwToPx = parseFloat(window.innerWidth) / 100; /* GET */
4534                                callUnitConversionData.vhToPx = parseFloat(window.innerHeight) / 100; /* GET */
4535                            }
4536
4537                            unitRatios.remToPx = callUnitConversionData.remToPx;
4538                            unitRatios.vwToPx = callUnitConversionData.vwToPx;
4539                            unitRatios.vhToPx = callUnitConversionData.vhToPx;
4540
4541                            if (Velocity.debug >= 1) console.log("Unit ratios: " + JSON.stringify(unitRatios), element);
4542
4543                            return unitRatios;
4544                        }
4545
4546                        /********************
4547                           Unit Conversion
4548                        ********************/
4549
4550                        /* The * and / operators, which are not passed in with an associated unit, inherently use startValue's unit. Skip value and unit conversion. */
4551                        if (/[\/*]/.test(operator)) {
4552                            endValueUnitType = startValueUnitType;
4553                        /* If startValue and endValue differ in unit type, convert startValue into the same unit type as endValue so that if endValueUnitType
4554                           is a relative unit (%, em, rem), the values set during tweening will continue to be accurately relative even if the metrics they depen
4554d
4555                           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
4556                           would become stale if the original unit being animated toward was relative and the underlying metrics change during the animation. */
4557                        /* Since 0 is 0 in any unit type, no conversion is necessary when startValue is 0 -- we just start at 0 with endValueUnitType. */
4558                        } else if ((startValueUnitType !== endValueUnitType) && startValue !== 0) {
4559                            /* Unit conversion is also skipped when endValue is 0, but *startValueUnitType* must be used for tween values to remain accurate. */
4560                            /* Note: Skipping unit conversion here means that if endValueUnitType was originally a relative unit, the animation won't relatively
4561                               match the underlying metrics if they change, but this is acceptable since we're animating toward invisibility instead of toward visibility,
4562                               which remains past the point of the animation's completion. */
4563                            if (endValue === 0) {
4564                                endValueUnitType = startValueUnitType;
4565                            } else {
4566                                /* By this point, we cannot avoid unit conversion (it's undesirable since it causes layout thrashing).
4567                                   If we haven't already, we trigger calculateUnitRatios(), which runs once per element per call. */
4568                                elementUnitConversionData = elementUnitConversionData || calculateUnitRatios();
4569
4570                                /* The following RegEx matches CSS properties that have their % values measured relative to the x-axis. */
4571                                /* 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. */
4572                                var axis = (/margin|padding|left|right|width|text|word|letter/i.test(property) || /X$/.test(property) || property === "x") ? "x" : "y";
4573
4574                                /* In order to avoid generating n^2 bespoke conversion functions, unit conversion is a two-step process:
4575                                   1) Convert startValue into pixels. 2) Convert this new pixel value into endValue's unit type. */
4576                                switch (startValueUnitType) {
4577                                    case "%":
4578                                        /* Note: translateX and translateY are the only properties that are %-relative to an element's own dimensions -- not its parent's dimensions.
4579                                           Velocity does not include a special conversion process to account for this behavior. Therefore, animating translateX/Y from a % value
4580                                           to a non-% value will produce an incorrect start value. Fortunately, this sort of cross-unit conversion is rarely done by users in practice. */
4581                                        startValue *= (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight);
4582                                        break;
4583
4584                                    case "px":
4585                                        /* px acts as our midpoint in the unit conversion process; do nothing. */
4586                                        break;
4587
4588                                    default:
4589                                        startValue *= elementUnitConversionData[startValueUnitType + "ToPx"];
4590                                }
4591
4592                                /* Invert the px ratios to convert into to the target unit. */
4593                                switch (endValueUnitType) {
4594                                    case "%":
4595                                        startValue *= 1 / (axis === "x" ? elementUnitConversionData.percentToPxWidth : elementUnitConversionData.percentToPxHeight);
4596                                        break;
4597
4598                                    case "px":
4599                                        /* startValue is already in px, do nothing; we're done. */
4600                                        break;
4601
4602                                    default:
4603                                        startValue *= 1 / elementUnitConversionData[endValueUnitType + "ToPx"];
4604                                }
4605                            }
4606                        }
4607
4608                        /*********************
4609                           Relative Values
4610                        *********************/
4611
4612                        /* Operator logic must be performed last since it requires unit-normalized start and end values. */
4613                        /* Note: Relative *percent values* do not behave how most people think; while one would expect "+=50%"
4614                           to increase the property 1.5x its current value, it in fact increases the percent units in absolute terms:
4615                           50 points is added on top of the current % value. */
4616                        switch (operator) {
4617                            case "+":
4618                                endValue = startValue + endValue;
4619                                break;
4620
4621                            case "-":
4622                                endValue = startValue - endValue;
4623                                break;
4624
4625                            case "*":
4626                                endValue = startValue * endValue;
4627                                break;
4628
4629                            case "/":
4630                                endValue = startValue / endValue;
4631                                break;
4632                        }
4633
4634                        /**************************
4635                           tweensContainer Push
4636                        **************************/
4637
4638                        /* Construct the per-property tween object, and push it to the element's tweensContainer. */
4639                        tweensContainer[property] = {
4640                            rootPropertyValue: rootPropertyValue,
4641                            startValue: startValue,
4642                            currentValue: startValue,
4643                            endValue: endValue,
4644                            unitType: endValueUnitType,
4645                            easing: easing
4646                        };
4647
4648                        if (Velocity.debug) console.log("tweensContainer (" + property + "): " + JSON.stringify(tweensContainer[property]), element);
4649                    }
4650
4651                    /* Along with its property data, store a reference to the element itself onto tweensContainer. */
4652                    tweensContainer.element = element;
4653                }
4654
4655                /*****************
4656                    Call Push
4657                *****************/
4658
4659                /* Note: tweensContainer can be empty if all of the properties in this call's property map were skipped due to not
4660                   being supported by the browser. The element property is used for checking that the tweensContainer has been appended to. */
4661                if (tweensContainer.element) {
4662                    /* Apply the "velocity-animating" indicator class. */
4663                    CSS.Values.addClass(element, "velocity-animating");
4664
4665                    /* The call array houses the tweensContainers for each element being animated in the current call. */
4666                    call.push(tweensContainer);
4667
4668                    /* Store the tweensContainer and options if we're working on the default effects queue, so that they can be used by the reverse command. */
4669                    if (opts.queue === "") {
4670                        Data(element).tweensContainer = tweensContainer;
4671                        Data(element).opts = opts;
4672                    }
4673
4674                    /* Switch on the element's animating flag. */
4675                    Data(element).isAnimating = true;
4676
4677                    /* Once the final element in this call's element set has been processed, push the call array onto
4678                       Velocity.State.calls for the animation tick to immediately begin processing. */
4679                    if (elementsIndex === elementsLength - 1) {
4680                        /* To speed up iterating over this array, it is compacted (falsey items -- calls that have completed -- are removed)
4681                           when its length has ballooned to a point that can impact tick performance. This only becomes necessary when animation
4682                           has been continuous with many elements over a long period of time; whenever all active calls are completed, completeCall() clears Velocity.State.calls. */
4683                        if (Velocity.State.calls.length > 10000) {
4684                            Velocity.State.calls = compactSparseArray(Velocity.State.calls);
4685                        }
4686
4687                        /* Add the current call plus its associated metadata (the element set and the call's options) onto the global call container.
4688                           Anything on this call container is subjected to tick() processing. */
4689                        Velocity.State.calls.push([ call, elements, opts, null, promiseData.resolver ]);
4690
4691                        /* If the animation tick isn't running, start it. (Velocity shuts it off when there are no active calls to process.) */
4692                        if (Velocity.State.isTicking === false) {
4693                            Velocity.State.isTicking = true;
4694
4695                            /* Start the tick loop. */
4696                            tick();
4697                        }
4698                    } else {
4699                        elementsIndex++;
4700                    }
4701                }
4702            }
4703
4704            /* When the queue option is set to false, the call skips the element's queue and fires immediately. */
4705            if (opts.queue === false) {
4706                /* Since this buildQueue call doesn't respect the element's existing queue (which is where a delay option would have been appended),
4707                   we manually inject the delay property here with an explicit setTimeout. */
4708                if (opts.delay) {
4709                    setTimeout(buildQueue, opts.delay);
4710                } else {
4711                    buildQueue();
4712                }
4713            /* Otherwise, the call undergoes element queueing as normal. */
4714            /* Note: To interoperate with jQuery, Velocity uses jQuery's own $.queue() stack for queuing logic. */
4715            } else {
4716                $.queue(element, opts.queue, function(next, clearQueue) {
4717                    /* If the clearQueue flag was passed in by the stop command, resolve this call's promise. (Promises can only be resolved once,
4718                       so it's fine if this is repeatedly triggered for each element in the associated call.) */
4719                    if (clearQueue === true) {
4720                        if (promiseData.promise) {
4721                            promiseData.resolver(elements);
4722                        }
4723
4724                        /* Do not continue with animation queueing. */
4725                        return true;
4726                    }
4727
4728                    /* This flag indicates to the upcoming completeCall() function that this queue entry was initiated by Velocity.
4729                       See completeCall() for further details. */
4730                    Velocity.velocityQueueEntryFlag = true;
4731
4732                    buildQueue(next);
4733                });
4734            }
4735
4736            /*********************
4737                Auto-Dequeuing
4738            *********************/
4739
4740            /* As per jQuery's $.queue() behavior, to fire the first non-custom-queue entry on an element, the element
4741               must be dequeued if its queue stack consists *solely* of the current call. (This can be determined by checking
4742               for the "inprogress" item that jQuery prepends to active queue stack arrays.) Regardless, whenever the element's
4743               queue is further appended with additional items -- including $.delay()'s or even $.animate() calls, the queue's
4744               first entry is automatically fired. This behavior contrasts that of custom queues, which never auto-fire. */
4745            /* Note: When an element set is being subjected to a non-parallel Velocity call, the animation will not begin until
4746               each one of the elements in the set has reached the end of its individually pre-existing queue chain. */
4747            /* Note: Unfortunately, most people don't fully grasp jQuery's powerful, yet quirky, $.queue() function.
4748               Lean more here: http://stackoverflow.com/questions/1058158/can-somebody-explain-jquery-queue-to-me */
4749            if ((opts.queue === "" || opts.queue === "fx") && $.queue(element)[0] !== "inprogress") {
4750                $.dequeue(element);
4751            }
4752        }
4753
4754        /**************************
4755           Element Set Iteration
4756        **************************/
4757
4758        /* If the "nodeType" property exists on the elements variable, we're animating a single element.
4759           Place it in an array so that $.each() can iterate over it. */
4760        $.each(elements, function(i, element) {
4761            /* Ensure each element in a set has a nodeType (is a real element) to avoid throwing errors. */
4762            if (Type.isNode(element)) {
4763                processElement.call(element);
4764            }
4765        });
4766
4767        /******************
4768           Option: Loop
4769        ******************/
4770
4771        /* The loop option accepts an integer indicating how many times the element should loop between the values in the
4772           current call's properties map and the element's property values prior to this call. */
4773        /* Note: The loop option's logic is performed here -- after element processing -- because the current call needs
4774           to undergo its queue insertion prior to the loop option generating its series of constituent "reverse" calls,
4775           which chain after the current call. Two reverse calls (two "alternations") constitute one loop. */
4776        var opts = $.extend({}, Velocity.defaults, options),
4777            reverseCallsCount;
4778
4779        opts.loop = parseInt(opts.loop);
4780        reverseCallsCount = (opts.loop * 2) - 1;
4781
4782        if (opts.loop) {
4783            /* Double the loop count to convert it into its appropriate number of "reverse" calls.
4784               Subtract 1 from the resulting value since the current call is included in the total alternation count. */
4785            for (var x = 0; x < reverseCallsCount; x++) {
4786                /* Since the logic for the reverse action occurs inside Queueing and therefore this call's options object
4787                   isn't parsed until then as well, the current call's delay option must be explicitly passed into the reverse
4788                   call so that the delay logic that occurs inside *Pre-Queueing* can process it. */
4789                var reverseOptions = {
4790                    delay: opts.delay,
4791                    progress: opts.progress
4792                };
4793
4794                /* If a complete callback was passed into this call, transfer it to the loop redirect's final "reverse" call
4795                   so that it's triggered when the entire redirect is complete (and not when the very first animation is complete). */
4796                if (x === reverseCallsCount - 1) {
4797                    reverseOptions.display = opts.display;
4798                    reverseOptions.visibility = opts.visibility;
4799                    reverseOptions.complete = opts.complete;
4800                }
4801
4802                animate(elements, "reverse", reverseOptions);
4803            }
4804        }
4805
4806        /***************
4807            Chaining
4808        ***************/
4809
4810        /* Return the elements back to the call chain, with wrapped elements taking precedence in case Velocity was called via the $.fn. extension. */
4811        return getChain();
4812    };
4813
4814    /* Turn Velocity into the animation function, extended with the pre-existing Velocity object. */
4815    Velocity = $.extend(animate, Velocity);
4816    /* For legacy support, also expose the literal animate method. */
4817    Velocity.animate = animate;
4818
4819    /**************
4820        Timing
4821    **************/
4822
4823    /* Ticker function. */
4824    var ticker = window.requestAnimationFrame || rAFShim;
4825
4826    /* Inactive browser tabs pause rAF, which results in all active animations immediately sprinting to their completion states when the tab refocuses.
4827       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
4828       devices to avoid wasting battery power on inactive tabs. */
4829    /* 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. */
4830    if (!Velocity.State.isMobile && document.hidden !== undefined) {
4831        document.addEventListener("visibilitychange", function() {
4832            /* Reassign the rAF function (which the global tick() function uses) based on the tab's focus state. */
4833            if (document.hidden) {
4834                ticker = function(callback) {
4835                    /* The tick function needs a truthy first argument in order to pass its internal timestamp check. */
4836                    return setTimeout(function() { callback(true) }, 16);
4837                };
4838
4839                /* The rAF loop has been paused by the browser, so we manually restart the tick. */
4840                tick();
4841            } else {
4842                ticker = window.requestAnimationFrame || rAFShim;
4843            }
4844        });
4845    }
4846
4847    /************
4848        Tick
4849    ************/
4850
4851    /* Note: All calls to Velocity are pushed to the Velocity.State.calls array, which is fully iterated through upon each tick. */
4852    function tick (timestamp) {
4853        /* An empty timestamp argument indicates that this is the first tick occurence since ticking was turned on.
4854           We leverage this metadata to fully ignore the first tick pass since RAF's initial pass is fired whenever
4855           the browser's next tick sync time occurs, which results in the first elements subjected to Velocity
4856           calls being animated out of sync with any elements animated immediately thereafter. In short, we ignore
4857           the first RAF tick pass so that elements being immediately consecutively animated -- instead of simultaneously animated
4858           by the same Velocity call -- are properly batched into the same initial RAF tick and consequently remain in sync thereafter. */
4859        if (timestamp) {
4860            /* We ignore RAF's high resolution timestamp since it can be significantly offset when the browser is
4861               under high stress; we opt for choppiness over allowing the browser to drop huge chunks of frames. */
4862            var timeCurrent = (new Date).getTime();
4863
4864            /********************
4865               Call Iteration
4866            ********************/
4867
4868            /* Iterate through each active call. */
4869            for (var i = 0, callsLength = Velocity.State.calls.length; i < callsLength; i++) {
4870                /* When a Velocity call is completed, its Velocity.State.calls entry is set to false. Continue on to the next call. */
4871                if (!Velocity.State.calls[i]) {
4872                    continue;
4873                }
4874
4875                /************************
4876                   Call-Wide Variables
4877                ************************/
4878
4879                var callContainer = Velocity.State.calls[i],
4880                    call = callContainer[0],
4881                    opts = callContainer[2],
4882                    timeStart = callContainer[3],
4883                    firstTick = !!timeStart;
4884
4885                /* If timeStart is undefined, then this is the first time that this call has been processed by tick().
4886                   We assign timeStart now so that its value is as close to the real animation start time as possible.
4887                   (Conversely, had timeStart been defined when this call was added to Velocity.State.calls, the delay
4888                   between that time and now would cause the first few frames of the tween to be skipped since
4889                   percentComplete is calculated relative to timeStart.) */
4890                /* Further, subtract 16ms (the approximate resolution of RAF) from the current time value so that the
4891                   first tick iteration isn't wasted by animating at 0% tween completion, which would produce the
4892                   same style value as the element's current value. */
4893                if (!timeStart) {
4894                    timeStart = Velocity.State.calls[i][3] = timeCurrent - 16;
4895                }
4896
4897                /* The tween's completion percentage is relative to the tween's start time, not the tween's start value
4898                   (which would result in unpredictable tween durations since JavaScript's timers are not particularly accurate).
4899                   Accordingly, we ensure that percentComplete does not exceed 1. */
4900                var percentComplete = Math.min((timeCurrent - timeStart) / opts.duration, 1);
4901
4902                /**********************
4903                   Element Iteration
4904                **********************/
4905
4906                /* For every call, iterate through each of the elements in its set. */
4907                for (var j = 0, callLength = call.length; j < callLength; j++) {
4908                    var tweensContainer = call[j],
4909                        element = tweensContainer.element;
4910
4911                    /* Check to see if this element has been deleted midway through the animation by checking for the
4912                       continued existence of its data cache. If it's gone, skip animating this element. */
4913                    if (!Data(element)) {
4914                        continue;
4915                    }
4916
4917                    var transformPropertyExists = false;
4918
4919                    /**********************************
4920                       Display & Visibility Toggling
4921                    **********************************/
4922
4923                    /* If the display option is set to non-"none", set it upfront so that the element can become visible before tweening begins.
4924                       (Otherwise, display's "none" value is set in completeCall() once the animation has completed.) */
4925                    if (opts.display !== undefined && opts.display !== null && opts.display !== "none") {
4926                        if (opts.display === "flex") {
4927                            var flexValues = [ "-webkit-box", "-moz-box", "-ms-flexbox", "-webkit-flex" ];
4928
4929                            $.each(flexValues, function(i, flexValue) {
4930                                CSS.setPropertyValue(element, "display", flexValue);
4931                            });
4932                        }
4933
4934                        CSS.setPropertyValue(element, "display", opts.display);
4935                    }
4936
4937                    /* Same goes with the visibility option, but its "none" equivalent is "hidden". */
4938                    if (opts.visibility !== undefined && opts.visibility !== "hidden") {
4939                        CSS.setPropertyValue(element, "visibility", opts.visibility);
4940                    }
4941
4942                    /************************
4943                       Property Iteration
4944                    ************************/
4945
4946                    /* For every element, iterate through each property. */
4947                    for (var property in tweensContainer) {
4948                        /* Note: In addition to property tween data, tweensContainer contains a reference to its associated element. */
4949                        if (property !== "element") {
4950                            var tween = tweensContainer[property],
4951                                currentValue,
4952                                /* Easing can either be a pre-genereated function or a string that references a pre-registered easing
4953                                   on the Velocity.Easings object. In either case, return the appropriate easing *function*. */
4954                                easing = Type.isString(tween.easing) ? Velocity.Easings[tween.easing] : tween.easing;
4955
4956                            /******************************
4957                               Current Value Calculation
4958                            ******************************/
4959
4960                            /* If this is the last tick pass (if we've reached 100% completion for this tween),
4961                               ensure that currentValue is explicitly set to its target endValue so that it's not subjected to any rounding. */
4962                            if (percentComplete === 1) {
4963                                currentValue = tween.endValue;
4964                            /* Otherwise, calculate currentValue based on the current delta from startValue. */
4965                            } else {
4966                                currentValue = tween.startValue + ((tween.endValue - tween.startValue) * easing(percentComplete));
4967
4968                                /* If no value change is occurring, don't proceed with DOM updating. */
4969                                if (!firstTick && (currentValue === tween.currentValue)) {
4970                                    continue;
4971                                }
4972                            }
4973
4974                            tween.currentValue = currentValue;
4975
4976                            /******************
4977                               Hooks: Part I
4978                            ******************/
4979
4980                            /* For hooked properties, the newly-updated rootPropertyValueCache is cached onto the element so that it can be used
4981                               for subsequent hooks in this call that are associated with the same root property. If we didn't cache the updated
4982                               rootPropertyValue, each subsequent update to the root property in this tick pass would reset the previous hook's
4983                               updates to rootPropertyValue prior to injection. A nice performance byproduct of rootPropertyValue caching is that
4984                               subsequently chained animations using the same hookRoot but a different hook can use this cached rootPropertyValue. */
4985                            if (CSS.Hooks.registered[property]) {
4986                                var hookRoot = CSS.Hooks.getRoot(property),
4987                                    rootPropertyValueCache = Data(element).rootPropertyValueCache[hookRoot];
4988
4989                                if (rootPropertyValueCache) {
4990                                    tween.rootPropertyValue = rootPropertyValueCache;
4991                                }
4992                            }
4993
4994                            /*****************
4995                                DOM Update
4996                            *****************/
4997
4998                            /* setPropertyValue() returns an array of the property name and property value post any normalization that may have been performed. */
4999                            /* Note: To solve an IE<=8 positioning bug, the unit type is dropped when setting a property value of 0. */
5000                            var adjustedSetData = CSS.setPropertyValue(element, /* SET */
5001                                                                       property,
5002                                                                       tween.currentValue + (parseFloat(currentValue) === 0 ? "" : tween.unitType),
5003                                                                       tween.rootPropertyValue,
5004                                                                       tween.scrollData);
5005
5006                            /*******************
5007                               Hooks: Part II
5008                            *******************/
5009
5010                            /* Now that we have the hook's updated rootPropertyValue (the post-processed value provided by adjustedSetData), cache it onto the element. */
5011                            if (CSS.Hooks.registered[property]) {
5012                                /* Since adjustedSetData contains 
5012normalized data ready for DOM updating, the rootPropertyValue needs to be re-extracted from its normalized form. ?? */
5013                                if (CSS.Normalizations.registered[hookRoot]) {
5014                                    Data(element).rootPropertyValueCache[hookRoot] = CSS.Normalizations.registered[hookRoot]("extract", null, adjustedSetData[1]);
5015                                } else {
5016                                    Data(element).rootPropertyValueCache[hookRoot] = adjustedSetData[1];
5017                                }
5018                            }
5019
5020                            /***************
5021                               Transforms
5022                            ***************/
5023
5024                            /* Flag whether a transform property is being animated so that flushTransformCache() can be triggered once this tick pass is complete. */
5025                            if (adjustedSetData[0] === "transform") {
5026                                transformPropertyExists = true;
5027                            }
5028                        }
5029                    }
5030
5031                    /****************
5032                        mobileHA
5033                    ****************/
5034
5035                    /* If mobileHA is enabled, set the translate3d transform to null to force hardware acceleration.
5036                       It's safe to override this property since Velocity doesn't actually support its animation (hooks are used in its place). */
5037                    if (opts.mobileHA) {
5038                        /* Don't set the null transform hack if we've already done so. */
5039                        if (Data(element).transformCache.translate3d === undefined) {
5040                            /* All entries on the transformCache object are later concatenated into a single transform string via flushTransformCache(). */
5041                            Data(element).transformCache.translate3d = "(0px, 0px, 0px)";
5042
5043                            transformPropertyExists = true;
5044                        }
5045                    }
5046
5047                    if (transformPropertyExists) {
5048                        CSS.flushTransformCache(element);
5049                    }
5050                }
5051
5052                /* The non-"none" display value is only applied to an element once -- when its associated call is first ticked through.
5053                   Accordingly, it's set to false so that it isn't re-processed by this call in the next tick. */
5054                if (opts.display !== undefined && opts.display !== "none") {
5055                    Velocity.State.calls[i][2].display = false;
5056                }
5057                if (opts.visibility !== undefined && opts.visibility !== "hidden") {
5058                    Velocity.State.calls[i][2].visibility = false;
5059                }
5060
5061
5062                /* Pass the elements and the timing data (percentComplete, msRemaining, and timeStart) into the progress callback. */
5063                if (opts.progress) {
5064                    opts.progress.call(callContainer[1],
5065                                       callContainer[1],
5066                                       percentComplete,
5067                                       Math.max(0, (timeStart + opts.duration) - timeCurrent),
5068                                       timeStart);
5069                }
5070
5071                /* If this call has finished tweening, pass its index to completeCall() to handle call cleanup. */
5072                if (percentComplete === 1) {
5073                    completeCall(i);
5074                }
5075            }
5076        }
5077
5078        /* Note: completeCall() sets the isTicking flag to false when the last call on Velocity.State.calls has completed. */
5079        if (Velocity.State.isTicking) {
5080            ticker(tick);
5081        }
5082    }
5083
5084    /**********************
5085        Call Completion
5086    **********************/
5087
5088    /* Note: Unlike tick(), which processes all active calls at once, call completion is handled on a per-call basis. */
5089    function completeCall (callIndex, isStopped) {
5090        /* Ensure the call exists. */
5091        if (!Velocity.State.calls[callIndex]) {
5092            return false;
5093        }
5094
5095        /* Pull the metadata from the call. */
5096        var call = Velocity.State.calls[callIndex][0],
5097            elements = Velocity.State.calls[callIndex][1],
5098            opts = Velocity.State.calls[callIndex][2],
5099            resolver = Velocity.State.calls[callIndex][4];
5100
5101        var remainingCallsExist = false;
5102
5103        /*************************
5104           Element Finalization
5105        *************************/
5106
5107        for (var i = 0, callLength = call.length; i < callLength; i++) {
5108            var element = call[i].element;
5109
5110            /* If the user set display to "none" (intending to hide the element), set it now that the animation has completed. */
5111            /* Note: display:none isn't set when calls are manually stopped (via Velocity("stop"). */
5112            /* Note: Display gets ignored with "reverse" calls and infinite loops, since this behavior would be undesirable. */
5113            if (!isStopped && !opts.loop) {
5114                if (opts.display === "none") {
5115                    CSS.setPropertyValue(element, "display", opts.display);
5116                }
5117
5118                if (opts.visibility === "hidden") {
5119                    CSS.setPropertyValue(element, "visibility", opts.visibility);
5120                }
5121            }
5122
5123            /* 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
5124               a non-Velocity-initiated entry, turn off the isAnimating flag. A non-Velocity-initiatied queue entry's logic might alter
5125               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,
5126               we check for the existence of our special Velocity.queueEntryFlag declaration, which minifiers won't rename since the flag
5127               is assigned to jQuery's global $ object and thus exists out of Velocity's own scope. */
5128            if (opts.loop !== true && ($.queue(element)[1] === undefined || !/\.velocityQueueEntryFlag/i.test($.queue(element)[1]))) {
5129                /* The element may have been deleted. Ensure that its data cache still exists before acting on it. */
5130                if (Data(element)) {
5131                    Data(element).isAnimating = false;
5132                    /* Clear the element's rootPropertyValueCache, which will become stale. */
5133                    Data(element).rootPropertyValueCache = {};
5134
5135                    var transformHAPropertyExists = false;
5136                    /* If any 3D transform subproperty is at its default value (regardless of unit type), remove it. */
5137                    $.each(CSS.Lists.transforms3D, function(i, transformName) {
5138                        var defaultValue = /^scale/.test(transformName) ? 1 : 0,
5139                            currentValue = Data(element).transformCache[transformName];
5140
5141                        if (Data(element).transformCache[transformName] !== undefined && new RegExp("^\\(" + defaultValue + "[^.]").test(currentValue)) {
5142                            transformHAPropertyExists = true;
5143
5144                            delete Data(element).transformCache[transformName];
5145                        }
5146                    });
5147
5148                    /* Mobile devices have hardware acceleration removed at the end of the animation in order to avoid hogging the GPU's memory. */
5149                    if (opts.mobileHA) {
5150                        transformHAPropertyExists = true;
5151                        delete Data(element).transformCache.translate3d;
5152                    }
5153
5154                    /* Flush the subproperty removals to the DOM. */
5155                    if (transformHAPropertyExists) {
5156                        CSS.flushTransformCache(element);
5157                    }
5158
5159                    /* Remove the "velocity-animating" indicator class. */
5160                    CSS.Values.removeClass(element, "velocity-animating");
5161                }
5162            }
5163
5164            /*********************
5165               Option: Complete
5166            *********************/
5167
5168            /* 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. */
5169            /* Note: Callbacks aren't fired when calls are manually stopped (via Velocity("stop"). */
5170            if (!isStopped && opts.complete && !opts.loop && (i === callLength - 1)) {
5171                /* We throw callbacks in a setTimeout so that thrown errors don't halt the execution of Velocity itself. */
5172                try {
5173                    opts.complete.call(elements, elements);
5174                } catch (error) {
5175                    setTimeout(function() { throw error; }, 1);
5176                }
5177            }
5178
5179            /**********************
5180               Promise Resolving
5181            **********************/
5182
5183            /* Note: Infinite loops don't return promises. */
5184            if (resolver && opts.loop !== true) {
5185                resolver(elements);
5186            }
5187
5188            /****************************
5189               Option: Loop (Infinite)
5190            ****************************/
5191
5192            if (opts.loop === true && !isStopped) {
5193                /* If a rotateX/Y/Z property is being animated to 360 deg with loop:true, swap tween start/end values to enable
5194                   continuous iterative rotation looping. (Otherise, the element would just rotate back and forth.) */
5195                $.each(Data(element).tweensContainer, function(propertyName, tweenContainer) {
5196                    if (/^rotate/.test(propertyName) && parseFloat(tweenContainer.endValue) === 360) {
5197                        tweenContainer.endValue = 0;
5198                        tweenContainer.startValue = 360;
5199                    }
5200                });
5201
5202                Velocity(element, "reverse", { loop: true, delay: opts.delay });
5203            }
5204
5205            /***************
5206               Dequeueing
5207            ***************/
5208
5209            /* Fire the next call in the queue so long as this call's queue wasn't set to false (to trigger a parallel animation),
5210               which would have already caused the next call to fire. Note: Even if the end of the animation queue has been reached,
5211               $.dequeue() must still be called in order to completely clear jQuery's animation queue. */
5212            if (opts.queue !== false) {
5213                $.dequeue(element, opts.queue);
5214            }
5215        }
5216
5217        /************************
5218           Calls Array Cleanup
5219        ************************/
5220
5221        /* Since this call is complete, set it to false so that the rAF tick skips it. This array is later compacted via compactSparseArray().
5222          (For performance reasons, the call is set to false instead of being deleted from the array: http://www.html5rocks.com/en/tutorials/speed/v8/) */
5223        Velocity.State.calls[callIndex] = false;
5224
5225        /* Iterate through the calls array to determine if this was the final in-progress animation.
5226           If so, set a flag to end ticking and clear the calls array. */
5227        for (var j = 0, callsLength = Velocity.State.calls.length; j < callsLength; j++) {
5228            if (Velocity.State.calls[j] !== false) {
5229                remainingCallsExist = true;
5230
5231                break;
5232            }
5233        }
5234
5235        if (remainingCallsExist === false) {
5236            /* tick() will detect this flag upon its next iteration and subsequently turn itself off. */
5237            Velocity.State.isTicking = false;
5238
5239            /* Clear the calls array so that its length is reset. */
5240            delete Velocity.State.calls;
5241            Velocity.State.calls = [];
5242        }
5243    }
5244
5245    /******************
5246        Frameworks
5247    ******************/
5248
5249    /* Both jQuery and Zepto allow their $.fn object to be extended to allow wrapped elements to be subjected to plugin calls.
5250       If either framework is loaded, register a "velocity" extension pointing to Velocity's core animate() method.  Velocity
5251       also registers itself onto a global container (window.jQuery || window.Zepto || window) so that certain features are
5252       accessible beyond just a per-element scope. This master object contains an .animate() method, which is later assigned to $.fn
5253       (if jQuery or Zepto are present). Accordingly, Velocity can both act on wrapped DOM elements and stand alone for targeting raw DOM elements. */
5254    global.Velocity = Velocity;
5255
5256    if (global !== window) {
5257        /* Assign the element function to Velocity's core animate() method. */
5258        global.fn.velocity = animate;
5259        /* Assign the object function's defaults to Velocity's global defaults object. */
5260        global.fn.velocity.defaults = Velocity.defaults;
5261    }
5262
5263    /***********************
5264       Packaged Redirects
5265    ***********************/
5266
5267    /* slideUp, slideDown */
5268    $.each([ "Down", "Up" ], function(i, direction) {
5269        Velocity.Redirects["slide" + direction] = function (element, options, elementsIndex, elementsSize, elements, promiseData) {
5270            var opts = $.extend({}, options),
5271                begin = opts.begin,
5272                complete = opts.complete,
5273                computedValues = { height: "", marginTop: "", marginBottom: "", paddingTop: "", paddingBottom: "" },
5274                inlineValues = {};
5275
5276            if (opts.display === undefined) {
5277                /* Show the element before slideDown begins and hide the element after slideUp completes. */
5278                /* Note: Inline elements cannot have dimensions animated, so they're reverted to inline-block. */
5279                opts.display = (direction === "Down" ? (Velocity.CSS.Values.getDisplayType(element) === "inline" ? "inline-block" : "block") : "none");
5280            }
5281
5282            opts.begin = function() {
5283                /* If the user passed in a begin callback, fire it now. */
5284                begin && begin.call(elements, elements);
5285
5286                /* Cache the elements' original vertical dimensional property values so that we can animate back to them. */
5287                for (var property in computedValues) {
5288                    /* Cache all inline values, we reset to upon animation completion. */
5289                    inlineValues[property] = element.style[property];
5290
5291                    /* For slideDown, use forcefeeding to animate all vertical properties from 0. For slideUp,
5292                       use forcefeeding to start from computed values and animate down to 0. */
5293                    var propertyValue = Velocity.CSS.getPropertyValue(element, property);
5294                    computedValues[property] = (direction === "Down") ? [ propertyValue, 0 ] : [ 0, propertyValue ];
5295                }
5296
5297                /* Force vertical overflow content to clip so that sliding works as expected. */
5298                inlineValues.overflow = element.style.overflow;
5299                element.style.overflow = "hidden";
5300            }
5301
5302            opts.complete = function() {
5303                /* Reset element to its pre-slide inline values once its slide animation is complete. */
5304                for (var property in inlineValues) {
5305                    element.style[property] = inlineValues[property];
5306                }
5307
5308                /* If the user passed in a complete callback, fire it now. */
5309                complete && complete.call(elements, elements);
5310                promiseData && promiseData.resolver(elements);
5311            };
5312
5313            Velocity(element, computedValues, opts);
5314        };
5315    });
5316
5317    /* fadeIn, fadeOut */
5318    $.each([ "In", "Out" ], function(i, direction) {
5319        Velocity.Redirects["fade" + direction] = function (element, options, elementsIndex, elementsSize, elements, promiseData) {
5320            var opts = $.extend({}, options),
5321                propertiesMap = { opacity: (direction === "In") ? 1 : 0 },
5322                originalComplete = opts.complete;
5323
5324            /* Since redirects are triggered individually for each element in the animated set, avoid repeatedly triggering
5325               callbacks by firing them only when the final element has been reached. */
5326            if (elementsIndex !== elementsSize - 1) {
5327                opts.complete = opts.begin = null;
5328            } else {
5329                opts.complete = function() {
5330                    if (originalComplete) {
5331                        originalComplete.call(elements, elements);
5332                    }
5333
5334                    promiseData && promiseData.resolver(elements);
5335                }
5336            }
5337
5338            /* If a display was passed in, use it. Otherwise, default to "none" for fadeOut or the element-specific default for fadeIn. */
5339            /* Note: We allow users to pass in "null" to skip display setting altogether. */
5340            if (opts.display === undefined) {
5341                opts.display = (direction === "In" ? "auto" : "none");
5342            }
5343
5344            Velocity(this, propertiesMap, opts);
5345        };
5346    });
5347
5348    return Velocity;
5349}((window.jQuery || window.Zepto || window), window, document);
5350}));
5351
5352/******************
5353   Known Issues
5354******************/
5355
5356/* The CSS spec mandates that the translateX/Y/Z transforms are %-relative to the element itself -- not its parent.
5357Velocity, however, doesn't make this distinction. Thus, converting to or from the % unit with these subproperties
5358will produce an inaccurate conversion value. The same issue exists with the cx/cy attributes of SVG circles and ellipses. */
5359;
5360(function ($, window, undefined) {
5361
5362	// /* ====== SHARED VARS  - jQuery ====== */
5363	// These depend on jQuery
5364	var $window = $(window),
5365		windowHeight = $window.height(),
5366		windowWidth = $window.width();
5367
5368	/**
5369	 * Detect browser size and remember it in global variables
5370	 */
5371
5372	function browserSize() {
5373		wh = $window.height();
5374		ww = $window.width();
5375		dh = $(document).height();
5376		ar = ww / wh;
5377	}
5378
5379
5380	/**
5381	 * Detect what platform are we on (browser, mobile, etc)
5382	 */
5383
5384	function platformDetect() {
5385		$.support.touch = 'ontouchend' in document;
5386		var navUA = navigator.userAgent.toLowerCase(),
5387			navPlat = navigator.platform.toLowerCase();
5388
5389		var isiPhone = navPlat.indexOf("iphone"),
5390			isiPod = navPlat.indexOf("ipod"),
5391			isAndroidPhone = navPlat.indexOf("android"),
5392			safari = (navUA.indexOf('safari') != -1 && navUA.indexOf('chrome') == -1) ? true : false,
5393			svgSupport = (window.SVGAngle) ? true : false,
5394			svgSupportAlt = (document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")) ? true : false,
5395			ff3x = (/gecko/i.test(navUA) && /rv:1.9/i.test(navUA)) ? true : false;
5396
5397		ieMobile = navigator.userAgent.match(/Windows Phone/i) ? true : false;
5398		phone = (isiPhone > -1 || isiPod > -1 || isAndroidPhone > -1) ? true : false;
5399		touch = $.support.touch ? true : false;
5400
5401		if (touch) $html.addClass('touch');
5402
5403		if (ieMobile) $html.addClass('is--winmob');
5404		if (is_android) $html.addClass('is--ancient-android');
5405
5406		if (safari) $body.addClass('safari');
5407		if (phone) $body.addClass('phone');
5408	}
5409
5410	// /* ====== SHARED VARS ====== */
5411	// These do not depend on jQuery
5412	var phone, touch, wh, ww, dh, ar, fonts;
5413
5414	var ua = navigator.userAgent;
5415	var winLoc = window.location.toString();
5416
5417	var is_webkit = ua.match(/webkit/i);
5418	var is_firefox = ua.match(/gecko/i);
5419	var is_newer_ie = ua.match(/msie (9|([1-9][0-9]))/i);
5420	var is_older_ie = ua.match(/msie/i) && !is_newer_ie;
5421	var is_ancient_ie = ua.match(/msie 6/i);
5422	var is_mobile = ua.match(/mobile/i);
5423	var is_OSX = (ua.match(/(iPad|iPhone|iPod|Macintosh)/g) ? true : false);
5424
5425	var nua = navigator.userAgent;
5426	var is_android = ((nua.indexOf('Mozilla/5.0') !== -1 && nua.indexOf('Android ') !== -1 && nua.indexOf('AppleWebKit') !== -1) && nua.indexOf('Chrome') === -1);
5427
5428	var useTransform = true;
5429	var use2DTransform = (ua.match(/msie 9/i) || winLoc.match(/transform\=2d/i));
5430	var transform;
5431
5432	var $html = $('html');
5433	var $body = $('body');
5434
5435	// setting up transform prefixes
5436	var prefixes = {
5437		webkit: 'webkitTransform',
5438		firefox: 'MozTransform',
5439		ie: 'msTransform',
5440		w3c: 'transform'
5441	};
5442
5443	if (useTransform) {
5444		if (is_webkit) {
5445			transform = prefixes.webkit;
5446		} else if (is_firefox) {
5447			transform = prefixes.firefox;
5448		} else if (is_newer_ie) {
5449			transform = prefixes.ie;
5450		}
5451	}
5452	// /* ====== Masonry Logic ====== */
5453	(function () {
5454
5455		var $container = $('.archive__grid'),
5456			$blocks = $container.children().addClass('post--animated  post--loaded'),
5457			slices = $blocks.first().children().length;
5458
5459        var observerConfig = { attributes: false, childList: true, characterData: true },
5460            observer;
5461
5462        if ( "MutationObserver" in window ) {
5463            observer = new MutationObserver( function( mutations ) {
5464                $container.masonry( 'layout' );
5465            } );
5466        }
5467
5468        // initialize masonry after the images have loaded
5469        $container.imagesLoaded(function () {
5470
5471			// prepare hover animations
5472			if (!$html.hasClass('touch'))
5473				$blocks.addHoverAnimation();
5474
5475            // initialize masonry
5476            $container.masonry({
5477                isAnimated: false,
5478                itemSelector: '.grid__item',
5479                transitionDuration: 0,
5480                hiddenStyle: {
5481                    opacity: 0
5482                }
5483            });
5484
5485			/**
5486			 * function used to display cards with a simple fade in transition
5487			 */
5488
5489			function showBlocks($blocks) {
5490
5491				// use different delays for each card to stagger them
5492				$blocks.each(function (i, obj) {
5493
5494					var $block = $(obj),
5495						duration = 200 + slices * 0.1;
5496
5497					$block.velocity({
5498						translateY: 40
5499					}, {
5500						duration: 0
5501					});
5502					setTimeout(function () {
5503						$block.velocity({
5504							translateY: 0
5505						}, {
5506							easing: "easeOutQuad",
5507							duration: 100
5508						});
5509
5510						$block.children().each(function (j, child) {
5511							var $child = $(child),
5512								timeout = (j + 1) * 100;
5513
5514							$child.velocity({
5515								opacity: 0,
5516								translateY: 40
5517							}, {
5518								duration: 0
5519							});
5520
5521							$child.velocity({
5522								opacity: 1,
5523								translateY: 0
5524							}, {
5525								duration: 300,
5526								delay: timeout
5527							});
5528						});
5529
5530						setTimeout(function () {
5531							$block.toggleClass('sticky--bg', $block.hasClass('sticky'));
5532							$block.addClass('post--visible');
5533						}, 300);
5534
5535					}, i * 200);
5536				});
5537			}
5538
5539			// animate cards in
5540			showBlocks($blocks);
5541
5542            $blocks.each( function( i, obj ) {
5543                if ( typeof observer !== "undefined" ) {
5544                    observer.observe( obj, observerConfig );
5545                }
5546            } );
5547
5548            // update the masonry layout on window.resize
5549            $(window).smartresize(function () {
5550                $container.masonry('layout');
5551            });
5552
5553			$(window).load(function () {
5554				$container.masonry('layout');
5555			});
5556
5557			// handle behavior for infinite scroll
5558			$(document.body).on('post-load', function () {
5559
5560				// figure out which are the new loaded posts
5561				var $newBlocks = $('.archive__grid').children().not('.post--loaded').addClass('post--loaded');
5562
5563				// when images have loaded take care of the layout, prepare hover animations, and animate cards in
5564				$newBlocks.imagesLoaded( function() {
5565					$container.masonry( 'appended', $newBlocks, true ).masonry( 'layout' );
5566					if ( ! $html.hasClass( 'touch' ) ) {
5567						$newBlocks.addHoverAnimation();
5568					}
5569					showBlocks( $newBlocks );
5570				} );
5571
5572				if ( typeof observer !== "undefined" ) {
5573					$newBlocks.each( function(i, obj ) {
5574						observer.observe( obj, observerConfig );
5575					} );
5576				}
5577			});
5578		});
5579	})();
5580
5581	// /* ====== Navigation Logic ====== */
5582	var $nav = $('.nav--main'),
5583		$navTrigger = $('.navigation__trigger'),
5584		$navContainer = $('.main-navigation'),
5585		navTop = (typeof $navContainer.offset() !== 'undefined') ? $navContainer.offset().top : 0,
5586		navLeft = (typeof $navContainer.offset() !== 'undefined') ? $navContainer.offset().left : 0,
5587		navWidth = $nav.outerWidth(),
5588		containerWidth = $navContainer.outerWidth(),
5589		navHeight = $nav.outerHeight(),
5590		$toolbar = $('.toolbar'),
5591		isOpen = false,
5592		pageTop = $('#page').offset().top,
5593		pageWidth = $('#page').width(),
5594		pageLeft = $('#page').offset().left,
5595		sticked = false;
5596
5597	/**
5598	 * bind toggling the navigation drawer to click and touchstart
5599	 *in order to get rid of the 300ms delay on touch devices we use the touchstart event
5600	 */
5601	var triggerEvents = 'click touchstart';
5602	if (is_android) triggerEvents = 'click';
5603
5604	// Set the Navigation Container Height
5605	$navContainer.height(navHeight);
5606
5607	$navTrigger.on(triggerEvents, function (e) {
5608		// but we still have to prevent the default behavior of the touchstart event
5609		// because this way we're making sure the click event won't fire anymore
5610		e.preventDefault();
5611		e.stopPropagation();
5612
5613		isOpen = !isOpen;
5614		$('body').toggleClass('nav--is-open');
5615
5616		var offset;
5617
5618		navWidth = $nav.outerWidth();
5619
5620		if ($('body').hasClass('rtl')) {
5621			offset = -1 * navWidth;
5622		} else {
5623			offset = navWidth;
5624		}
5625
5626		if (!is_android) {
5627			if (!isOpen) {
5628
5629				$([$nav, $navTrigger]).each(function (i, obj) {
5630					$(obj).velocity({
5631						translateX: 0,
5632						translateZ: 0.01
5633					}, {
5634						duration: 300,
5635						easing: "easeInQuart",
5636						begin: function () {
5637							$navContainer.removeClass('shadow');
5638						}
5639					});
5640				});
5641
5642			} else {
5643
5644				$([$nav, $navTrigger]).each(function (i, obj) {
5645					$(obj).velocity({
5646						translateX: offset,
5647						translateZ: 0.01
5648					}, {
5649						easing: "easeOutCubic",
5650						duration: 300,
5651						complete: function () {
5652							$navContainer.addClass('shadow');
5653						}
5654					});
5655				});
5656			}
5657		}
5658	});
5659
5660	var HandleParentMenuItems = (function() {
5661		// Handle parent menu items on tablet in landscape mode;
5662		// use case: normal, horizontal menu, touch events,
5663		// sub menus are not visible.
5664		function handleParentMenuItems() {
5665			// Make sure there are no open menu items
5666			$('[class*="has-children"]').removeClass('hover');
5667
5668			$('[class*="has-children"] > a').each( function(){
5669				// Add a class so we know the items to handle
5670				$(this).addClass('prevent-one').attr('hasbeenclicked', false);
5671			});
5672
5673			$('a.prevent-one').on('click', function(e) {
5674				if( $( this ).attr( 'hasbeenclicked' ) == "false" ) {
5675					e.preventDefault();
5676					e.stopPropagation();
5677
5678					$(this).attr('hasbeenclicked', true);
5679
5680					// Open the sub menu of this parent item
5681					$(this).parent().addClass('hover')
5682					// When a parent menu item is activated,
5683					// close other menu items on the same level
5684					       .siblings().removeClass('hover').find('> a.prevent-one').attr('hasbeenclicked', false);
5685				}
5686			});
5687		}
5688
5689		// Restore the original behaviour when in portrait mode;
5690		// use case: vertical menu, all menu items are visible.
5691		function unHandleParentMenuItems() {
5692			$('a.prevent-one').each(function(){
5693				// Unbind te click handler
5694				$(this).unbind();
5695			});
5696		}
5697
5698		// When a sub menu is open, close it by a touch on
5699		// any other part of the viewport than navigation.
5700		// use case: normal, horizontal menu, touch events,
5701		// sub menus are not visible.
5702		function bindOuterNavClick() {
5703			$('body').on( 'touchstart', function (e) {
5704				var container = $('.nav--main');
5705
5706				if (!container.is(e.target) // if the target of the click isn't the container...
5707				    && container.has(e.target).length === 0) // ... nor a descendant of the container
5708				{
5709					$('[class*="has-children"]').removeClass('hover');
5710					$('a.prevent-one').attr('hasbeenclicked', false);
5711				}
5712			});
5713		}
5714
5715		return {
5716			handle: handleParentMenuItems,
5717			unHandle: unHandleParentMenuItems,
5718			bindOuterNavClick: bindOuterNavClick
5719		}
5720	}());
5721
5722	/**
5723	 * function used to make the navigation bar on big screens
5724	 * sticky or static depending on the scroll position
5725	 */
5726
5727	function updateStickyMenu() {
5728
5729		// pin
5730		if (latestKnownScrollY + pageTop > navTop && !sticked) {
5731			$nav.css({
5732				position: 'fixed',
5733				top: pageTop,
5734				left: pageLeft,
5735				width: pageWidth
5736			});
5737
5738			sticked = true;
5739			return;
5740		}
5741
5742		// unpin
5743		if (latestKnownScrollY + pageTop <= navTop && sticked) {
5744
5745			$nav.css({
5746				position: '',
5747				left: '',
5748				top: '',
5749				width: ''
5750			});
5751
5752			sticked = false;
5753		}
5754
5755	}
5756
5757	/**
5758	 * because we hard-code properties on the navigation bar when we stick it at the top of the window
5759	 * we need to update some properties on window resize
5760	 */
5761
5762	function refreshNavigation() {
5763		navTop = (typeof $navContainer.offset() !== 'undefined') ? $navContainer.offset().top : 0;
5764		navLeft = (typeof $navContainer.offset() !== 'undefined') ? $navContainer.offset().left : 0;
5765		containerWidth = $navContainer.outerWidth();
5766		navWidth = $nav.outerWidth();
5767		navHeight = $nav.outerHeight();
5768		pageTop = $('#page').offset().top;
5769		pageWidth = $('#page').width();
5770
5771		$navContainer.height(navHeight);
5772
5773		if (sticked) {
5774			$nav.velocity({
5775				width: pageWidth
5776			}, {
5777				easing: "easeOutCubic",
5778				duration: 200
5779			});
5780		}
5781
5782		if (isOpen) {
5783			$([$nav, $navTrigger]).each(function (i, obj) {
5784				$(obj).velocity({
5785					translateX: navWidth
5786				}, {
5787					easing: "easeOutQuint",
5788					duration: 200
5789				});
5790			});
5791		}
5792
5793		navWidth = containerWidth;
5794	}
5795
5796	/**
5797	 * cardHover jQuery plugin
5798	 *
5799	 * we need to create a jQuery plugin so we can easily create the hover animations on the archive
5800	 * both an window.load and on jetpack's infinite scroll 'post-load'
5801	 */
5802	$.fn.addHoverAnimation = function () {
5803
5804		return this.each(function (i, obj) {
5805
5806			var $obj = $(obj),
5807				$handler = $obj.find('.hover__handler'),
5808				$hover = $obj.find('.hover');
5809
5810			// if we don't have have elements that need to be animated return
5811			if (!$hover.length) {
5812				return;
5813			}
5814
5815			var $letter = $hover.find('.hover__letter'),
5816				letterWidth = $letter.outerWidth,
5817				letterHeight = $letter.outerHeight;
5818
5819			$hover.find('.hover__bg').velocity({
5820				opacity: 0
5821			}, {
5822				duration: 0
5823			});
5824			$hover.find('.hover__line').velocity({
5825				height: 0
5826			}, {
5827				duration: 0
5828			});
5829			$hover.find('.hover__more').velocity({
5830				opacity: 0
5831			}, {
5832				duration: 0
5833			});
5834			$hover.find('.hover__letter').velocity({
5835				opacity: 0,
5836				translateX: '-50%',
5837				translateY: '-50%',
5838				scaleX: 1.25,
5839				scaleY: 1.25
5840			}, {
5841				duration: 0
5842			});
5843
5844			// bind the tweens we created above to mouse events accordingly, through hoverIntent to avoid flickering
5845			if ($handler.length) {
5846				$handler.hoverIntent({
5847					over: animateHoverIn,
5848					out: animateHoverOut,
5849					timeout: 100,
5850					interval: 50
5851				});
5852			}
5853
5854			function animateHoverIn() {
5855
5856				$hover.find('.hover__bg').velocity("reverse", {
5857					easing: "easeOutQuart",
5858					duration: 500
5859				});
5860				$hover.find('.hover__line').velocity("reverse", {
5861					easing: "easeOutQuart",
5862					duration: 350,
5863					delay: 150
5864				});
5865				$hover.find('.hover__more').velocity("reverse", {
5866					easing: "easeOutQuart",
5867					duration: 350,
5868					delay: 150
5869				});
5870				$hover.find('.hover__letter').velocity({
5871					scaleX: 1,
5872					scaleY: 1,
5873					opacity: 0.2,
5874					translateX: '-50%',
5875					translateY: '-50%'
5876				}, {
5877					easing: "easeOutQuart",
5878					duration: 350,
5879					delay: 150
5880				});
5881
5882			}
5883
5884			function animateHoverOut() {
5885
5886				var letterHeight = $hover.find('.hover__letter-mask').outerHeight();
5887
5888				$hover.find('.hover__letter').velocity({
5889					opacity: 0,
5890					translateX: '-50%',
5891					translateY: '-50%',
5892					scaleX: 1.25,
5893					scaleY: 1.25
5894				}, {
5895					easing: "easeOutQuart",
5896					duration: 350,
5897					delay: 0
5898				});
5899				$hover.find('.hover__more').velocity("reverse", {
5900					duration: 350,
5901					delay: 0
5902				});
5903				$hover.find('.hover__line').velocity("reverse", {
5904					duration: 350,
5905					delay: 0
5906				});
5907				$hover.find('.hover__bg').velocity("reverse", {
5908					duration: 350,
5909					delay: 0
5910				});
5911
5912			}
5913
5914		});
5915	};
5916
5917	// /* ====== Search Overlay Logic ====== */
5918	(function () {
5919
5920		var isOpen = false,
5921			$overlay = $('.overlay--search');
5922
5923		// update overlay position (if it's open) on window.resize
5924		$(window).on('smartresize', function () {
5925
5926			windowWidth = $(window).outerWidth();
5927
5928			if (isOpen) {
5929				$overlay.velocity({
5930					translateX: -1 * windowWidth
5931				}, {
5932					duration: 200,
5933					easing: "easeInCubic"
5934				});
5935			}
5936
5937		});
5938
5939		/**
5940		 * dismiss overlay
5941		 */
5942
5943		function closeOverlay() {
5944
5945			if (!isOpen) {
5946				return;
5947			}
5948
5949			var offset;
5950
5951			if ($('body').hasClass('rtl')) {
5952				offset = windowWidth
5953			} else {
5954				offset = -1 * windowWidth
5955			}
5956
5957			// we don't need a timeline for this animations so we'll use a simple tween between two states
5958			$overlay.velocity({
5959				translateX: offset
5960			}, {
5961				duration: 0
5962			});
5963			$overlay.velocity({
5964				translateX: 0
5965			}, {
5966				duration: 300,
5967				easing: "easeInCubic"
5968			});
5969
5970			// remove focus from the search field
5971			$overlay.find('input').blur();
5972
5973			isOpen = false;
5974		}
5975
5976		function escOverlay(e) {
5977			if (e.keyCode == 27) {
5978				closeOverlay();
5979			}
5980		}
5981
5982		// create animation and run it on
5983		$('.nav__item--search').on('click touchstart', function (e) {
5984			// prevent default behavior and stop propagation
5985			e.preventDefault();
5986			e.stopPropagation();
5987
5988			// if through some kind of sorcery the navigation drawer is already open return
5989			if (isOpen) {
5990				return;
5991			}
5992
5993			var offset;
5994
5995			if ($('body').hasClass('rtl')) {
5996				offset = windowWidth
5997			} else {
5998				offset = -1 * windowWidth
5999			}
6000
6001			// automatically focus the search field so the user can type right away
6002			$overlay.find('input').focus();
6003
6004			$overlay.velocity({
6005				translateX: 0
6006			}, {
6007				duration: 0
6008			}).velocity({
6009				translateX: offset
6010			}, {
6011				duration: 300,
6012				easing: "easeOut",
6013				queue: false
6014			});
6015
6016			$('.search-form').velocity({
6017				translateX: 300,
6018				opacity: 0
6019			}, {
6020				duration: 0
6021			}).velocity({
6022				opacity: 1
6023			}, {
6024				duration: 200,
6025				easing: "easeOutQuad",
6026				delay: 200,
6027				queue: false
6028			}).velocity({
6029				translateX: 0
6030			}, {
6031				duration: 400,
6032				easeing: [0.175, 0.885, 0.320, 1.275],
6033				delay: 50,
6034				queue: false
6035			});
6036
6037			$('.overlay__wrapper > p').velocity({
6038				translateX: 200,
6039				opacity: 0
6040			}, {
6041				duration: 0
6042			}).velocity({
6043				opacity: 1
6044			}, {
6045				duration: 400,
6046				easing: "easeOutQuad",
6047				delay: 350,
6048				queue: false
6049			}).velocity({
6050				translateX: 0
6051			}, {
6052				duration: 400,
6053				easing: [0.175, 0.885, 0.320, 1.275],
6054				delay: 250,
6055				queue: false
6056			});
6057
6058			// bind overlay dismissal to escape key
6059			$(document).on('keyup', escOverlay);
6060
6061			isOpen = true;
6062		});
6063
6064		// create function to hide the search overlay and bind it to the click event
6065		$('.overlay__close').on('click touchstart', function (e) {
6066
6067			e.preventDefault();
6068			e.stopPropagation();
6069
6070			closeOverlay();
6071
6072			// unbind overlay dismissal from escape key
6073			$(document).off('keyup', escOverlay);
6074
6075		});
6076
6077	})();
6078
6079	// /* ====== Smart Resize Logic ====== */
6080	// It's best to debounce the resize event to a void performance hiccups
6081	(function ($, sr) {
6082
6083		/**
6084		 * debouncing function from John Hann
6085		 * http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
6086		 */
6087		var debounce = function (func, threshold, execAsap) {
6088			var timeout;
6089
6090			return function debounced() {
6091				var obj = this,
6092					args = arguments;
6093
6094				function delayed() {
6095					if (!execAsap) func.apply(obj, args);
6096					timeout = null;
6097				}
6098
6099				if (timeout) clearTimeout(timeout);
6100				else if (execAsap) func.apply(obj, args);
6101
6102				timeout = setTimeout(delayed, threshold || 200);
6103			};
6104		}
6105		// smartresize
6106		jQuery.fn[sr] = function (fn) {
6107			return fn ? this.bind('resize', debounce(fn)) : this.trigger(sr);
6108		};
6109
6110	})(jQuery, 'smartresize');
6111	var latestKnownScrollY = window.scrollY,
6112		ticking = false;
6113
6114	function requestTick() {
6115		"use strict";
6116
6117		if (!ticking) {
6118			requestAnimationFrame(update);
6119		}
6120		ticking = true;
6121	}
6122
6123	function update() {
6124		"use strict";
6125
6126		ticking = false;
6127
6128		if (!is_android) {
6129			updateStickyMenu();
6130		}
6131	}
6132
6133	/* ====== INTERNAL FUNCTIONS END ====== */
6134
6135
6136	/* ====== ONE TIME INIT ====== */
6137
6138	function init() {
6139
6140		// /* GLOBAL VARS */
6141		touch = false;
6142
6143		//  GET BROWSER DIMENSIONS
6144		browserSize();
6145
6146		// /* DETECT PLATFORM */
6147		platformDetect();
6148	}
6149
6150
6151	/* --- GLOBAL EVENT HANDLERS --- */
6152
6153
6154	/* ====== ON DOCUMENT READY ====== */
6155
6156	$(document).ready(function () {
6157		init();
6158	});
6159
6160
6161	/* ====== ON WINDOW LOAD ====== */
6162
6163	$window.load(function () {
6164
6165		if ( !$html.hasClass( 'touch' ) ) {
6166			var $nav = $( '.nav--main' ).addClass( 'hover-intent' );
6167
6168			$( '.nav--main li' ).hoverIntent({
6169				over: showSubMenu,
6170				out: hideSubMenu,
6171				timeout: 300
6172			});
6173		} else if ( $html.hasClass( 'touch') && windowWidth > 1000 ) {
6174			HandleParentMenuItems.handle();
6175			HandleParentMenuItems.bindOuterNavClick();
6176		}
6177
6178		function showSubMenu() {
6179			$(this).addClass('hover');
6180		}
6181
6182		function hideSubMenu() {
6183			$(this).removeClass('hover');
6184		}
6185
6186	});
6187
6188	/* ====== ON RESIZE ====== */
6189
6190	$(window).smartresize(function () {
6191		if (!is_android) {
6192			refreshNavigation();
6193		}
6194		windowWidth = $(window).outerWidth();
6195		windowHeight = $(window).outerHeight();
6196
6197		if( $html.hasClass( 'touch' ) ) {
6198			if( windowWidth >= 1000 ) {
6199				// Handle parent menu items
6200				HandleParentMenuItems.handle();
6201			} else if ( windowWidth < 1000 ) {
6202				// Remove handlers
6203				HandleParentMenuItems.unHandle();
6204			}
6205		}
6206	});
6207
6208	/* ====== ON SCROLL ====== */
6209
6210	$window.on('scroll', function (e) {
6211		"use strict";
6212
6213		latestKnownScrollY = window.scrollY;
6214		requestTick();
6215	});
6216	// /* ====== HELPER FUNCTIONS ====== */
6217	/**
6218	 * function similar to PHP's empty function
6219	 */
6220
6221	function empty(data) {
6222		if (typeof(data) == 'number' || typeof(data) == 'boolean') {
6223			return false;
6224		}
6225		if (typeof(data) == 'undefined' || data === null) {
6226			return true;
6227		}
6228		if (typeof(data.length) != 'undefined') {
6229			return data.length === 0;
6230		}
6231		var count = 0;
6232		for (var i in data) {
6233			// if(data.hasOwnProperty(i))
6234			//
6235			// This doesn't work in ie8/ie9 due the fact that hasOwnProperty works only on native objects.
6236			// http://stackoverflow.com/questions/8157700/object-has-no-hasownproperty-method-i-e-its-undefined-ie8
6237			//
6238			// for hosts objects we do this
6239			if (Object.prototype.hasOwnProperty.call(data, i)) {
6240				count++;
6241			}
6242		}
6243		return count === 0;
6244	}
6245
6246	/**
6247	 * function to add/modify a GET parameter
6248	 */
6249
6250	function setQueryParameter(uri, key, value) {
6251		var re = new RegExp("([?|&])" + key + "=.*?(&|$)", "i");
6252		separator = uri.indexOf('?') !== -1 ? "&" : "?";
6253		if (uri.match(re)) {
6254			return uri.replace(re, '$1' + key + "=" + value + '$2');
6255		}
6256		else {
6257			return uri + separator + key + "=" + value;
6258		}
6259	}
6260
6261	/**
6262	 * requestAnimationFrame polyfill by Erik Möller.
6263	 * Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavič, Darius Bacon
6264	 *
6265	 * MIT license
6266	 */
6267
6268	if (!Date.now)
6269		Date.now = function () {
6270			return new Date().getTime();
6271		};
6272
6273	(function () {
6274		'use strict';
6275
6276		var vendors = ['webkit', 'moz'];
6277		for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
6278			var vp = vendors[i];
6279			window.requestAnimationFrame = window[vp + 'RequestAnimationFrame'];
6280			window.cancelAnimationFrame = (window[vp + 'CancelAnimationFrame']
6281			                               || window[vp + 'CancelRequestAnimationFrame']);
6282		}
6283		if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
6284		    || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
6285			var lastTime = 0;
6286			window.requestAnimationFrame = function (callback) {
6287				var now = Date.now();
6288				var nextTime = Math.max(lastTime + 16, now);
6289				return setTimeout(function () {
6290						callback(lastTime = nextTime);
6291					},
6292					nextTime - now);
6293			};
6294			window.cancelAnimationFrame = clearTimeout;
6295		}
6296	}());
6297
6298})(jQuery, window);;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.