PageSourceSearch

https://wearebombo.com/wp-content/plugins/happy-elementor-addons/assets/vendor/jquery.isotope.js?ver=3.12.2

js wearebombo.com collected 2026-09-24 10:47:02 UTC 127,091 bytes, 4,016 lines download raw bytes

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

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.