PageSourceSearch

https://wedesa.com/js/js-plugins/isotope.pkgd.min.js?20221220

js wedesa.com collected 2026-10-02 21:22:20 UTC 92,774 bytes, 3,563 lines download raw bytes

vendor: 36,133 bytes, lines 1-1381
1/*!
2 * Isotope PACKAGED v3.0.6
3 *
4 * Licensed GPLv3 for open source use
5 * or Isotope Commercial License for commercial use
6 *
7 * https://isotope.metafizzy.co
8 * Copyright 2010-2018 Metafizzy
9 */
10
11/**
12 * Bridget makes jQuery widgets
13 * v2.0.1
14 * MIT license
15 */
16
17/* jshint browser: true, strict: true, undef: true, unused: true */
18
19( function( window, factory ) {
20	// universal module definition
21	/*jshint strict: false */ /* globals define, module, require */
22	if ( typeof define == 'function' && define.amd ) {
23		// AMD
24		define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
25			return factory( window, jQuery );
26		});
27	} else if ( typeof module == 'object' && module.exports ) {
28		// CommonJS
29		module.exports = factory(
30			window,
31			require('jquery')
32		);
33	} else {
34		// browser global
35		window.jQueryBridget = factory(
36			window,
37			window.jQuery
38		);
39	}
40
41}( window, function factory( window, jQuery ) {
42	'use strict';
43
44// ----- utils ----- //
45
46	var arraySlice = Array.prototype.slice;
47
48// helper function for logging errors
49// $.error breaks jQuery chaining
50	var console = window.console;
51	var logError = typeof console == 'undefined' ? function() {} :
52		function( message ) {
53			console.error( message );
54		};
55
56// ----- jQueryBridget ----- //
57
58	function jQueryBridget( namespace, PluginClass, $ ) {
59		$ = $ || jQuery || window.jQuery;
60		if ( !$ ) {
61			return;
62		}
63
64		// add option method -> $().plugin('option', {...})
65		if ( !PluginClass.prototype.option ) {
66			// option setter
67			PluginClass.prototype.option = function( opts ) {
68				// bail out if not an object
69				if ( !$.isPlainObject( opts ) ){
70					return;
71				}
72				this.options = $.extend( true, this.options, opts );
73			};
74		}
75
76		// make jQuery plugin
77		$.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
78			if ( typeof arg0 == 'string' ) {
79				// method call $().plugin( 'methodName', { options } )
80				// shift arguments by 1
81				var args = arraySlice.call( arguments, 1 );
82				return methodCall( this, arg0, args );
83			}
84			// just $().plugin({ options })
85			plainCall( this, arg0 );
86			return this;
87		};
88
89		// $().plugin('methodName')
90		function methodCall( $elems, methodName, args ) {
91			var returnValue;
92			var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
93
94			$elems.each( function( i, elem ) {
95				// get instance
96				var instance = $.data( elem, namespace );
97				if ( !instance ) {
98					logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
99						pluginMethodStr );
100					return;
101				}
102
103				var method = instance[ methodName ];
104				if ( !method || methodName.charAt(0) == '_' ) {
105					logError( pluginMethodStr + ' is not a valid method' );
106					return;
107				}
108
109				// apply method, get return value
110				var value = method.apply( instance, args );
111				// set return value if value is returned, use only first value
112				returnValue = returnValue === undefined ? value : returnValue;
113			});
114
115			return returnValue !== undefined ? returnValue : $elems;
116		}
117
118		function plainCall( $elems, options ) {
119			$elems.each( function( i, elem ) {
120				var instance = $.data( elem, namespace );
121				if ( instance ) {
122					// set options & init
123					instance.option( options );
124					instance._init();
125				} else {
126					// initialize new instance
127					instance = new PluginClass( elem, options );
128					$.data( elem, namespace, instance );
129				}
130			});
131		}
132
133		updateJQuery( $ );
134
135	}
136
137// ----- updateJQuery ----- //
138
139// set $.bridget for v1 backwards compatibility
140	function updateJQuery( $ ) {
141		if ( !$ || ( $ && $.bridget ) ) {
142			return;
143		}
144		$.bridget = jQueryBridget;
145	}
146
147	updateJQuery( jQuery || window.jQuery );
148
149// -----  ----- //
150
151	return jQueryBridget;
152
153}));
154
155/**
156 * EvEmitter v1.1.0
157 * Lil' event emitter
158 * MIT License
159 */
160
161/* jshint unused: true, undef: true, strict: true */
162
163( function( global, factory ) {
164	// universal module definition
165	/* jshint strict: false */ /* globals define, module, window */
166	if ( typeof define == 'function' && define.amd ) {
167		// AMD - RequireJS
168		define( 'ev-emitter/ev-emitter',factory );
169	} else if ( typeof module == 'object' && module.exports ) {
170		// CommonJS - Browserify, Webpack
171		module.exports = factory();
172	} else {
173		// Browser globals
174		global.EvEmitter = factory();
175	}
176
177}( typeof window != 'undefined' ? window : this, function() {
178
179
180
181	function EvEmitter() {}
182
183	var proto = EvEmitter.prototype;
184
185	proto.on = function( eventName, listener ) {
186		if ( !eventName || !listener ) {
187			return;
188		}
189		// set events hash
190		var events = this._events = this._events || {};
191		// set listeners array
192		var listeners = events[ eventName ] = events[ eventName ] || [];
193		// only add once
194		if ( listeners.indexOf( listener ) == -1 ) {
195			listeners.push( listener );
196		}
197
198		return this;
199	};
200
201	proto.once = function( eventName, listener ) {
202		if ( !eventName || !listener ) {
203			return;
204		}
205		// add event
206		this.on( eventName, listener );
207		// set once flag
208		// set onceEvents hash
209		var onceEvents = this._onceEvents = this._onceEvents || {};
210		// set onceListeners object
211		var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
212		// set flag
213		onceListeners[ listener ] = true;
214
215		return this;
216	};
217
218	proto.off = function( eventName, listener ) {
219		var listeners = this._events && this._events[ eventName ];
220		if ( !listeners || !listeners.length ) {
221			return;
222		}
223		var index = listeners.indexOf( listener );
224		if ( index != -1 ) {
225			listeners.splice( index, 1 );
226		}
227
228		return this;
229	};
230
231	proto.emitEvent = function( eventName, args ) {
232		var listeners = this._events && this._events[ eventName ];
233		if ( !listeners || !listeners.length ) {
234			return;
235		}
236		// copy over to avoid interference if .off() in listener
237		listeners = listeners.slice(0);
238		args = args || [];
239		// once stuff
240		var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
241
242		for ( var i=0; i < listeners.length; i++ ) {
243			var listener = listeners[i]
244			var isOnce = onceListeners && onceListeners[ listener ];
245			if ( isOnce ) {
246				// remove listener
247				// remove before trigger to prevent recursion
248				this.off( eventName, listener );
249				// unset once flag
250				delete onceListeners[ listener ];
251			}
252			// trigger listener
253			listener.apply( this, args );
254		}
255
256		return this;
257	};
258
259	proto.allOff = function() {
260		delete this._events;
261		delete this._onceEvents;
262	};
263
264	return EvEmitter;
265
266}));
267
268/*!
269 * getSize v2.0.3
270 * measure size of elements
271 * MIT license
272 */
273
274/* jshint browser: true, strict: true, undef: true, unused: true */
275/* globals console: false */
276
277( function( window, factory ) {
278	/* jshint strict: false */ /* globals define, module */
279	if ( typeof define == 'function' && define.amd ) {
280		// AMD
281		define( 'get-size/get-size',factory );
282	} else if ( typeof module == 'object' && module.exports ) {
283		// CommonJS
284		module.exports = factory();
285	} else {
286		// browser global
287		window.getSize = factory();
288	}
289
290})( window, function factory() {
291	'use strict';
292
293// -------------------------- helpers -------------------------- //
294
295// get a number from a string, not a percentage
296	function getStyleSize( value ) {
297		var num = parseFloat( value );
298		// not a percent like '100%', and a number
299		var isValid = value.indexOf('%') == -1 && !isNaN( num );
300		return isValid && num;
301	}
302
303	function noop() {}
304
305	var logError = typeof console == 'undefined' ? noop :
306		function( message ) {
307			console.error( message );
308		};
309
310// -------------------------- measurements -------------------------- //
311
312	var measurements = [
313		'paddingLeft',
314		'paddingRight',
315		'paddingTop',
316		'paddingBottom',
317		'marginLeft',
318		'marginRight',
319		'marginTop',
320		'marginBottom',
321		'borderLeftWidth',
322		'borderRightWidth',
323		'borderTopWidth',
324		'borderBottomWidth'
325	];
326
327	var measurementsLength = measurements.length;
328
329	function getZeroSize() {
330		var size = {
331			width: 0,
332			height: 0,
333			innerWidth: 0,
334			innerHeight: 0,
335			outerWidth: 0,
336			outerHeight: 0
337		};
338		for ( var i=0; i < measurementsLength; i++ ) {
339			var measurement = measurements[i];
340			size[ measurement ] = 0;
341		}
342		return size;
343	}
344
345// -------------------------- getStyle -------------------------- //
346
347	/**
348	 * getStyle, get style of element, check for Firefox bug
349	 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
350	 */
351	function getStyle( elem ) {
352		var style = getComputedStyle( elem );
353		if ( !style ) {
354			logError( 'Style returned ' + style +
355				'. Are you running this code in a hidden iframe on Firefox? ' +
356				'See https://bit.ly/getsizebug1' );
357		}
358		return style;
359	}
360
361// -------------------------- setup -------------------------- //
362
363	var isSetup = false;
364
365	var isBoxSizeOuter;
366
367	/**
368	 * setup
369	 * check isBoxSizerOuter
370	 * do on first getSize() rather than on page load for Firefox bug
371	 */
372	function setup() {
373		// setup once
374		if ( isSetup ) {
375			return;
376		}
377		isSetup = true;
378
379		// -------------------------- box sizing -------------------------- //
380
381		/**
382		 * Chrome & Safari measure the outer-width on style.width on border-box elems
383		 * IE11 & Firefox<29 measures the inner-width
384		 */
385		var div = document.createElement('div');
386		div.style.width = '200px';
387		div.style.padding = '1px 2px 3px 4px';
388		div.style.borderStyle = 'solid';
389		div.style.borderWidth = '1px 2px 3px 4px';
390		div.style.boxSizing = 'border-box';
391
392		var body = document.body || document.documentElement;
393		body.appendChild( div );
394		var style = getStyle( div );
395		// round value for browser zoom. desandro/masonry#928
396		isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;
397		getSize.isBoxSizeOuter = isBoxSizeOuter;
398
399		body.removeChild( div );
400	}
401
402// -------------------------- getSize -------------------------- //
403
404	function getSize( elem ) {
405		setup();
406
407		// use querySeletor if elem is string
408		if ( typeof elem == 'string' ) {
409			elem = document.querySelector( elem );
410		}
411
412		// do not proceed on non-objects
413		if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
414			return;
415		}
416
417		var style = getStyle( elem );
418
419		// if hidden, everything is 0
420		if ( style.display == 'none' ) {
421			return getZeroSize();
422		}
423
424		var size = {};
425		size.width = elem.offsetWidth;
426		size.height = elem.offsetHeight;
427
428		var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
429
430		// get all measurements
431		for ( var i=0; i < measurementsLength; i++ ) {
432			var measurement = measurements[i];
433			var value = style[ measurement ];
434			var num = parseFloat( value );
435			// any 'auto', 'medium' value will be 0
436			size[ measurement ] = !isNaN( num ) ? num : 0;
437		}
438
439		var paddingWidth = size.paddingLeft + size.paddingRight;
440		var paddingHeight = size.paddingTop + size.paddingBottom;
441		var marginWidth = size.marginLeft + size.marginRight;
442		var marginHeight = size.marginTop + size.marginBottom;
443		var borderWidth = size.borderLeftWidth + size.borderRightWidth;
444		var borderHeight = size.borderTopWidth + size.borderBottomWidth;
445
446		var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
447
448		// overwrite width and height if we can get it from style
449		var styleWidth = getStyleSize( style.width );
450		if ( styleWidth !== false ) {
451			size.width = styleWidth +
452				// add padding and border unless it's already including it
453				( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
454		}
455
456		var styleHeight = getStyleSize( style.height );
457		if ( styleHeight !== false ) {
458			size.height = styleHeight +
459				// add padding and border unless it's already including it
460				( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
461		}
462
463		size.innerWidth = size.width - ( paddingWidth + borderWidth );
464		size.innerHeight = size.height - ( paddingHeight + borderHeight );
465
466		size.outerWidth = size.width + marginWidth;
467		size.outerHeight = size.height + marginHeight;
468
469		return size;
470	}
471
472	return getSize;
473
474});
475
476/**
477 * matchesSelector v2.0.2
478 * matchesSelector( element, '.selector' )
479 * MIT license
480 */
481
482/*jshint browser: true, strict: true, undef: true, unused: true */
483
484( function( window, factory ) {
485	/*global define: false, module: false */
486	'use strict';
487	// universal module definition
488	if ( typeof define == 'function' && define.amd ) {
489		// AMD
490		define( 'desandro-matches-selector/matches-selector',factory );
491	} else if ( typeof module == 'object' && module.exports ) {
492		// CommonJS
493		module.exports = factory();
494	} else {
495		// browser global
496		window.matchesSelector = factory();
497	}
498
499}( window, function factory() {
500	'use strict';
501
502	var matchesMethod = ( function() {
503		var ElemProto = window.Element.prototype;
504		// check for the standard method name first
505		if ( ElemProto.matches ) {
506			return 'matches';
507		}
508		// check un-prefixed
509		if ( ElemProto.matchesSelector ) {
510			return 'matchesSelector';
511		}
512		// check vendor prefixes
513		var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
514
515		for ( var i=0; i < prefixes.length; i++ ) {
516			var prefix = prefixes[i];
517			var method = prefix + 'MatchesSelector';
518			if ( ElemProto[ method ] ) {
519				return method;
520			}
521		}
522	})();
523
524	return function matchesSelector( elem, selector ) {
525		return elem[ matchesMethod ]( selector );
526	};
527
528}));
529
530/**
531 * Fizzy UI utils v2.0.7
532 * MIT license
533 */
534
535/*jshint browser: true, undef: true, unused: true, strict: true */
536
537( function( window, factory ) {
538	// universal module definition
539	/*jshint strict: false */ /*globals define, module, require */
540
541	if ( typeof define == 'function' && define.amd ) {
542		// AMD
543		define( 'fizzy-ui-utils/utils',[
544			'desandro-matches-selector/matches-selector'
545		], function( matchesSelector ) {
546			return factory( window, matchesSelector );
547		});
548	} else if ( typeof module == 'object' && module.exports ) {
549		// CommonJS
550		module.exports = factory(
551			window,
552			require('desandro-matches-selector')
553		);
554	} else {
555		// browser global
556		window.fizzyUIUtils = factory(
557			window,
558			window.matchesSelector
559		);
560	}
561
562}( window, function factory( window, matchesSelector ) {
563
564
565
566	var utils = {};
567
568// ----- extend ----- //
569
570// extends objects
571	utils.extend = function( a, b ) {
572		for ( var prop in b ) {
573			a[ prop ] = b[ prop ];
574		}
575		return a;
576	};
577
578// ----- modulo ----- //
579
580	utils.modulo = function( num, div ) {
581		return ( ( num % div ) + div ) % div;
582	};
583
584// ----- makeArray ----- //
585
586	var arraySlice = Array.prototype.slice;
587
588// turn element or nodeList into an array
589	utils.makeArray = function( obj ) {
590		if ( Array.isArray( obj ) ) {
591			// use object if already an array
592			return obj;
593		}
594		// return empty array if undefined or null. #6
595		if ( obj === null || obj === undefined ) {
596			return [];
597		}
598
599		var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
600		if ( isArrayLike ) {
601			// convert nodeList to array
602			return arraySlice.call( obj );
603		}
604
605		// array of single index
606		return [ obj ];
607	};
608
609// ----- removeFrom ----- //
610
611	utils.removeFrom = function( ary, obj ) {
612		var index = ary.indexOf( obj );
613		if ( index != -1 ) {
614			ary.splice( index, 1 );
615		}
616	};
617
618// ----- getParent ----- //
619
620	utils.getParent = function( elem, selector ) {
621		while ( elem.parentNode && elem != document.body ) {
622			elem = elem.parentNode;
623			if ( matchesSelector( elem, selector ) ) {
624				return elem;
625			}
626		}
627	};
628
629// ----- getQueryElement ----- //
630
631// use element as selector string
632	utils.getQueryElement = function( elem ) {
633		if ( typeof elem == 'string' ) {
634			return document.querySelector( elem );
635		}
636		return elem;
637	};
638
639// ----- handleEvent ----- //
640
641// enable .ontype to trigger from .addEventListener( elem, 'type' )
642	utils.handleEvent = function( event ) {
643		var method = 'on' + event.type;
644		if ( this[ method ] ) {
645			this[ method ]( event );
646		}
647	};
648
649// ----- filterFindElements ----- //
650
651	utils.filterFindElements = function( elems, selector ) {
652		// make array of elems
653		elems = utils.makeArray( elems );
654		var ffElems = [];
655
656		elems.forEach( function( elem ) {
657			// check that elem is an actual element
658			if ( !( elem instanceof HTMLElement ) ) {
659				return;
660			}
661			// add elem if no selector
662			if ( !selector ) {
663				ffElems.push( elem );
664				return;
665			}
666			// filter & find items if we have a selector
667			// filter
668			if ( matchesSelector( elem, selector ) ) {
669				ffElems.push( elem );
670			}
671			// find children
672			var childElems = elem.querySelectorAll( selector );
673			// concat childElems to filterFound array
674			for ( var i=0; i < childElems.length; i++ ) {
675				ffElems.push( childElems[i] );
676			}
677		});
678
679		return ffElems;
680	};
681
682// ----- debounceMethod ----- //
683
684	utils.debounceMethod = function( _class, methodName, threshold ) {
685		threshold = threshold || 100;
686		// original method
687		var method = _class.prototype[ methodName ];
688		var timeoutName = methodName + 'Timeout';
689
690		_class.prototype[ methodName ] = function() {
691			var timeout = this[ timeoutName ];
692			clearTimeout( timeout );
693
694			var args = arguments;
695			var _this = this;
696			this[ timeoutName ] = setTimeout( function() {
697				method.apply( _this, args );
698				delete _this[ timeoutName ];
699			}, threshold );
700		};
701	};
702
703// ----- docReady ----- //
704
705	utils.docReady = function( callback ) {
706		var readyState = document.readyState;
707		if ( readyState == 'complete' || readyState == 'interactive' ) {
708			// do async to allow for other scripts to run. metafizzy/flickity#441
709			setTimeout( callback );
710		} else {
711			document.addEventListener( 'DOMContentLoaded', callback );
712		}
713	};
714
715// ----- htmlInit ----- //
716
717// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
718	utils.toDashed = function( str ) {
719		return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
720			return $1 + '-' + $2;
721		}).toLowerCase();
722	};
723
724	var console = window.console;
725	/**
726	 * allow user to initialize classes via [data-namespace] or .js-namespace class
727	 * htmlInit( Widget, 'widgetName' )
728	 * options are parsed from data-namespace-options
729	 */
730	utils.htmlInit = function( WidgetClass, namespace ) {
731		utils.docReady( function() {
732			var dashedNamespace = utils.toDashed( namespace );
733			var dataAttr = 'data-' + dashedNamespace;
734			var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
735			var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
736			var elems = utils.makeArray( dataAttrElems )
737				.concat( utils.makeArray( jsDashElems ) );
738			var dataOptionsAttr = dataAttr + '-options';
739			var jQuery = window.jQuery;
740
741			elems.forEach( function( elem ) {
742				var attr = elem.getAttribute( dataAttr ) ||
743					elem.getAttribute( dataOptionsAttr );
744				var options;
745				try {
746					options = attr && JSON.parse( attr );
747				} catch ( error ) {
748					// log error, do not initialize
749					if ( console ) {
750						console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
751							': ' + error );
752					}
753					return;
754				}
755				// initialize
756				var instance = new WidgetClass( elem, options );
757				// make available via $().data('namespace')
758				if ( jQuery ) {
759					jQuery.data( elem, namespace, instance );
760				}
761			});
762
763		});
764	};
765
766// -----  ----- //
767
768	return utils;
769
770}));
771
772/**
773 * Outlayer Item
774 */
775
776( function( window, factory ) {
777	// universal module definition
778	/* jshint strict: false */ /* globals define, module, require */
779	if ( typeof define == 'function' && define.amd ) {
780		// AMD - RequireJS
781		define( 'outlayer/item',[
782				'ev-emitter/ev-emitter',
783				'get-size/get-size'
784			],
785			factory
786		);
787	} else if ( typeof module == 'object' && module.exports ) {
788		// CommonJS - Browserify, Webpack
789		module.exports = factory(
790			require('ev-emitter'),
791			require('get-size')
792		);
793	} else {
794		// browser global
795		window.Outlayer = {};
796		window.Outlayer.Item = factory(
797			window.EvEmitter,
798			window.getSize
799		);
800	}
801
802}( window, function factory( EvEmitter, getSize ) {
803	'use strict';
804
805// ----- helpers ----- //
806
807	function isEmptyObj( obj ) {
808		for ( var prop in obj ) {
809			return false;
810		}
811		prop = null;
812		return true;
813	}
814
815// -------------------------- CSS3 support -------------------------- //
816
817
818	var docElemStyle = document.documentElement.style;
819
820	var transitionProperty = typeof docElemStyle.transition == 'string' ?
821		'transition' : 'WebkitTransition';
822	var transformProperty = typeof docElemStyle.transform == 'string' ?
823		'transform' : 'WebkitTransform';
824
825	var transitionEndEvent = {
826		WebkitTransition: 'webkitTransitionEnd',
827		transition: 'transitionend'
828	}[ transitionProperty ];
829
830// cache all vendor properties that could have vendor prefix
831	var vendorProperties = {
832		transform: transformProperty,
833		transition: transitionProperty,
834		transitionDuration: transitionProperty + 'Duration',
835		transitionProperty: transitionProperty + 'Property',
836		transitionDelay: transitionProperty + 'Delay'
837	};
838
839// -------------------------- Item -------------------------- //
840
841	function Item( element, layout ) {
842		if ( !element ) {
843			return;
844		}
845
846		this.element = element;
847		// parent layout class, i.e. Masonry, Isotope, or Packery
848		this.layout = layout;
849		this.position = {
850			x: 0,
851			y: 0
852		};
853
854		this._create();
855	}
856
857// inherit EvEmitter
858	var proto = Item.prototype = Object.create( EvEmitter.prototype );
859	proto.constructor = Item;
860
861	proto._create = function() {
862		// transition objects
863		this._transn = {
864			ingProperties: {},
865			clean: {},
866			onEnd: {}
867		};
868
869		this.css({
870			position: 'absolute'
871		});
872	};
873
874// trigger specified handler for event type
875	proto.handleEvent = function( event ) {
876		var method = 'on' + event.type;
877		if ( this[ method ] ) {
878			this[ method ]( event );
879		}
880	};
881
882	proto.getSize = function() {
883		this.size = getSize( this.element );
884	};
885
886	/**
887	 * apply CSS styles to element
888	 * @param {Object} style
889	 */
890	proto.css = function( style ) {
891		var elemStyle = this.element.style;
892
893		for ( var prop in style ) {
894			// use vendor property if available
895			var supportedProp = vendorProperties[ prop ] || prop;
896			elemStyle[ supportedProp ] = style[ prop ];
897		}
898	};
899
900	// measure position, and sets it
901	proto.getPosition = function() {
902		var style = getComputedStyle( this.element );
903		var isOriginLeft = this.layout._getOption('originLeft');
904		var isOriginTop = this.layout._getOption('originTop');
905		var xValue = style[ isOriginLeft ? 'left' : 'right' ];
906		var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
907		var x = parseFloat( xValue );
908		var y = parseFloat( yValue );
909		// convert percent to pixels
910		var layoutSize = this.layout.size;
911		if ( xValue.indexOf('%') != -1 ) {
912			x = ( x / 100 ) * layoutSize.width;
913		}
914		if ( yValue.indexOf('%') != -1 ) {
915			y = ( y / 100 ) * layoutSize.height;
916		}
917		// clean up 'auto' or other non-integer values
918		x = isNaN( x ) ? 0 : x;
919		y = isNaN( y ) ? 0 : y;
920		// remove padding from measurement
921		x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
922		y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
923
924		this.position.x = x;
925		this.position.y = y;
926	};
927
928// set settled position, apply padding
929	proto.layoutPosition = function() {
930		var layoutSize = this.layout.size;
931		var style = {};
932		var isOriginLeft = this.layout._getOption('originLeft');
933		var isOriginTop = this.layout._getOption('originTop');
934
935		// x
936		var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
937		var xProperty = isOriginLeft ? 'left' : 'right';
938		var xResetProperty = isOriginLeft ? 'right' : 'left';
939
940		var x = this.position.x + layoutSize[ xPadding ];
941		// set in percentage or pixels
942		style[ xProperty ] = this.getXValue( x );
943		// reset other property
944		style[ xResetProperty ] = '';
945
946		// y
947		var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
948		var yProperty = isOriginTop ? 'top' : 'bottom';
949		var yResetProperty = isOriginTop ? 'bottom' : 'top';
950
951		var y = this.position.y + layoutSize[ yPadding ];
952		// set in percentage or pixels
953		style[ yProperty ] = this.getYValue( y );
954		// reset other property
955		style[ yResetProperty ] = '';
956
957		this.css( style );
958		this.emitEvent( 'layout', [ this ] );
959	};
960
961	proto.getXValue = function( x ) {
962		var isHorizontal = this.layout._getOption('horizontal');
963		return this.layout.options.percentPosition && !isHorizontal ?
964			( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
965	};
966
967	proto.getYValue = function( y ) {
968		var isHorizontal = this.layout._getOption('horizontal');
969		return this.layout.options.percentPosition && isHorizontal ?
970			( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
971	};
972
973	proto._transitionTo = function( x, y ) {
974		this.getPosition();
975		// get current x & y from top/left
976		var curX = this.position.x;
977		var curY = this.position.y;
978
979		var didNotMove = x == this.position.x && y == this.position.y;
980
981		// save end position
982		this.setPosition( x, y );
983
984		// if did not move and not transitioning, just go to layout
985		if ( didNotMove && !this.isTransitioning ) {
986			this.layoutPosition();
987			return;
988		}
989
990		var transX = x - curX;
991		var transY = y - curY;
992		var transitionStyle = {};
993		transitionStyle.transform = this.getTranslate( transX, transY );
994
995		this.transition({
996			to: transitionStyle,
997			onTransitionEnd: {
998				transform: this.layoutPosition
999			},
1000			isCleaning: true
1001		});
1002	};
1003
1004	proto.getTranslate = function( x, y ) {
1005		// flip cooridinates if origin on right or bottom
1006		var isOriginLeft = this.layout._getOption('originLeft');
1007		var isOriginTop = this.layout._getOption('originTop');
1008		x = isOriginLeft ? x : -x;
1009		y = isOriginTop ? y : -y;
1010		return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
1011	};
1012
1013// non transition + transform support
1014	proto.goTo = function( x, y ) {
1015		this.setPosition( x, y );
1016		this.layoutPosition();
1017	};
1018
1019	proto.moveTo = proto._transitionTo;
1020
1021	proto.setPosition = function( x, y ) {
1022		this.position.x = parseFloat( x );
1023		this.position.y = parseFloat( y );
1024	};
1025
1026// ----- transition ----- //
1027
1028	/**
1029	 * @param {Object} style - CSS
1030	 * @param {Function} onTransitionEnd
1031	 */
1032
1033// non transition, just trigger callback
1034	proto._nonTransition = function( args ) {
1035		this.css( args.to );
1036		if ( args.isCleaning ) {
1037			this._removeStyles( args.to );
1038		}
1039		for ( var prop in args.onTransitionEnd ) {
1040			args.onTransitionEnd[ prop ].call( this );
1041		}
1042	};
1043
1044	/**
1045	 * proper transition
1046	 * @param {Object} args - arguments
1047	 *   @param {Object} to - style to transition to
1048	 *   @param {Object} from - style to start transition from
1049	 *   @param {Boolean} isCleaning - removes transition styles after transition
1050	 *   @param {Function} onTransitionEnd - callback
1051	 */
1052	proto.transition = function( args ) {
1053		// redirect to nonTransition if no transition duration
1054		if ( !parseFloat( this.layout.options.transitionDuration ) ) {
1055			this._nonTransition( args );
1056			return;
1057		}
1058
1059		var _transition = this._transn;
1060		// keep track of onTransitionEnd callback by css property
1061		for ( var prop in args.onTransitionEnd ) {
1062			_transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
1063		}
1064		// keep track of properties that are transitioning
1065		for ( prop in args.to ) {
1066			_transition.ingProperties[ prop ] = true;
1067			// keep track of properties to clean up when transition is done
1068			if ( args.isCleaning ) {
1069				_transition.clean[ prop ] = true;
1070			}
1071		}
1072
1073		// set from styles
1074		if ( args.from ) {
1075			this.css( args.from );
1076			// force redraw. http://blog.alexmaccaw.com/css-transitions
1077			var h = this.element.offsetHeight;
1078			// hack for JSHint to hush about unused var
1079			h = null;
1080		}
1081		// enable transition
1082		this.enableTransition( args.to );
1083		// set styles that are transitioning
1084		this.css( args.to );
1085
1086		this.isTransitioning = true;
1087
1088	};
1089
1090// dash before all cap letters, including first for
1091// WebkitTransform => -webkit-transform
1092	function toDashedAll( str ) {
1093		return str.replace( /([A-Z])/g, function( $1 ) {
1094			return '-' + $1.toLowerCase();
1095		});
1096	}
1097
1098	var transitionProps = 'opacity,' + toDashedAll( transformProperty );
1099
1100	proto.enableTransition = function(/* style */) {
1101		// HACK changing transitionProperty during a transition
1102		// will cause transition to jump
1103		if ( this.isTransitioning ) {
1104			return;
1105		}
1106
1107		// make `transition: foo, bar, baz` from style object
1108		// HACK un-comment this when enableTransition can work
1109		// while a transition is happening
1110		// var transitionValues = [];
1111		// for ( var prop in style ) {
1112		//   // dash-ify camelCased properties like WebkitTransition
1113		//   prop = vendorProperties[ prop ] || prop;
1114		//   transitionValues.push( toDashedAll( prop ) );
1115		// }
1116		// munge number to millisecond, to match stagger
1117		var duration = this.layout.options.transitionDuration;
1118		duration = typeof duration == 'number' ? duration + 'ms' : duration;
1119		// enable transition styles
1120		this.css({
1121			transitionProperty: transitionProps,
1122			transitionDuration: duration,
1123			transitionDelay: this.staggerDelay || 0
1124		});
1125		// listen for transition end event
1126		this.element.addEventListener( transitionEndEvent, this, false );
1127	};
1128
1129// ----- events ----- //
1130
1131	proto.onwebkitTransitionEnd = function( event ) {
1132		this.ontransitionend( event );
1133	};
1134
1135	proto.onotransitionend = function( event ) {
1136		this.ontransitionend( event );
1137	};
1138
1139// properties that I munge to make my life easier
1140	var dashedVendorProperties = {
1141		'-webkit-transform': 'transform'
1142	};
1143
1144	proto.ontransitionend = function( event ) {
1145		// disregard bubbled events from children
1146		if ( event.target !== this.element ) {
1147			return;
1148		}
1149		var _transition = this._transn;
1150		// get property name of transitioned property, convert to prefix-free
1151		var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
1152
1153		// remove property that has completed transitioning
1154		delete _transition.ingProperties[ propertyName ];
1155		// check if any properties are still transitioning
1156		if ( isEmptyObj( _transition.ingProperties ) ) {
1157			// all properties have completed transitioning
1158			this.disableTransition();
1159		}
1160		// clean style
1161		if ( propertyName in _transition.clean ) {
1162			// clean up style
1163			this.element.style[ event.propertyName ] = '';
1164			delete _transition.clean[ propertyName ];
1165		}
1166		// trigger onTransitionEnd callback
1167		if ( propertyName in _transition.onEnd ) {
1168			var onTransitionEnd = _transition.onEnd[ propertyName ];
1169			onTransitionEnd.call( this );
1170			delete _transition.onEnd[ propertyName ];
1171		}
1172
1173		this.emitEvent( 'transitionEnd', [ this ] );
1174	};
1175
1176	proto.disableTransition = function() {
1177		this.removeTransitionStyles();
1178		this.element.removeEventListener( transitionEndEvent, this, false );
1179		this.isTransitioning = false;
1180	};
1181
1182	/**
1183	 * removes style property from element
1184	 * @param {Object} style
1185	 **/
1186	proto._removeStyles = function( style ) {
1187		// clean up transition styles
1188		var cleanStyle = {};
1189		for ( var prop in style ) {
1190			cleanStyle[ prop ] = '';
1191		}
1192		this.css( cleanStyle );
1193	};
1194
1195	var cleanTransitionStyle = {
1196		transitionProperty: '',
1197		transitionDuration: '',
1198		transitionDelay: ''
1199	};
1200
1201	proto.removeTransitionStyles = function() {
1202		// remove transition
1203		this.css( cleanTransitionStyle );
1204	};
1205
1206// ----- stagger ----- //
1207
1208	proto.stagger = function( delay ) {
1209		delay = isNaN( delay ) ? 0 : delay;
1210		this.staggerDelay = delay + 'ms';
1211	};
1212
1213// ----- show/hide/remove ----- //
1214
1215// remove element from DOM
1216	proto.removeElem = function() {
1217		this.element.parentNode.removeChild( this.element );
1218		// remove display: none
1219		this.css({ display: '' });
1220		this.emitEvent( 'remove', [ this ] );
1221	};
1222
1223	proto.remove = function() {
1224		// just remove element if no transition support or no transition
1225		if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
1226			this.removeElem();
1227			return;
1228		}
1229
1230		// start transition
1231		this.once( 'transitionEnd', function() {
1232			this.removeElem();
1233		});
1234		this.hide();
1235	};
1236
1237	proto.reveal = function() {
1238		delete this.isHidden;
1239		// remove display: none
1240		this.css({ display: '' });
1241
1242		var options = this.layout.options;
1243
1244		var onTransitionEnd = {};
1245		var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
1246		onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
1247
1248		this.transition({
1249			from: options.hiddenStyle,
1250			to: options.visibleStyle,
1251			isCleaning: true,
1252			onTransitionEnd: onTransitionEnd
1253		});
1254	};
1255
1256	proto.onRevealTransitionEnd = function() {
1257		// check if still visible
1258		// during transition, item may have been hidden
1259		if ( !this.isHidden ) {
1260			this.emitEvent('reveal');
1261		}
1262	};
1263
1264	/**
1265	 * get style property use for hide/reveal transition end
1266	 * @param {String} styleProperty - hiddenStyle/visibleStyle
1267	 * @returns {String}
1268	 */
1269	proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
1270		var optionStyle = this.layout.options[ styleProperty ];
1271		// use opacity
1272		if ( optionStyle.opacity ) {
1273			return 'opacity';
1274		}
1275		// get first property
1276		for ( var prop in optionStyle ) {
1277			return prop;
1278		}
1279	};
1280
1281	proto.hide = function() {
1282		// set flag
1283		this.isHidden = true;
1284		// remove display: none
1285		this.css({ display: '' });
1286
1287		var options = this.layout.options;
1288
1289		var onTransitionEnd = {};
1290		var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
1291		onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
1292
1293		this.transition({
1294			from: options.visibleStyle,
1295			to: options.hiddenStyle,
1296			// keep hidden stuff hidden
1297			isCleaning: true,
1298			onTransitionEnd: onTransitionEnd
1299		});
1300	};
1301
1302	proto.onHideTransitionEnd = function() {
1303		// check if still hidden
1304		// during transition, item may have been un-hidden
1305		if ( this.isHidden ) {
1306			this.css({ display: 'none' });
1307			this.emitEvent('hide');
1308		}
1309	};
1310
1311	proto.destroy = function() {
1312		this.css({
1313			position: '',
1314			left: '',
1315			right: '',
1316			top: '',
1317			bottom: '',
1318			transition: '',
1319			transform: ''
1320		});
1321	};
1322
1323	return Item;
1324
1325}));
1326
1327/*!
1328 * Outlayer v2.1.1
1329 * the brains and guts of a layout library
1330 * MIT license
1331 */
1332
1333( function( window, factory ) {
1334	'use strict';
1335	// universal module definition
1336	/* jshint strict: false */ /* globals define, module, require */
1337	if ( typeof define == 'function' && define.amd ) {
1338		// AMD - RequireJS
1339		define( 'outlayer/outlayer',[
1340				'ev-emitter/ev-emitter',
1341				'get-size/get-size',
1342				'fizzy-ui-utils/utils',
1343				'./item'
1344			],
1345			function( EvEmitter, getSize, utils, Item ) {
1346				return factory( window, EvEmitter, getSize, utils, Item);
1347			}
1348		);
1349	} else if ( typeof module == 'object' && module.exports ) {
1350		// CommonJS - Browserify, Webpack
1351		module.exports = factory(
1352			window,
1353			require('ev-emitter'),
1354			require('get-size'),
1355			require('fizzy-ui-utils'),
1356			require('./item')
1357		);
1358	} else {
1359		// browser global
1360		window.Outlayer = factory(
1361			window,
1362			window.EvEmitter,
1363			window.getSize,
1364			window.fizzyUIUtils,
1365			window.Outlayer.Item
1366		);
1367	}
1368
1369}( window, function factory( window, EvEmitter, getSize, utils, Item ) {
1370	'use strict';
1371
1372// ----- vars ----- //
1373
1374	var console = window.console;
1375	var jQuery = window.jQuery;
1376	var noop = function() {};
1377
1378// -------------------------- Outlayer -------------------------- //
1379
1380// globally unique identifiers
1381	var GUID = 0;
vendor: 18,809 bytes, lines 1382-2139
1382// internal store of all Outlayer intances
1383	var instances = {};
1384
1385
1386	/**
1387	 * @param {Element, String} element
1388	 * @param {Object} options
1389	 * @constructor
1390	 */
1391	function Outlayer( element, options ) {
1392		var queryElement = utils.getQueryElement( element );
1393		if ( !queryElement ) {
1394			if ( console ) {
1395				console.error( 'Bad element for ' + this.constructor.namespace +
1396					': ' + ( queryElement || element ) );
1397			}
1398			return;
1399		}
1400		this.element = queryElement;
1401		// add jQuery
1402		if ( jQuery ) {
1403			this.$element = jQuery( this.element );
1404		}
1405
1406		// options
1407		this.options = utils.extend( {}, this.constructor.defaults );
1408		this.option( options );
1409
1410		// add id for Outlayer.getFromElement
1411		var id = ++GUID;
1412		this.element.outlayerGUID = id; // expando
1413		instances[ id ] = this; // associate via id
1414
1415		// kick it off
1416		this._create();
1417
1418		var isInitLayout = this._getOption('initLayout');
1419		if ( isInitLayout ) {
1420			this.layout();
1421		}
1422	}
1423
1424// settings are for internal use only
1425	Outlayer.namespace = 'outlayer';
1426	Outlayer.Item = Item;
1427
1428// default options
1429	Outlayer.defaults = {
1430		containerStyle: {
1431			position: 'relative'
1432		},
1433		initLayout: true,
1434		originLeft: true,
1435		originTop: true,
1436		resize: true,
1437		resizeContainer: true,
1438		// item options
1439		transitionDuration: '0.4s',
1440		hiddenStyle: {
1441			opacity: 0,
1442			transform: 'scale(0.001)'
1443		},
1444		visibleStyle: {
1445			opacity: 1,
1446			transform: 'scale(1)'
1447		}
1448	};
1449
1450	var proto = Outlayer.prototype;
1451// inherit EvEmitter
1452	utils.extend( proto, EvEmitter.prototype );
1453
1454	/**
1455	 * set options
1456	 * @param {Object} opts
1457	 */
1458	proto.option = function( opts ) {
1459		utils.extend( this.options, opts );
1460	};
1461
1462	/**
1463	 * get backwards compatible option value, check old name
1464	 */
1465	proto._getOption = function( option ) {
1466		var oldOption = this.constructor.compatOptions[ option ];
1467		return oldOption && this.options[ oldOption ] !== undefined ?
1468			this.options[ oldOption ] : this.options[ option ];
1469	};
1470
1471	Outlayer.compatOptions = {
1472		// currentName: oldName
1473		initLayout: 'isInitLayout',
1474		horizontal: 'isHorizontal',
1475		layoutInstant: 'isLayoutInstant',
1476		originLeft: 'isOriginLeft',
1477		originTop: 'isOriginTop',
1478		resize: 'isResizeBound',
1479		resizeContainer: 'isResizingContainer'
1480	};
1481
1482	proto._create = function() {
1483		// get items from children
1484		this.reloadItems();
1485		// elements that affect layout, but are not laid out
1486		this.stamps = [];
1487		this.stamp( this.options.stamp );
1488		// set container style
1489		utils.extend( this.element.style, this.options.containerStyle );
1490
1491		// bind resize method
1492		var canBindResize = this._getOption('resize');
1493		if ( canBindResize ) {
1494			this.bindResize();
1495		}
1496	};
1497
1498// goes through all children again and gets bricks in proper order
1499	proto.reloadItems = function() {
1500		// collection of item elements
1501		this.items = this._itemize( this.element.children );
1502	};
1503
1504
1505	/**
1506	 * turn elements into Outlayer.Items to be used in layout
1507	 * @param {Array or NodeList or HTMLElement} elems
1508	 * @returns {Array} items - collection of new Outlayer Items
1509	 */
1510	proto._itemize = function( elems ) {
1511
1512		var itemElems = this._filterFindItemElements( elems );
1513		var Item = this.constructor.Item;
1514
1515		// create new Outlayer Items for collection
1516		var items = [];
1517		for ( var i=0; i < itemElems.length; i++ ) {
1518			var elem = itemElems[i];
1519			var item = new Item( elem, this );
1520			items.push( item );
1521		}
1522
1523		return items;
1524	};
1525
1526	/**
1527	 * get item elements to be used in layout
1528	 * @param {Array or NodeList or HTMLElement} elems
1529	 * @returns {Array} items - item elements
1530	 */
1531	proto._filterFindItemElements = function( elems ) {
1532		return utils.filterFindElements( elems, this.options.itemSelector );
1533	};
1534
1535	/**
1536	 * getter method for getting item elements
1537	 * @returns {Array} elems - collection of item elements
1538	 */
1539	proto.getItemElements = function() {
1540		return this.items.map( function( item ) {
1541			return item.element;
1542		});
1543	};
1544
1545// ----- init & layout ----- //
1546
1547	/**
1548	 * lays out all items
1549	 */
1550	proto.layout = function() {
1551		this._resetLayout();
1552		this._manageStamps();
1553
1554		// don't animate first layout
1555		var layoutInstant = this._getOption('layoutInstant');
1556		var isInstant = layoutInstant !== undefined ?
1557			layoutInstant : !this._isLayoutInited;
1558		this.layoutItems( this.items, isInstant );
1559
1560		// flag for initalized
1561		this._isLayoutInited = true;
1562	};
1563
1564// _init is alias for layout
1565	proto._init = proto.layout;
1566
1567	/**
1568	 * logic before any new layout
1569	 */
1570	proto._resetLayout = function() {
1571		this.getSize();
1572	};
1573
1574
1575	proto.getSize = function() {
1576		this.size = getSize( this.element );
1577	};
1578
1579	/**
1580	 * get measurement from option, for columnWidth, rowHeight, gutter
1581	 * if option is String -> get element from selector string, & get size of element
1582	 * if option is Element -> get size of element
1583	 * else use option as a number
1584	 *
1585	 * @param {String} measurement
1586	 * @param {String} size - width or height
1587	 * @private
1588	 */
1589	proto._getMeasurement = function( measurement, size ) {
1590		var option = this.options[ measurement ];
1591		var elem;
1592		if ( !option ) {
1593			// default to 0
1594			this[ measurement ] = 0;
1595		} else {
1596			// use option as an element
1597			if ( typeof option == 'string' ) {
1598				elem = this.element.querySelector( option );
1599			} else if ( option instanceof HTMLElement ) {
1600				elem = option;
1601			}
1602			// use size of element, if element
1603			this[ measurement ] = elem ? getSize( elem )[ size ] : option;
1604		}
1605	};
1606
1607	/**
1608	 * layout a collection of item elements
1609	 * @api public
1610	 */
1611	proto.layoutItems = function( items, isInstant ) {
1612		items = this._getItemsForLayout( items );
1613
1614		this._layoutItems( items, isInstant );
1615
1616		this._postLayout();
1617	};
1618
1619	/**
1620	 * get the items to be laid out
1621	 * you may want to skip over some items
1622	 * @param {Array} items
1623	 * @returns {Array} items
1624	 */
1625	proto._getItemsForLayout = function( items ) {
1626		return items.filter( function( item ) {
1627			return !item.isIgnored;
1628		});
1629	};
1630
1631	/**
1632	 * layout items
1633	 * @param {Array} items
1634	 * @param {Boolean} isInstant
1635	 */
1636	proto._layoutItems = function( items, isInstant ) {
1637		this._emitCompleteOnItems( 'layout', items );
1638
1639		if ( !items || !items.length ) {
1640			// no items, emit event with empty array
1641			return;
1642		}
1643
1644		var queue = [];
1645
1646		items.forEach( function( item ) {
1647			// get x/y object from method
1648			var position = this._getItemLayoutPosition( item );
1649			// enqueue
1650			position.item = item;
1651			position.isInstant = isInstant || item.isLayoutInstant;
1652			queue.push( position );
1653		}, this );
1654
1655		this._processLayoutQueue( queue );
1656	};
1657
1658	/**
1659	 * get item layout position
1660	 * @param {Outlayer.Item} item
1661	 * @returns {Object} x and y position
1662	 */
1663	proto._getItemLayoutPosition = function( /* item */ ) {
1664		return {
1665			x: 0,
1666			y: 0
1667		};
1668	};
1669
1670	/**
1671	 * iterate over array and position each item
1672	 * Reason being - separating this logic prevents 'layout invalidation'
1673	 * thx @paul_irish
1674	 * @param {Array} queue
1675	 */
1676	proto._processLayoutQueue = function( queue ) {
1677		this.updateStagger();
1678		queue.forEach( function( obj, i ) {
1679			this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );
1680		}, this );
1681	};
1682
1683// set stagger from option in milliseconds number
1684	proto.updateStagger = function() {
1685		var stagger = this.options.stagger;
1686		if ( stagger === null || stagger === undefined ) {
1687			this.stagger = 0;
1688			return;
1689		}
1690		this.stagger = getMilliseconds( stagger );
1691		return this.stagger;
1692	};
1693
1694	/**
1695	 * Sets position of item in DOM
1696	 * @param {Outlayer.Item} item
1697	 * @param {Number} x - horizontal position
1698	 * @param {Number} y - vertical position
1699	 * @param {Boolean} isInstant - disables transitions
1700	 */
1701	proto._positionItem = function( item, x, y, isInstant, i ) {
1702		if ( isInstant ) {
1703			// if not transition, just set CSS
1704			item.goTo( x, y );
1705		} else {
1706			item.stagger( i * this.stagger );
1707			item.moveTo( x, y );
1708		}
1709	};
1710
1711	/**
1712	 * Any logic you want to do after each layout,
1713	 * i.e. size the container
1714	 */
1715	proto._postLayout = function() {
1716		this.resizeContainer();
1717	};
1718
1719	proto.resizeContainer = function() {
1720		var isResizingContainer = this._getOption('resizeContainer');
1721		if ( !isResizingContainer ) {
1722			return;
1723		}
1724		var size = this._getContainerSize();
1725		if ( size ) {
1726			this._setContainerMeasure( size.width, true );
1727			this._setContainerMeasure( size.height, false );
1728		}
1729	};
1730
1731	/**
1732	 * Sets width or height of container if returned
1733	 * @returns {Object} size
1734	 *   @param {Number} width
1735	 *   @param {Number} height
1736	 */
1737	proto._getContainerSize = noop;
1738
1739	/**
1740	 * @param {Number} measure - size of width or height
1741	 * @param {Boolean} isWidth
1742	 */
1743	proto._setContainerMeasure = function( measure, isWidth ) {
1744		if ( measure === undefined ) {
1745			return;
1746		}
1747
1748		var elemSize = this.size;
1749		// add padding and border width if border box
1750		if ( elemSize.isBorderBox ) {
1751			measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
1752				elemSize.borderLeftWidth + elemSize.borderRightWidth :
1753				elemSize.paddingBottom + elemSize.paddingTop +
1754				elemSize.borderTopWidth + elemSize.borderBottomWidth;
1755		}
1756
1757		measure = Math.max( measure, 0 );
1758		this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
1759	};
1760
1761	/**
1762	 * emit eventComplete on a collection of items events
1763	 * @param {String} eventName
1764	 * @param {Array} items - Outlayer.Items
1765	 */
1766	proto._emitCompleteOnItems = function( eventName, items ) {
1767		var _this = this;
1768		function onComplete() {
1769			_this.dispatchEvent( eventName + 'Complete', null, [ items ] );
1770		}
1771
1772		var count = items.length;
1773		if ( !items || !count ) {
1774			onComplete();
1775			return;
1776		}
1777
1778		var doneCount = 0;
1779		function tick() {
1780			doneCount++;
1781			if ( doneCount == count ) {
1782				onComplete();
1783			}
1784		}
1785
1786		// bind callback
1787		items.forEach( function( item ) {
1788			item.once( eventName, tick );
1789		});
1790	};
1791
1792	/**
1793	 * emits events via EvEmitter and jQuery events
1794	 * @param {String} type - name of event
1795	 * @param {Event} event - original event
1796	 * @param {Array} args - extra arguments
1797	 */
1798	proto.dispatchEvent = function( type, event, args ) {
1799		// add original event to arguments
1800		var emitArgs = event ? [ event ].concat( args ) : args;
1801		this.emitEvent( type, emitArgs );
1802
1803		if ( jQuery ) {
1804			// set this.$element
1805			this.$element = this.$element || jQuery( this.element );
1806			if ( event ) {
1807				// create jQuery event
1808				var $event = jQuery.Event( event );
1809				$event.type = type;
1810				this.$element.trigger( $event, args );
1811			} else {
1812				// just trigger with type if no event available
1813				this.$element.trigger( type, args );
1814			}
1815		}
1816	};
1817
1818// -------------------------- ignore & stamps -------------------------- //
1819
1820
1821	/**
1822	 * keep item in collection, but do not lay it out
1823	 * ignored items do not get skipped in layout
1824	 * @param {Element} elem
1825	 */
1826	proto.ignore = function( elem ) {
1827		var item = this.getItem( elem );
1828		if ( item ) {
1829			item.isIgnored = true;
1830		}
1831	};
1832
1833	/**
1834	 * return item to layout collection
1835	 * @param {Element} elem
1836	 */
1837	proto.unignore = function( elem ) {
1838		var item = this.getItem( elem );
1839		if ( item ) {
1840			delete item.isIgnored;
1841		}
1842	};
1843
1844	/**
1845	 * adds elements to stamps
1846	 * @param {NodeList, Array, Element, or String} elems
1847	 */
1848	proto.stamp = function( elems ) {
1849		elems = this._find( elems );
1850		if ( !elems ) {
1851			return;
1852		}
1853
1854		this.stamps = this.stamps.concat( elems );
1855		// ignore
1856		elems.forEach( this.ignore, this );
1857	};
1858
1859	/**
1860	 * removes elements to stamps
1861	 * @param {NodeList, Array, or Element} elems
1862	 */
1863	proto.unstamp = function( elems ) {
1864		elems = this._find( elems );
1865		if ( !elems ){
1866			return;
1867		}
1868
1869		elems.forEach( function( elem ) {
1870			// filter out removed stamp elements
1871			utils.removeFrom( this.stamps, elem );
1872			this.unignore( elem );
1873		}, this );
1874	};
1875
1876	/**
1877	 * finds child elements
1878	 * @param {NodeList, Array, Element, or String} elems
1879	 * @returns {Array} elems
1880	 */
1881	proto._find = function( elems ) {
1882		if ( !elems ) {
1883			return;
1884		}
1885		// if string, use argument as selector string
1886		if ( typeof elems == 'string' ) {
1887			elems = this.element.querySelectorAll( elems );
1888		}
1889		elems = utils.makeArray( elems );
1890		return elems;
1891	};
1892
1893	proto._manageStamps = function() {
1894		if ( !this.stamps || !this.stamps.length ) {
1895			return;
1896		}
1897
1898		this._getBoundingRect();
1899
1900		this.stamps.forEach( this._manageStamp, this );
1901	};
1902
1903// update boundingLeft / Top
1904	proto._getBoundingRect = function() {
1905		// get bounding rect for container element
1906		var boundingRect = this.element.getBoundingClientRect();
1907		var size = this.size;
1908		this._boundingRect = {
1909			left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
1910			top: boundingRect.top + size.paddingTop + size.borderTopWidth,
1911			right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
1912			bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
1913		};
1914	};
1915
1916	/**
1917	 * @param {Element} stamp
1918	 **/
1919	proto._manageStamp = noop;
1920
1921	/**
1922	 * get x/y position of element relative to container element
1923	 * @param {Element} elem
1924	 * @returns {Object} offset - has left, top, right, bottom
1925	 */
1926	proto._getElementOffset = function( elem ) {
1927		var boundingRect = elem.getBoundingClientRect();
1928		var thisRect = this._boundingRect;
1929		var size = getSize( elem );
1930		var offset = {
1931			left: boundingRect.left - thisRect.left - size.marginLeft,
1932			top: boundingRect.top - thisRect.top - size.marginTop,
1933			right: thisRect.right - boundingRect.right - size.marginRight,
1934			bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
1935		};
1936		return offset;
1937	};
1938
1939// -------------------------- resize -------------------------- //
1940
1941// enable event handlers for listeners
1942// i.e. resize -> onresize
1943	proto.handleEvent = utils.handleEvent;
1944
1945	/**
1946	 * Bind layout to window resizing
1947	 */
1948	proto.bindResize = function() {
1949		window.addEventListener( 'resize', this );
1950		this.isResizeBound = true;
1951	};
1952
1953	/**
1954	 * Unbind layout to window resizing
1955	 */
1956	proto.unbindResize = function() {
1957		window.removeEventListener( 'resize', this );
1958		this.isResizeBound = false;
1959	};
1960
1961	proto.onresize = function() {
1962		this.resize();
1963	};
1964
1965	utils.debounceMethod( Outlayer, 'onresize', 100 );
1966
1967	proto.resize = function() {
1968		// don't trigger if size did not change
1969		// or if resize was unbound. See #9
1970		if ( !this.isResizeBound || !this.needsResizeLayout() ) {
1971			return;
1972		}
1973
1974		this.layout();
1975	};
1976
1977	/**
1978	 * check if layout is needed post layout
1979	 * @returns Boolean
1980	 */
1981	proto.needsResizeLayout = function() {
1982		var size = getSize( this.element );
1983		// check that this.size and size are there
1984		// IE8 triggers resize on body size change, so they might not be
1985		var hasSizes = this.size && size;
1986		return hasSizes && size.innerWidth !== this.size.innerWidth;
1987	};
1988
1989// -------------------------- methods -------------------------- //
1990
1991	/**
1992	 * add items to Outlayer instance
1993	 * @param {Array or NodeList or Element} elems
1994	 * @returns {Array} items - Outlayer.Items
1995	 **/
1996	proto.addItems = function( elems ) {
1997		var items = this._itemize( elems );
1998		// add items to collection
1999		if ( items.length ) {
2000			this.items = this.items.concat( items );
2001		}
2002		return items;
2003	};
2004
2005	/**
2006	 * Layout newly-appended item elements
2007	 * @param {Array or NodeList or Element} elems
2008	 */
2009	proto.appended = function( elems ) {
2010		var items = this.addItems( elems );
2011		if ( !items.length ) {
2012			return;
2013		}
2014		// layout and reveal just the new items
2015		this.layoutItems( items, true );
2016		this.reveal( items );
2017	};
2018
2019	/**
2020	 * Layout prepended elements
2021	 * @param {Array or NodeList or Element} elems
2022	 */
2023	proto.prepended = function( elems ) {
2024		var items = this._itemize( elems );
2025		if ( !items.length ) {
2026			return;
2027		}
2028		// add items to beginning of collection
2029		var previousItems = this.items.slice(0);
2030		this.items = items.concat( previousItems );
2031		// start new layout
2032		this._resetLayout();
2033		this._manageStamps();
2034		// layout new stuff without transition
2035		this.layoutItems( items, true );
2036		this.reveal( items );
2037		// layout previous items
2038		this.layoutItems( previousItems );
2039	};
2040
2041	/**
2042	 * reveal a collection of items
2043	 * @param {Array of Outlayer.Items} items
2044	 */
2045	proto.reveal = function( items ) {
2046		this._emitCompleteOnItems( 'reveal', items );
2047		if ( !items || !items.length ) {
2048			return;
2049		}
2050		var stagger = this.updateStagger();
2051		items.forEach( function( item, i ) {
2052			item.stagger( i * stagger );
2053			item.reveal();
2054		});
2055	};
2056
2057	/**
2058	 * hide a collection of items
2059	 * @param {Array of Outlayer.Items} items
2060	 */
2061	proto.hide = function( items ) {
2062		this._emitCompleteOnItems( 'hide', items );
2063		if ( !items || !items.length ) {
2064			return;
2065		}
2066		var stagger = this.updateStagger();
2067		items.forEach( function( item, i ) {
2068			item.stagger( i * stagger );
2069			item.hide();
2070		});
2071	};
2072
2073	/**
2074	 * reveal item elements
2075	 * @param {Array}, {Element}, {NodeList} items
2076	 */
2077	proto.revealItemElements = function( elems ) {
2078		var items = this.getItems( elems );
2079		this.reveal( items );
2080	};
2081
2082	/**
2083	 * hide item elements
2084	 * @param {Array}, {Element}, {NodeList} items
2085	 */
2086	proto.hideItemElements = function( elems ) {
2087		var items = this.getItems( elems );
2088		this.hide( items );
2089	};
2090
2091	/**
2092	 * get Outlayer.Item, given an Element
2093	 * @param {Element} elem
2094	 * @param {Function} callback
2095	 * @returns {Outlayer.Item} item
2096	 */
2097	proto.getItem = function( elem ) {
2098		// loop through items to get the one that matches
2099		for ( var i=0; i < this.items.length; i++ ) {
2100			var item = this.items[i];
2101			if ( item.element == elem ) {
2102				// return item
2103				return item;
2104			}
2105		}
2106	};
2107
2108	/**
2109	 * get collection of Outlayer.Items, given Elements
2110	 * @param {Array} elems
2111	 * @returns {Array} items - Outlayer.Items
2112	 */
2113	proto.getItems = function( elems ) {
2114		elems = utils.makeArray( elems );
2115		var items = [];
2116		elems.forEach( function( elem ) {
2117			var item = this.getItem( elem );
2118			if ( item ) {
2119				items.push( item );
2120			}
2121		}, this );
2122
2123		return items;
2124	};
2125
2126	/**
2127	 * remove element(s) from instance and DOM
2128	 * @param {Array or NodeList or Element} elems
2129	 */
2130	proto.remove = function( elems ) {
2131		var removeItems = this.getItems( elems );
2132
2133		this._emitCompleteOnItems( 'remove', removeItems );
2134
2135		// bail if no items to remove
2136		if ( !removeItems || !removeItems.length ) {
2137			return;
2138		}
2139
vendor: 9,743 bytes, lines 2140-2543
2140		removeItems.forEach( function( item ) {
2141			item.remove();
2142			// remove item from collection
2143			utils.removeFrom( this.items, item );
2144		}, this );
2145	};
2146
2147// ----- destroy ----- //
2148
2149// remove and disable Outlayer instance
2150	proto.destroy = function() {
2151		// clean up dynamic styles
2152		var style = this.element.style;
2153		style.height = '';
2154		style.position = '';
2155		style.width = '';
2156		// destroy items
2157		this.items.forEach( function( item ) {
2158			item.destroy();
2159		});
2160
2161		this.unbindResize();
2162
2163		var id = this.element.outlayerGUID;
2164		delete instances[ id ]; // remove reference to instance by id
2165		delete this.element.outlayerGUID;
2166		// remove data for jQuery
2167		if ( jQuery ) {
2168			jQuery.removeData( this.element, this.constructor.namespace );
2169		}
2170
2171	};
2172
2173// -------------------------- data -------------------------- //
2174
2175	/**
2176	 * get Outlayer instance from element
2177	 * @param {Element} elem
2178	 * @returns {Outlayer}
2179	 */
2180	Outlayer.data = function( elem ) {
2181		elem = utils.getQueryElement( elem );
2182		var id = elem && elem.outlayerGUID;
2183		return id && instances[ id ];
2184	};
2185
2186
2187// -------------------------- create Outlayer class -------------------------- //
2188
2189	/**
2190	 * create a layout class
2191	 * @param {String} namespace
2192	 */
2193	Outlayer.create = function( namespace, options ) {
2194		// sub-class Outlayer
2195		var Layout = subclass( Outlayer );
2196		// apply new options and compatOptions
2197		Layout.defaults = utils.extend( {}, Outlayer.defaults );
2198		utils.extend( Layout.defaults, options );
2199		Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );
2200
2201		Layout.namespace = namespace;
2202
2203		Layout.data = Outlayer.data;
2204
2205		// sub-class Item
2206		Layout.Item = subclass( Item );
2207
2208		// -------------------------- declarative -------------------------- //
2209
2210		utils.htmlInit( Layout, namespace );
2211
2212		// -------------------------- jQuery bridge -------------------------- //
2213
2214		// make into jQuery plugin
2215		if ( jQuery && jQuery.bridget ) {
2216			jQuery.bridget( namespace, Layout );
2217		}
2218
2219		return Layout;
2220	};
2221
2222	function subclass( Parent ) {
2223		function SubClass() {
2224			Parent.apply( this, arguments );
2225		}
2226
2227		SubClass.prototype = Object.create( Parent.prototype );
2228		SubClass.prototype.constructor = SubClass;
2229
2230		return SubClass;
2231	}
2232
2233// ----- helpers ----- //
2234
2235// how many milliseconds are in each unit
2236	var msUnits = {
2237		ms: 1,
2238		s: 1000
2239	};
2240
2241// munge time-like parameter into millisecond number
2242// '0.4s' -> 40
2243	function getMilliseconds( time ) {
2244		if ( typeof time == 'number' ) {
2245			return time;
2246		}
2247		var matches = time.match( /(^\d*\.?\d*)(\w*)/ );
2248		var num = matches && matches[1];
2249		var unit = matches && matches[2];
2250		if ( !num.length ) {
2251			return 0;
2252		}
2253		num = parseFloat( num );
2254		var mult = msUnits[ unit ] || 1;
2255		return num * mult;
2256	}
2257
2258// ----- fin ----- //
2259
2260// back in global
2261	Outlayer.Item = Item;
2262
2263	return Outlayer;
2264
2265}));
2266
2267/**
2268 * Isotope Item
2269 **/
2270
2271( function( window, factory ) {
2272	// universal module definition
2273	/* jshint strict: false */ /*globals define, module, require */
2274	if ( typeof define == 'function' && define.amd ) {
2275		// AMD
2276		define( 'isotope-layout/js/item',[
2277				'outlayer/outlayer'
2278			],
2279			factory );
2280	} else if ( typeof module == 'object' && module.exports ) {
2281		// CommonJS
2282		module.exports = factory(
2283			require('outlayer')
2284		);
2285	} else {
2286		// browser global
2287		window.Isotope = window.Isotope || {};
2288		window.Isotope.Item = factory(
2289			window.Outlayer
2290		);
2291	}
2292
2293}( window, function factory( Outlayer ) {
2294	'use strict';
2295
2296// -------------------------- Item -------------------------- //
2297
2298// sub-class Outlayer Item
2299	function Item() {
2300		Outlayer.Item.apply( this, arguments );
2301	}
2302
2303	var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
2304
2305	var _create = proto._create;
2306	proto._create = function() {
2307		// assign id, used for original-order sorting
2308		this.id = this.layout.itemGUID++;
2309		_create.call( this );
2310		this.sortData = {};
2311	};
2312
2313	proto.updateSortData = function() {
2314		if ( this.isIgnored ) {
2315			return;
2316		}
2317		// default sorters
2318		this.sortData.id = this.id;
2319		// for backward compatibility
2320		this.sortData['original-order'] = this.id;
2321		this.sortData.random = Math.random();
2322		// go thru getSortData obj and apply the sorters
2323		var getSortData = this.layout.options.getSortData;
2324		var sorters = this.layout._sorters;
2325		for ( var key in getSortData ) {
2326			var sorter = sorters[ key ];
2327			this.sortData[ key ] = sorter( this.element, this );
2328		}
2329	};
2330
2331	var _destroy = proto.destroy;
2332	proto.destroy = function() {
2333		// call super
2334		_destroy.apply( this, arguments );
2335		// reset display, #741
2336		this.css({
2337			display: ''
2338		});
2339	};
2340
2341	return Item;
2342
2343}));
2344
2345/**
2346 * Isotope LayoutMode
2347 */
2348
2349( function( window, factory ) {
2350	// universal module definition
2351	/* jshint strict: false */ /*globals define, module, require */
2352	if ( typeof define == 'function' && define.amd ) {
2353		// AMD
2354		define( 'isotope-layout/js/layout-mode',[
2355				'get-size/get-size',
2356				'outlayer/outlayer'
2357			],
2358			factory );
2359	} else if ( typeof module == 'object' && module.exports ) {
2360		// CommonJS
2361		module.exports = factory(
2362			require('get-size'),
2363			require('outlayer')
2364		);
2365	} else {
2366		// browser global
2367		window.Isotope = window.Isotope || {};
2368		window.Isotope.LayoutMode = factory(
2369			window.getSize,
2370			window.Outlayer
2371		);
2372	}
2373
2374}( window, function factory( getSize, Outlayer ) {
2375	'use strict';
2376
2377	// layout mode class
2378	function LayoutMode( isotope ) {
2379		this.isotope = isotope;
2380		// link properties
2381		if ( isotope ) {
2382			this.options = isotope.options[ this.namespace ];
2383			this.element = isotope.element;
2384			this.items = isotope.filteredItems;
2385			this.size = isotope.size;
2386		}
2387	}
2388
2389	var proto = LayoutMode.prototype;
2390
2391	/**
2392	 * some methods should just defer to default Outlayer method
2393	 * and reference the Isotope instance as `this`
2394	 **/
2395	var facadeMethods = [
2396		'_resetLayout',
2397		'_getItemLayoutPosition',
2398		'_manageStamp',
2399		'_getContainerSize',
2400		'_getElementOffset',
2401		'needsResizeLayout',
2402		'_getOption'
2403	];
2404
2405	facadeMethods.forEach( function( methodName ) {
2406		proto[ methodName ] = function() {
2407			return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );
2408		};
2409	});
2410
2411	// -----  ----- //
2412
2413	// for horizontal layout modes, check vertical size
2414	proto.needsVerticalResizeLayout = function() {
2415		// don't trigger if size did not change
2416		var size = getSize( this.isotope.element );
2417		// check that this.size and size are there
2418		// IE8 triggers resize on body size change, so they might not be
2419		var hasSizes = this.isotope.size && size;
2420		return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
2421	};
2422
2423	// ----- measurements ----- //
2424
2425	proto._getMeasurement = function() {
2426		this.isotope._getMeasurement.apply( this, arguments );
2427	};
2428
2429	proto.getColumnWidth = function() {
2430		this.getSegmentSize( 'column', 'Width' );
2431	};
2432
2433	proto.getRowHeight = function() {
2434		this.getSegmentSize( 'row', 'Height' );
2435	};
2436
2437	/**
2438	 * get columnWidth or rowHeight
2439	 * segment: 'column' or 'row'
2440	 * size 'Width' or 'Height'
2441	 **/
2442	proto.getSegmentSize = function( segment, size ) {
2443		var segmentName = segment + size;
2444		var outerSize = 'outer' + size;
2445		// columnWidth / outerWidth // rowHeight / outerHeight
2446		this._getMeasurement( segmentName, outerSize );
2447		// got rowHeight or columnWidth, we can chill
2448		if ( this[ segmentName ] ) {
2449			return;
2450		}
2451		// fall back to item of first element
2452		var firstItemSize = this.getFirstItemSize();
2453		this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
2454			// or size of container
2455			this.isotope.size[ 'inner' + size ];
2456	};
2457
2458	proto.getFirstItemSize = function() {
2459		var firstItem = this.isotope.filteredItems[0];
2460		return firstItem && firstItem.element && getSize( firstItem.element );
2461	};
2462
2463	// ----- methods that should reference isotope ----- //
2464
2465	proto.layout = function() {
2466		this.isotope.layout.apply( this.isotope, arguments );
2467	};
2468
2469	proto.getSize = function() {
2470		this.isotope.getSize();
2471		this.size = this.isotope.size;
2472	};
2473
2474	// -------------------------- create -------------------------- //
2475
2476	LayoutMode.modes = {};
2477
2478	LayoutMode.create = function( namespace, options ) {
2479
2480		function Mode() {
2481			LayoutMode.apply( this, arguments );
2482		}
2483
2484		Mode.prototype = Object.create( proto );
2485		Mode.prototype.constructor = Mode;
2486
2487		// default options
2488		if ( options ) {
2489			Mode.options = options;
2490		}
2491
2492		Mode.prototype.namespace = namespace;
2493		// register in Isotope
2494		LayoutMode.modes[ namespace ] = Mode;
2495
2496		return Mode;
2497	};
2498
2499	return LayoutMode;
2500
2501}));
2502
2503/*!
2504 * Masonry v4.2.1
2505 * Cascading grid layout library
2506 * https://masonry.desandro.com
2507 * MIT License
2508 * by David DeSandro
2509 */
2510
2511( function( window, factory ) {
2512	// universal module definition
2513	/* jshint strict: false */ /*globals define, module, require */
2514	if ( typeof define == 'function' && define.amd ) {
2515		// AMD
2516		define( 'masonry-layout/masonry',[
2517				'outlayer/outlayer',
2518				'get-size/get-size'
2519			],
2520			factory );
2521	} else if ( typeof module == 'object' && module.exports ) {
2522		// CommonJS
2523		module.exports = factory(
2524			require('outlayer'),
2525			require('get-size')
2526		);
2527	} else {
2528		// browser global
2529		window.Masonry = factory(
2530			window.Outlayer,
2531			window.getSize
2532		);
2533	}
2534
2535}( window, function factory( Outlayer, getSize ) {
2536
2537
2538
2539// -------------------------- masonryDefinition -------------------------- //
2540
2541	// create an Outlayer layout class
2542	var Masonry = Outlayer.create('masonry');
2543	// isFitWidth -> fitWidth
vendor: 6,045 bytes, lines 2544-2728
2544	Masonry.compatOptions.fitWidth = 'isFitWidth';
2545
2546	var proto = Masonry.prototype;
2547
2548	proto._resetLayout = function() {
2549		this.getSize();
2550		this._getMeasurement( 'columnWidth', 'outerWidth' );
2551		this._getMeasurement( 'gutter', 'outerWidth' );
2552		this.measureColumns();
2553
2554		// reset column Y
2555		this.colYs = [];
2556		for ( var i=0; i < this.cols; i++ ) {
2557			this.colYs.push( 0 );
2558		}
2559
2560		this.maxY = 0;
2561		this.horizontalColIndex = 0;
2562	};
2563
2564	proto.measureColumns = function() {
2565		this.getContainerWidth();
2566		// if columnWidth is 0, default to outerWidth of first item
2567		if ( !this.columnWidth ) {
2568			var firstItem = this.items[0];
2569			var firstItemElem = firstItem && firstItem.element;
2570			// columnWidth fall back to item of first element
2571			this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
2572				// if first elem has no width, default to size of container
2573				this.containerWidth;
2574		}
2575
2576		var columnWidth = this.columnWidth += this.gutter;
2577
2578		// calculate columns
2579		var containerWidth = this.containerWidth + this.gutter;
2580		var cols = containerWidth / columnWidth;
2581		// fix rounding errors, typically with gutters
2582		var excess = columnWidth - containerWidth % columnWidth;
2583		// if overshoot is less than a pixel, round up, otherwise floor it
2584		var mathMethod = excess && excess < 1 ? 'round' : 'floor';
2585		cols = Math[ mathMethod ]( cols );
2586		this.cols = Math.max( cols, 1 );
2587	};
2588
2589	proto.getContainerWidth = function() {
2590		// container is parent if fit width
2591		var isFitWidth = this._getOption('fitWidth');
2592		var container = isFitWidth ? this.element.parentNode : this.element;
2593		// check that this.size and size are there
2594		// IE8 triggers resize on body size change, so they might not be
2595		var size = getSize( container );
2596		this.containerWidth = size && size.innerWidth;
2597	};
2598
2599	proto._getItemLayoutPosition = function( item ) {
2600		item.getSize();
2601		// how many columns does this brick span
2602		var remainder = item.size.outerWidth % this.columnWidth;
2603		var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
2604		// round if off by 1 pixel, otherwise use ceil
2605		var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
2606		colSpan = Math.min( colSpan, this.cols );
2607		// use horizontal or top column position
2608		var colPosMethod = this.options.horizontalOrder ?
2609			'_getHorizontalColPosition' : '_getTopColPosition';
2610		var colPosition = this[ colPosMethod ]( colSpan, item );
2611		// position the brick
2612		var position = {
2613			x: this.columnWidth * colPosition.col,
2614			y: colPosition.y
2615		};
2616		// apply setHeight to necessary columns
2617		var setHeight = colPosition.y + item.size.outerHeight;
2618		var setMax = colSpan + colPosition.col;
2619		for ( var i = colPosition.col; i < setMax; i++ ) {
2620			this.colYs[i] = setHeight;
2621		}
2622
2623		return position;
2624	};
2625
2626	proto._getTopColPosition = function( colSpan ) {
2627		var colGroup = this._getTopColGroup( colSpan );
2628		// get the minimum Y value from the columns
2629		var minimumY = Math.min.apply( Math, colGroup );
2630
2631		return {
2632			col: colGroup.indexOf( minimumY ),
2633			y: minimumY,
2634		};
2635	};
2636
2637	/**
2638	 * @param {Number} colSpan - number of columns the element spans
2639	 * @returns {Array} colGroup
2640	 */
2641	proto._getTopColGroup = function( colSpan ) {
2642		if ( colSpan < 2 ) {
2643			// if brick spans only one column, use all the column Ys
2644			return this.colYs;
2645		}
2646
2647		var colGroup = [];
2648		// how many different places could this brick fit horizontally
2649		var groupCount = this.cols + 1 - colSpan;
2650		// for each group potential horizontal position
2651		for ( var i = 0; i < groupCount; i++ ) {
2652			colGroup[i] = this._getColGroupY( i, colSpan );
2653		}
2654		return colGroup;
2655	};
2656
2657	proto._getColGroupY = function( col, colSpan ) {
2658		if ( colSpan < 2 ) {
2659			return this.colYs[ col ];
2660		}
2661		// make an array of colY values for that one group
2662		var groupColYs = this.colYs.slice( col, col + colSpan );
2663		// and get the max value of the array
2664		return Math.max.apply( Math, groupColYs );
2665	};
2666
2667	// get column position based on horizontal index. #873
2668	proto._getHorizontalColPosition = function( colSpan, item ) {
2669		var col = this.horizontalColIndex % this.cols;
2670		var isOver = colSpan > 1 && col + colSpan > this.cols;
2671		// shift to next row if item can't fit on current row
2672		col = isOver ? 0 : col;
2673		// don't let zero-size items take up space
2674		var hasSize = item.size.outerWidth && item.size.outerHeight;
2675		this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;
2676
2677		return {
2678			col: col,
2679			y: this._getColGroupY( col, colSpan ),
2680		};
2681	};
2682
2683	proto._manageStamp = function( stamp ) {
2684		var stampSize = getSize( stamp );
2685		var offset = this._getElementOffset( stamp );
2686		// get the columns that this stamp affects
2687		var isOriginLeft = this._getOption('originLeft');
2688		var firstX = isOriginLeft ? offset.left : offset.right;
2689		var lastX = firstX + stampSize.outerWidth;
2690		var firstCol = Math.floor( firstX / this.columnWidth );
2691		firstCol = Math.max( 0, firstCol );
2692		var lastCol = Math.floor( lastX / this.columnWidth );
2693		// lastCol should not go over if multiple of columnWidth #425
2694		lastCol -= lastX % this.columnWidth ? 0 : 1;
2695		lastCol = Math.min( this.cols - 1, lastCol );
2696		// set colYs to bottom of the stamp
2697
2698		var isOriginTop = this._getOption('originTop');
2699		var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
2700			stampSize.outerHeight;
2701		for ( var i = firstCol; i <= lastCol; i++ ) {
2702			this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
2703		}
2704	};
2705
2706	proto._getContainerSize = function() {
2707		this.maxY = Math.max.apply( Math, this.colYs );
2708		var size = {
2709			height: this.maxY
2710		};
2711
2712		if ( this._getOption('fitWidth') ) {
2713			size.width = this._getContainerFitWidth();
2714		}
2715
2716		return size;
2717	};
2718
2719	proto._getContainerFitWidth = function() {
2720		var unusedCols = 0;
2721		// count unused columns
2722		var i = this.cols;
2723		while ( --i ) {
2724			if ( this.colYs[i] !== 0 ) {
2725				break;
2726			}
2727			unusedCols++;
2728		}
vendor: 9,555 bytes, lines 2729-3114
2729		// fit container to columns that have been used
2730		return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
2731	};
2732
2733	proto.needsResizeLayout = function() {
2734		var previousWidth = this.containerWidth;
2735		this.getContainerWidth();
2736		return previousWidth != this.containerWidth;
2737	};
2738
2739	return Masonry;
2740
2741}));
2742
2743/*!
2744 * Masonry layout mode
2745 * sub-classes Masonry
2746 * https://masonry.desandro.com
2747 */
2748
2749( function( window, factory ) {
2750	// universal module definition
2751	/* jshint strict: false */ /*globals define, module, require */
2752	if ( typeof define == 'function' && define.amd ) {
2753		// AMD
2754		define( 'isotope-layout/js/layout-modes/masonry',[
2755				'../layout-mode',
2756				'masonry-layout/masonry'
2757			],
2758			factory );
2759	} else if ( typeof module == 'object' && module.exports ) {
2760		// CommonJS
2761		module.exports = factory(
2762			require('../layout-mode'),
2763			require('masonry-layout')
2764		);
2765	} else {
2766		// browser global
2767		factory(
2768			window.Isotope.LayoutMode,
2769			window.Masonry
2770		);
2771	}
2772
2773}( window, function factory( LayoutMode, Masonry ) {
2774	'use strict';
2775
2776// -------------------------- masonryDefinition -------------------------- //
2777
2778	// create an Outlayer layout class
2779	var MasonryMode = LayoutMode.create('masonry');
2780
2781	var proto = MasonryMode.prototype;
2782
2783	var keepModeMethods = {
2784		_getElementOffset: true,
2785		layout: true,
2786		_getMeasurement: true
2787	};
2788
2789	// inherit Masonry prototype
2790	for ( var method in Masonry.prototype ) {
2791		// do not inherit mode methods
2792		if ( !keepModeMethods[ method ] ) {
2793			proto[ method ] = Masonry.prototype[ method ];
2794		}
2795	}
2796
2797	var measureColumns = proto.measureColumns;
2798	proto.measureColumns = function() {
2799		// set items, used if measuring first item
2800		this.items = this.isotope.filteredItems;
2801		measureColumns.call( this );
2802	};
2803
2804	// point to mode options for fitWidth
2805	var _getOption = proto._getOption;
2806	proto._getOption = function( option ) {
2807		if ( option == 'fitWidth' ) {
2808			return this.options.isFitWidth !== undefined ?
2809				this.options.isFitWidth : this.options.fitWidth;
2810		}
2811		return _getOption.apply( this.isotope, arguments );
2812	};
2813
2814	return MasonryMode;
2815
2816}));
2817
2818/**
2819 * fitRows layout mode
2820 */
2821
2822( function( window, factory ) {
2823	// universal module definition
2824	/* jshint strict: false */ /*globals define, module, require */
2825	if ( typeof define == 'function' && define.amd ) {
2826		// AMD
2827		define( 'isotope-layout/js/layout-modes/fit-rows',[
2828				'../layout-mode'
2829			],
2830			factory );
2831	} else if ( typeof exports == 'object' ) {
2832		// CommonJS
2833		module.exports = factory(
2834			require('../layout-mode')
2835		);
2836	} else {
2837		// browser global
2838		factory(
2839			window.Isotope.LayoutMode
2840		);
2841	}
2842
2843}( window, function factory( LayoutMode ) {
2844	'use strict';
2845
2846	var FitRows = LayoutMode.create('fitRows');
2847
2848	var proto = FitRows.prototype;
2849
2850	proto._resetLayout = function() {
2851		this.x = 0;
2852		this.y = 0;
2853		this.maxY = 0;
2854		this._getMeasurement( 'gutter', 'outerWidth' );
2855	};
2856
2857	proto._getItemLayoutPosition = function( item ) {
2858		item.getSize();
2859
2860		var itemWidth = item.size.outerWidth + this.gutter;
2861		// if this element cannot fit in the current row
2862		var containerWidth = this.isotope.size.innerWidth + this.gutter;
2863		if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
2864			this.x = 0;
2865			this.y = this.maxY;
2866		}
2867
2868		var position = {
2869			x: this.x,
2870			y: this.y
2871		};
2872
2873		this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
2874		this.x += itemWidth;
2875
2876		return position;
2877	};
2878
2879	proto._getContainerSize = function() {
2880		return { height: this.maxY };
2881	};
2882
2883	return FitRows;
2884
2885}));
2886
2887/**
2888 * vertical layout mode
2889 */
2890
2891( function( window, factory ) {
2892	// universal module definition
2893	/* jshint strict: false */ /*globals define, module, require */
2894	if ( typeof define == 'function' && define.amd ) {
2895		// AMD
2896		define( 'isotope-layout/js/layout-modes/vertical',[
2897				'../layout-mode'
2898			],
2899			factory );
2900	} else if ( typeof module == 'object' && module.exports ) {
2901		// CommonJS
2902		module.exports = factory(
2903			require('../layout-mode')
2904		);
2905	} else {
2906		// browser global
2907		factory(
2908			window.Isotope.LayoutMode
2909		);
2910	}
2911
2912}( window, function factory( LayoutMode ) {
2913	'use strict';
2914
2915	var Vertical = LayoutMode.create( 'vertical', {
2916		horizontalAlignment: 0
2917	});
2918
2919	var proto = Vertical.prototype;
2920
2921	proto._resetLayout = function() {
2922		this.y = 0;
2923	};
2924
2925	proto._getItemLayoutPosition = function( item ) {
2926		item.getSize();
2927		var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *
2928			this.options.horizontalAlignment;
2929		var y = this.y;
2930		this.y += item.size.outerHeight;
2931		return { x: x, y: y };
2932	};
2933
2934	proto._getContainerSize = function() {
2935		return { height: this.y };
2936	};
2937
2938	return Vertical;
2939
2940}));
2941
2942/*!
2943 * Isotope v3.0.6
2944 *
2945 * Licensed GPLv3 for open source use
2946 * or Isotope Commercial License for commercial use
2947 *
2948 * https://isotope.metafizzy.co
2949 * Copyright 2010-2018 Metafizzy
2950 */
2951
2952( function( window, factory ) {
2953	// universal module definition
2954	/* jshint strict: false */ /*globals define, module, require */
2955	if ( typeof define == 'function' && define.amd ) {
2956		// AMD
2957		define( [
2958				'outlayer/outlayer',
2959				'get-size/get-size',
2960				'desandro-matches-selector/matches-selector',
2961				'fizzy-ui-utils/utils',
2962				'isotope-layout/js/item',
2963				'isotope-layout/js/layout-mode',
2964				// include default layout modes
2965				'isotope-layout/js/layout-modes/masonry',
2966				'isotope-layout/js/layout-modes/fit-rows',
2967				'isotope-layout/js/layout-modes/vertical'
2968			],
2969			function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
2970				return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
2971			});
2972	} else if ( typeof module == 'object' && module.exports ) {
2973		// CommonJS
2974		module.exports = factory(
2975			window,
2976			require('outlayer'),
2977			require('get-size'),
2978			require('desandro-matches-selector'),
2979			require('fizzy-ui-utils'),
2980			require('isotope-layout/js/item'),
2981			require('isotope-layout/js/layout-mode'),
2982			// include default layout modes
2983			require('isotope-layout/js/layout-modes/masonry'),
2984			require('isotope-layout/js/layout-modes/fit-rows'),
2985			require('isotope-layout/js/layout-modes/vertical')
2986		);
2987	} else {
2988		// browser global
2989		window.Isotope = factory(
2990			window,
2991			window.Outlayer,
2992			window.getSize,
2993			window.matchesSelector,
2994			window.fizzyUIUtils,
2995			window.Isotope.Item,
2996			window.Isotope.LayoutMode
2997		);
2998	}
2999
3000}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
3001							 Item, LayoutMode ) {
3002
3003
3004
3005// -------------------------- vars -------------------------- //
3006
3007	var jQuery = window.jQuery;
3008
3009// -------------------------- helpers -------------------------- //
3010
3011	var trim = String.prototype.trim ?
3012		function( str ) {
3013			return str.trim();
3014		} :
3015		function( str ) {
3016			return str.replace( /^\s+|\s+$/g, '' );
3017		};
3018
3019// -------------------------- isotopeDefinition -------------------------- //
3020
3021	// create an Outlayer layout class
3022	var Isotope = Outlayer.create( 'isotope', {
3023		layoutMode: 'masonry',
3024		isJQueryFiltering: true,
3025		sortAscending: true
3026	});
3027
3028	Isotope.Item = Item;
3029	Isotope.LayoutMode = LayoutMode;
3030
3031	var proto = Isotope.prototype;
3032
3033	proto._create = function() {
3034		this.itemGUID = 0;
3035		// functions that sort items
3036		this._sorters = {};
3037		this._getSorters();
3038		// call super
3039		Outlayer.prototype._create.call( this );
3040
3041		// create layout modes
3042		this.modes = {};
3043		// start filteredItems with all items
3044		this.filteredItems = this.items;
3045		// keep of track of sortBys
3046		this.sortHistory = [ 'original-order' ];
3047		// create from registered layout modes
3048		for ( var name in LayoutMode.modes ) {
3049			this._initLayoutMode( name );
3050		}
3051	};
3052
3053	proto.reloadItems = function() {
3054		// reset item ID counter
3055		this.itemGUID = 0;
3056		// call super
3057		Outlayer.prototype.reloadItems.call( this );
3058	};
3059
3060	proto._itemize = function() {
3061		var items = Outlayer.prototype._itemize.apply( this, arguments );
3062		// assign ID for original-order
3063		for ( var i=0; i < items.length; i++ ) {
3064			var item = items[i];
3065			item.id = this.itemGUID++;
3066		}
3067		this._updateItemsSortData( items );
3068		return items;
3069	};
3070
3071
3072	// -------------------------- layout -------------------------- //
3073
3074	proto._initLayoutMode = function( name ) {
3075		var Mode = LayoutMode.modes[ name ];
3076		// set mode options
3077		// HACK extend initial options, back-fill in default options
3078		var initialOpts = this.options[ name ] || {};
3079		this.options[ name ] = Mode.options ?
3080			utils.extend( Mode.options, initialOpts ) : initialOpts;
3081		// init layout mode instance
3082		this.modes[ name ] = new Mode( this );
3083	};
3084
3085
3086	proto.layout = function() {
3087		// if first time doing layout, do all magic
3088		if ( !this._isLayoutInited && this._getOption('initLayout') ) {
3089			this.arrange();
3090			return;
3091		}
3092		this._layout();
3093	};
3094
3095	// private method to be used in layout() & magic()
3096	proto._layout = function() {
3097		// don't animate first layout
3098		var isInstant = this._getIsInstant();
3099		// layout flow
3100		this._resetLayout();
3101		this._manageStamps();
3102		this.layoutItems( this.filteredItems, isInstant );
3103
3104		// flag for initalized
3105		this._isLayoutInited = true;
3106	};
3107
3108	// filter + sort + layout
3109	proto.arrange = function( opts ) {
3110		// set any options pass
3111		this.option( opts );
3112		this._getIsInstant();
3113		// filter, sort, and layout
3114
vendor: 12,489 bytes, lines 3115-3563
3115		// filter
3116		var filtered = this._filter( this.items );
3117		this.filteredItems = filtered.matches;
3118
3119		this._bindArrangeComplete();
3120
3121		if ( this._isInstant ) {
3122			this._noTransition( this._hideReveal, [ filtered ] );
3123		} else {
3124			this._hideReveal( filtered );
3125		}
3126
3127		this._sort();
3128		this._layout();
3129	};
3130	// alias to _init for main plugin method
3131	proto._init = proto.arrange;
3132
3133	proto._hideReveal = function( filtered ) {
3134		this.reveal( filtered.needReveal );
3135		this.hide( filtered.needHide );
3136	};
3137
3138	// HACK
3139	// Don't animate/transition first layout
3140	// Or don't animate/transition other layouts
3141	proto._getIsInstant = function() {
3142		var isLayoutInstant = this._getOption('layoutInstant');
3143		var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
3144			!this._isLayoutInited;
3145		this._isInstant = isInstant;
3146		return isInstant;
3147	};
3148
3149	// listen for layoutComplete, hideComplete and revealComplete
3150	// to trigger arrangeComplete
3151	proto._bindArrangeComplete = function() {
3152		// listen for 3 events to trigger arrangeComplete
3153		var isLayoutComplete, isHideComplete, isRevealComplete;
3154		var _this = this;
3155		function arrangeParallelCallback() {
3156			if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
3157				_this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
3158			}
3159		}
3160		this.once( 'layoutComplete', function() {
3161			isLayoutComplete = true;
3162			arrangeParallelCallback();
3163		});
3164		this.once( 'hideComplete', function() {
3165			isHideComplete = true;
3166			arrangeParallelCallback();
3167		});
3168		this.once( 'revealComplete', function() {
3169			isRevealComplete = true;
3170			arrangeParallelCallback();
3171		});
3172	};
3173
3174	// -------------------------- filter -------------------------- //
3175
3176	proto._filter = function( items ) {
3177		var filter = this.options.filter;
3178		filter = filter || '*';
3179		var matches = [];
3180		var hiddenMatched = [];
3181		var visibleUnmatched = [];
3182
3183		var test = this._getFilterTest( filter );
3184
3185		// test each item
3186		for ( var i=0; i < items.length; i++ ) {
3187			var item = items[i];
3188			if ( item.isIgnored ) {
3189				continue;
3190			}
3191			// add item to either matched or unmatched group
3192			var isMatched = test( item );
3193			// item.isFilterMatched = isMatched;
3194			// add to matches if its a match
3195			if ( isMatched ) {
3196				matches.push( item );
3197			}
3198			// add to additional group if item needs to be hidden or revealed
3199			if ( isMatched && item.isHidden ) {
3200				hiddenMatched.push( item );
3201			} else if ( !isMatched && !item.isHidden ) {
3202				visibleUnmatched.push( item );
3203			}
3204		}
3205
3206		// return collections of items to be manipulated
3207		return {
3208			matches: matches,
3209			needReveal: hiddenMatched,
3210			needHide: visibleUnmatched
3211		};
3212	};
3213
3214	// get a jQuery, function, or a matchesSelector test given the filter
3215	proto._getFilterTest = function( filter ) {
3216		if ( jQuery && this.options.isJQueryFiltering ) {
3217			// use jQuery
3218			return function( item ) {
3219				return jQuery( item.element ).is( filter );
3220			};
3221		}
3222		if ( typeof filter == 'function' ) {
3223			// use filter as function
3224			return function( item ) {
3225				return filter( item.element );
3226			};
3227		}
3228		// default, use filter as selector string
3229		return function( item ) {
3230			return matchesSelector( item.element, filter );
3231		};
3232	};
3233
3234	// -------------------------- sorting -------------------------- //
3235
3236	/**
3237	 * @params {Array} elems
3238	 * @public
3239	 */
3240	proto.updateSortData = function( elems ) {
3241		// get items
3242		var items;
3243		if ( elems ) {
3244			elems = utils.makeArray( elems );
3245			items = this.getItems( elems );
3246		} else {
3247			// update all items if no elems provided
3248			items = this.items;
3249		}
3250
3251		this._getSorters();
3252		this._updateItemsSortData( items );
3253	};
3254
3255	proto._getSorters = function() {
3256		var getSortData = this.options.getSortData;
3257		for ( var key in getSortData ) {
3258			var sorter = getSortData[ key ];
3259			this._sorters[ key ] = mungeSorter( sorter );
3260		}
3261	};
3262
3263	/**
3264	 * @params {Array} items - of Isotope.Items
3265	 * @private
3266	 */
3267	proto._updateItemsSortData = function( items ) {
3268		// do not update if no items
3269		var len = items && items.length;
3270
3271		for ( var i=0; len && i < len; i++ ) {
3272			var item = items[i];
3273			item.updateSortData();
3274		}
3275	};
3276
3277	// ----- munge sorter ----- //
3278
3279	// encapsulate this, as we just need mungeSorter
3280	// other functions in here are just for munging
3281	var mungeSorter = ( function() {
3282		// add a magic layer to sorters for convienent shorthands
3283		// `.foo-bar` will use the text of .foo-bar querySelector
3284		// `[foo-bar]` will use attribute
3285		// you can also add parser
3286		// `.foo-bar parseInt` will parse that as a number
3287		function mungeSorter( sorter ) {
3288			// if not a string, return function or whatever it is
3289			if ( typeof sorter != 'string' ) {
3290				return sorter;
3291			}
3292			// parse the sorter string
3293			var args = trim( sorter ).split(' ');
3294			var query = args[0];
3295			// check if query looks like [an-attribute]
3296			var attrMatch = query.match( /^\[(.+)\]$/ );
3297			var attr = attrMatch && attrMatch[1];
3298			var getValue = getValueGetter( attr, query );
3299			// use second argument as a parser
3300			var parser = Isotope.sortDataParsers[ args[1] ];
3301			// parse the value, if there was a parser
3302			sorter = parser ? function( elem ) {
3303					return elem && parser( getValue( elem ) );
3304				} :
3305				// otherwise just return value
3306				function( elem ) {
3307					return elem && getValue( elem );
3308				};
3309
3310			return sorter;
3311		}
3312
3313		// get an attribute getter, or get text of the querySelector
3314		function getValueGetter( attr, query ) {
3315			// if query looks like [foo-bar], get attribute
3316			if ( attr ) {
3317				return function getAttribute( elem ) {
3318					return elem.getAttribute( attr );
3319				};
3320			}
3321
3322			// otherwise, assume its a querySelector, and get its text
3323			return function getChildText( elem ) {
3324				var child = elem.querySelector( query );
3325				return child && child.textContent;
3326			};
3327		}
3328
3329		return mungeSorter;
3330	})();
3331
3332	// parsers used in getSortData shortcut strings
3333	Isotope.sortDataParsers = {
3334		'parseInt': function( val ) {
3335			return parseInt( val, 10 );
3336		},
3337		'parseFloat': function( val ) {
3338			return parseFloat( val );
3339		}
3340	};
3341
3342	// ----- sort method ----- //
3343
3344	// sort filteredItem order
3345	proto._sort = function() {
3346		if ( !this.options.sortBy ) {
3347			return;
3348		}
3349		// keep track of sortBy History
3350		var sortBys = utils.makeArray( this.options.sortBy );
3351		if ( !this._getIsSameSortBy( sortBys ) ) {
3352			// concat all sortBy and sortHistory, add to front, oldest goes in last
3353			this.sortHistory = sortBys.concat( this.sortHistory );
3354		}
3355		// sort magic
3356		var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );
3357		this.filteredItems.sort( itemSorter );
3358	};
3359
3360	// check if sortBys is same as start of sortHistory
3361	proto._getIsSameSortBy = function( sortBys ) {
3362		for ( var i=0; i < sortBys.length; i++ ) {
3363			if ( sortBys[i] != this.sortHistory[i] ) {
3364				return false;
3365			}
3366		}
3367		return true;
3368	};
3369
3370	// returns a function used for sorting
3371	function getItemSorter( sortBys, sortAsc ) {
3372		return function sorter( itemA, itemB ) {
3373			// cycle through all sortKeys
3374			for ( var i = 0; i < sortBys.length; i++ ) {
3375				var sortBy = sortBys[i];
3376				var a = itemA.sortData[ sortBy ];
3377				var b = itemB.sortData[ sortBy ];
3378				if ( a > b || a < b ) {
3379					// if sortAsc is an object, use the value given the sortBy key
3380					var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
3381					var direction = isAscending ? 1 : -1;
3382					return ( a > b ? 1 : -1 ) * direction;
3383				}
3384			}
3385			return 0;
3386		};
3387	}
3388
3389	// -------------------------- methods -------------------------- //
3390
3391	// get layout mode
3392	proto._mode = function() {
3393		var layoutMode = this.options.layoutMode;
3394		var mode = this.modes[ layoutMode ];
3395		if ( !mode ) {
3396			// TODO console.error
3397			throw new Error( 'No layout mode: ' + layoutMode );
3398		}
3399		// HACK sync mode's options
3400		// any options set after init for layout mode need to be synced
3401		mode.options = this.options[ layoutMode ];
3402		return mode;
3403	};
3404
3405	proto._resetLayout = function() {
3406		// trigger original reset layout
3407		Outlayer.prototype._resetLayout.call( this );
3408		this._mode()._resetLayout();
3409	};
3410
3411	proto._getItemLayoutPosition = function( item  ) {
3412		return this._mode()._getItemLayoutPosition( item );
3413	};
3414
3415	proto._manageStamp = function( stamp ) {
3416		this._mode()._manageStamp( stamp );
3417	};
3418
3419	proto._getContainerSize = function() {
3420		return this._mode()._getContainerSize();
3421	};
3422
3423	proto.needsResizeLayout = function() {
3424		return this._mode().needsResizeLayout();
3425	};
3426
3427	// -------------------------- adding & removing -------------------------- //
3428
3429	// HEADS UP overwrites default Outlayer appended
3430	proto.appended = function( elems ) {
3431		var items = this.addItems( elems );
3432		if ( !items.length ) {
3433			return;
3434		}
3435		// filter, layout, reveal new items
3436		var filteredItems = this._filterRevealAdded( items );
3437		// add to filteredItems
3438		this.filteredItems = this.filteredItems.concat( filteredItems );
3439	};
3440
3441	// HEADS UP overwrites default Outlayer prepended
3442	proto.prepended = function( elems ) {
3443		var items = this._itemize( elems );
3444		if ( !items.length ) {
3445			return;
3446		}
3447		// start new layout
3448		this._resetLayout();
3449		this._manageStamps();
3450		// filter, layout, reveal new items
3451		var filteredItems = this._filterRevealAdded( items );
3452		// layout previous items
3453		this.layoutItems( this.filteredItems );
3454		// add to items and filteredItems
3455		this.filteredItems = filteredItems.concat( this.filteredItems );
3456		this.items = items.concat( this.items );
3457	};
3458
3459	proto._filterRevealAdded = function( items ) {
3460		var filtered = this._filter( items );
3461		this.hide( filtered.needHide );
3462		// reveal all new items
3463		this.reveal( filtered.matches );
3464		// layout new items, no transition
3465		this.layoutItems( filtered.matches, true );
3466		return filtered.matches;
3467	};
3468
3469	/**
3470	 * Filter, sort, and layout newly-appended item elements
3471	 * @param {Array or NodeList or Element} elems
3472	 */
3473	proto.insert = function( elems ) {
3474		var items = this.addItems( elems );
3475		if ( !items.length ) {
3476			return;
3477		}
3478		// append item elements
3479		var i, item;
3480		var len = items.length;
3481		for ( i=0; i < len; i++ ) {
3482			item = items[i];
3483			this.element.appendChild( item.element );
3484		}
3485		// filter new stuff
3486		var filteredInsertItems = this._filter( items ).matches;
3487		// set flag
3488		for ( i=0; i < len; i++ ) {
3489			items[i].isLayoutInstant = true;
3490		}
3491		this.arrange();
3492		// reset flag
3493		for ( i=0; i < len; i++ ) {
3494			delete items[i].isLayoutInstant;
3495		}
3496		this.reveal( filteredInsertItems );
3497	};
3498
3499	var _remove = proto.remove;
3500	proto.remove = function( elems ) {
3501		elems = utils.makeArray( elems );
3502		var removeItems = this.getItems( elems );
3503		// do regular thing
3504		_remove.call( this, elems );
3505		// bail if no items to remove
3506		var len = removeItems && removeItems.length;
3507		// remove elems from filteredItems
3508		for ( var i=0; len && i < len; i++ ) {
3509			var item = removeItems[i];
3510			// remove item from collection
3511			utils.removeFrom( this.filteredItems, item );
3512		}
3513	};
3514
3515	proto.shuffle = function() {
3516		// update random sortData
3517		for ( var i=0; i < this.items.length; i++ ) {
3518			var item = this.items[i];
3519			item.sortData.random = Math.random();
3520		}
3521		this.options.sortBy = 'random';
3522		this._sort();
3523		this._layout();
3524	};
3525
3526	/**
3527	 * trigger fn without transition
3528	 * kind of hacky to have this in the first place
3529	 * @param {Function} fn
3530	 * @param {Array} args
3531	 * @returns ret
3532	 * @private
3533	 */
3534	proto._noTransition = function( fn, args ) {
3535		// save transitionDuration before disabling
3536		var transitionDuration = this.options.transitionDuration;
3537		// disable transition
3538		this.options.transitionDuration = 0;
3539		// do it
3540		var returnValue = fn.apply( this, args );
3541		// re-enable transition for reveal
3542		this.options.transitionDuration = transitionDuration;
3543		return returnValue;
3544	};
3545
3546	// ----- helper methods ----- //
3547
3548	/**
3549	 * getter method for getting filtered item elements
3550	 * @returns {Array} elems - collection of item elements
3551	 */
3552	proto.getFilteredItemElements = function() {
3553		return this.filteredItems.map( function( item ) {
3554			return item.element;
3555		});
3556	};
3557
3558	// -----  ----- //
3559
3560	return Isotope;
3561
3562}));
3563

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.