PageSourceSearch

https://www.augustcap.com/wp-content/themes/august-capital/js/isotope.js?ver=1790308743

js augustcap.com collected 2026-09-25 04:05:27 UTC 114,053 bytes, 4,211 lines download raw bytes

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

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.