PageSourceSearch

https://www.hongleong.com.sg/wp-content/themes/HongLeongGroup/js/plugins/isotope.pkgd.js?ver=7.0.6

js hongleong.com.sg collected 2026-09-25 06:28:54 UTC 113,107 bytes, 4,049 lines download raw bytes

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

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.