PageSourceSearch

https://rocky.edu/wp-content/themes/unicamp/assets/libs/isotope/js/isotope.pkgd.js?ver=3.0.0

js rocky.edu collected 2026-09-24 19:43:37 UTC 89,803 bytes, 3,574 lines download raw bytes

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

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.