PageSourceSearch

https://moderator.be/wp-content/themes/peak/js/libs/isotope.js?ver=1.5.19

js moderator.be collected 2026-10-05 19:25:59 UTC 137,276 bytes, 4,221 lines download raw bytes

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

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.