PageSourceSearch

https://www.siepweb.it/siep/wp/wp-content/themes/avril-personal/assets/js/isotope.pkgd.js?ver=1

js siepweb.it collected 2026-09-24 10:14:06 UTC 122,168 bytes, 4,219 lines download raw bytes

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

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.