PageSourceSearch

http://katalog.stroykombinat.kz/design/stroy/js/masonry.js

js stroykombinat.kz collected 2026-10-07 19:43:08 UTC 97,621 bytes, 2,887 lines download raw bytes

1/*!
2 * Masonry PACKAGED v3.1.5
3 * Cascading grid layout library
4 * http://masonry.desandro.com
5 * MIT License
6 * by David DeSandro
7 */
8
9/**
10 * Bridget makes jQuery widgets
11 * v1.0.1
12 */
13
14(function(window) {
15
16
17
18    // -------------------------- utils -------------------------- //
19
20    var slice = Array.prototype.slice;
21
22    function noop() {}
23
24    // -------------------------- definition -------------------------- //
25
26    function defineBridget($) {
27
28        // bail if no jQuery
29        if (!$) {
30            return;
31        }
32
33        // -------------------------- addOptionMethod -------------------------- //
34
35        /**
36         * adds option method -> $().plugin('option', {...})
37         * @param {Function} PluginClass - constructor class
38         */
39        function addOptionMethod(PluginClass) {
40            // don't overwrite original option method
41            if (PluginClass.prototype.option) {
42                return;
43            }
44
45            // option setter
46            PluginClass.prototype.option = function(opts) {
47                // bail out if not an object
48                if (!$.isPlainObject(opts)) {
49                    return;
50                }
51                this.options = $.extend(true, this.options, opts);
52            };
53        }
54
55
56        // -------------------------- plugin bridge -------------------------- //
57
58        // helper function for logging errors
59        // $.error breaks jQuery chaining
60        var logError = typeof console === 'undefined' ? noop :
61                function(message) {
62                    console.error(message);
63            };
64
65        /**
66         * jQuery plugin bridge, access methods like $elem.plugin('method')
67         * @param {String} namespace - plugin name
68         * @param {Function} PluginClass - constructor class
69         */
70        function bridge(namespace, PluginClass) {
71            // add to jQuery fn namespace
72            $.fn[namespace] = function(options) {
73                if (typeof options === 'string') {
74                    // call plugin method when first argument is a string
75                    // get arguments for method
76                    var args = slice.call(arguments, 1);
77
78                    for (var i = 0, len = this.length; i < len; i++) {
79                        var elem = this[i];
80                        var instance = $.data(elem, namespace);
81                        if (!instance) {
82                            logError("cannot call methods on " + namespace + " prior to initialization; " +
83                                "attempted to call '" + options + "'");
84                            continue;
85                        }
86                        if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
87                            logError("no such method '" + options + "' for " + namespace + " instance");
88                            continue;
89                        }
90
91                        // trigger method with arguments
92                        var returnValue = instance[options].apply(instance, args);
93
94                        // break look and return first value if provided
95                        if (returnValue !== undefined) {
96                            return returnValue;
97                        }
98                    }
99                    // return this if no return value
100                    return this;
101                } else {
102                    return this.each(function() {
103                        var instance = $.data(this, namespace);
104                        if (instance) {
105                            // apply options & init
106                            instance.option(options);
107                            instance._init();
108                        } else {
109                            // initialize new instance
110                            instance = new PluginClass(this, options);
111                            $.data(this, namespace, instance);
112                        }
113                    });
114                }
115            };
116
117        }
118
119        // -------------------------- bridget -------------------------- //
120
121        /**
122         * converts a Prototypical class into a proper jQuery plugin
123         *   the class must have a ._init method
124         * @param {String} namespace - plugin name, used in $().pluginName
125         * @param {Function} PluginClass - constructor class
126         */
127        $.bridget = function(namespace, PluginClass) {
128            addOptionMethod(PluginClass);
129            bridge(namespace, PluginClass);
130        };
131
132        return $.bridget;
133
134    }
135
136    // transport
137    if (typeof define === 'function' && define.amd) {
138        // AMD
139        define('jquery-bridget/jquery.bridget', ['jquery'], defineBridget);
140    } else {
141        // get jquery from browser global
142        defineBridget(window.jQuery);
143    }
144
145})(window);
146
147/*!
148 * eventie v1.0.5
149 * event binding helper
150 *   eventie.bind( elem, 'click', myFn )
151 *   eventie.unbind( elem, 'click', myFn )
152 * MIT license
153 */
154
155/*jshint browser: true, undef: true, unused: true */
156/*global define: false, module: false */
157
158(function(window) {
159
160
161
162    var docElem = document.documentElement;
163
164    var bind = function() {};
165
166    function getIEEvent(obj) {
167        var event = window.event;
168        // add event.target
169        event.target = event.target || event.srcElement || obj;
170        return event;
171    }
172
173    if (docElem.addEventListener) {
174        bind = function(obj, type, fn) {
175            obj.addEventListener(type, fn, false);
176        };
177    } else if (docElem.attachEvent) {
178        bind = function(obj, type, fn) {
179            obj[type + fn] = fn.handleEvent ?
180                function() {
181                    var event = getIEEvent(obj);
182                    fn.handleEvent.call(fn, event);
183            } :
184                function() {
185                    var event = getIEEvent(obj);
186                    fn.call(obj, event);
187            };
188            obj.attachEvent("on" + type, obj[type + fn]);
189        };
190    }
191
192    var unbind = function() {};
193
194    if (docElem.removeEventListener) {
195        unbind = function(obj, type, fn) {
196            obj.removeEventListener(type, fn, false);
197        };
198    } else if (docElem.detachEvent) {
199        unbind = function(obj, type, fn) {
200            obj.detachEvent("on" + type, obj[type + fn]);
201            try {
202                delete obj[type + fn];
203            } catch (err) {
204                // can't delete window object properties
205                obj[type + fn] = undefined;
206            }
207        };
208    }
209
210    var eventie = {
211        bind: bind,
212        unbind: unbind
213    };
214
215    // ----- module definition ----- //
216
217    if (typeof define === 'function' && define.amd) {
218        // AMD
219        define('eventie/eventie', eventie);
220    } else if (typeof exports === 'object') {
221        // CommonJS
222        module.exports = eventie;
223    } else {
224        // browser global
225        window.eventie = eventie;
226    }
227
228})(this);
229
230/*!
231 * docReady
232 * Cross browser DOMContentLoaded event emitter
233 */
234
235/*jshint browser: true, strict: true, undef: true, unused: true*/
236/*global define: false */
237
238(function(window) {
239
240
241
242    var document = window.document;
243    // collection of functions to be triggered on ready
244    var queue = [];
245
246    function docReady(fn) {
247        // throw out non-functions
248        if (typeof fn !== 'function') {
249            return;
250        }
251
252        if (docReady.isReady) {
253            // ready now, hit it
254            fn();
255        } else {
256            // queue function when ready
257            queue.push(fn);
258        }
259    }
260
261    docReady.isReady = false;
262
263    // triggered on various doc ready events
264    function init(event) {
265        // bail if IE8 document is not ready just yet
266        var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete';
267        if (docReady.isReady || isIE8NotReady) {
268            return;
269        }
270        docReady.isReady = true;
271
272        // process queue
273        for (var i = 0, len = queue.length; i < len; i++) {
274            var fn = queue[i];
275            fn();
276        }
277    }
278
279    function defineDocReady(eventie) {
280        eventie.bind(document, 'DOMContentLoaded', init);
281        eventie.bind(document, 'readystatechange', init);
282        eventie.bind(window, 'load', init);
283
284        return docReady;
285    }
286
287    // transport
288    if (typeof define === 'function' && define.amd) {
289        // AMD
290        // if RequireJS, then doc is already ready
291        docReady.isReady = typeof requirejs === 'function';
292        define('doc-ready/doc-ready', ['eventie/eventie'], defineDocReady);
293    } else {
294        // browser global
295        window.docReady = defineDocReady(window.eventie);
296    }
297
298})(this);
299
300/*!
301 * EventEmitter v4.2.7 - git.io/ee
302 * Oliver Caldwell
303 * MIT license
304 * @preserve
305 */
306
307(function() {
308
309
310    /**
311     * Class for managing events.
312     * Can be extended to provide event functionality in other classes.
313     *
314     * @class EventEmitter Manages event registering and emitting.
315     */
316    function EventEmitter() {}
317
318    // Shortcuts to improve speed and size
319    var proto = EventEmitter.prototype;
320    var exports = this;
321    var originalGlobalValue = exports.EventEmitter;
322
323    /**
324     * Finds the index of the listener for the event in it's storage array.
325     *
326     * @param {Function[]} listeners Array of listeners to search through.
327     * @param {Function} listener Method to look for.
328     * @return {Number} Index of the specified listener, -1 if not found
329     * @api private
330     */
331    function indexOfListener(listeners, listener) {
332        var i = listeners.length;
333        while (i--) {
334            if (listeners[i].listener === listener) {
335                return i;
336            }
337        }
338
339        return -1;
340    }
341
342    /**
343     * Alias a method while keeping the context correct, to allow for over
vendor: 16,384 bytes, lines 343-727
343writing of target method.
344     *
345     * @param {String} name The name of the target method.
346     * @return {Function} The aliased method
347     * @api private
348     */
349    function alias(name) {
350        return function aliasClosure() {
351            return this[name].apply(this, arguments);
352        };
353    }
354
355    /**
356     * Returns the listener array for the specified event.
357     * Will initialise the event object and listener arrays if required.
358     * 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.
359     * Each property in the object response is an array of listener functions.
360     *
361     * @param {String|RegExp} evt Name of the event to return the listeners from.
362     * @return {Function[]|Object} All listener functions for the event.
363     */
364    proto.getListeners = function getListeners(evt) {
365        var events = this._getEvents();
366        var response;
367        var key;
368
369        // Return a concatenated array of all matching events if
370        // the selector is a regular expression.
371        if (evt instanceof RegExp) {
372            response = {};
373            for (key in events) {
374                if (events.hasOwnProperty(key) && evt.test(key)) {
375                    response[key] = events[key];
376                }
377            }
378        } else {
379            response = events[evt] || (events[evt] = []);
380        }
381
382        return response;
383    };
384
385    /**
386     * Takes a list of listener objects and flattens it into a list of listener functions.
387     *
388     * @param {Object[]} listeners Raw listener objects.
389     * @return {Function[]} Just the listener functions.
390     */
391    proto.flattenListeners = function flattenListeners(listeners) {
392        var flatListeners = [];
393        var i;
394
395        for (i = 0; i < listeners.length; i += 1) {
396            flatListeners.push(listeners[i].listener);
397        }
398
399        return flatListeners;
400    };
401
402    /**
403     * 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.
404     *
405     * @param {String|RegExp} evt Name of the event to return the listeners from.
406     * @return {Object} All listener functions for an event in an object.
407     */
408    proto.getListenersAsObject = function getListenersAsObject(evt) {
409        var listeners = this.getListeners(evt);
410        var response;
411
412        if (listeners instanceof Array) {
413            response = {};
414            response[evt] = listeners;
415        }
416
417        return response || listeners;
418    };
419
420    /**
421     * Adds a listener function to the specified event.
422     * The listener will not be added if it is a duplicate.
423     * If the listener returns true then it will be removed after it is called.
424     * If you pass a regular expression as the event name then the listener will be added to all events that match it.
425     *
426     * @param {String|RegExp} evt Name of the event to attach the listener to.
427     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
428     * @return {Object} Current instance of EventEmitter for chaining.
429     */
430    proto.addListener = function addListener(evt, listener) {
431        var listeners = this.getListenersAsObject(evt);
432        var listenerIsWrapped = typeof listener === 'object';
433        var key;
434
435        for (key in listeners) {
436            if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
437                listeners[key].push(listenerIsWrapped ? listener : {
438                    listener: listener,
439                    once: false
440                });
441            }
442        }
443
444        return this;
445    };
446
447    /**
448     * Alias of addListener
449     */
450    proto.on = alias('addListener');
451
452    /**
453     * Semi-alias of addListener. It will add a listener that will be
454     * automatically removed after it's first execution.
455     *
456     * @param {String|RegExp} evt Name of the event to attach the listener to.
457     * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
458     * @return {Object} Current instance of EventEmitter for chaining.
459     */
460    proto.addOnceListener = function addOnceListener(evt, listener) {
461        return this.addListener(evt, {
462            listener: listener,
463            once: true
464        });
465    };
466
467    /**
468     * Alias of addOnceListener.
469     */
470    proto.once = alias('addOnceListener');
471
472    /**
473     * 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.
474     * You need to tell it what event names should be matched by a regex.
475     *
476     * @param {String} evt Name of the event to create.
477     * @return {Object} Current instance of EventEmitter for chaining.
478     */
479    proto.defineEvent = function defineEvent(evt) {
480        this.getListeners(evt);
481        return this;
482    };
483
484    /**
485     * Uses defineEvent to define multiple events.
486     *
487     * @param {String[]} evts An array of event names to define.
488     * @return {Object} Current instance of EventEmitter for chaining.
489     */
490    proto.defineEvents = function defineEvents(evts) {
491        for (var i = 0; i < evts.length; i += 1) {
492            this.defineEvent(evts[i]);
493        }
494        return this;
495    };
496
497    /**
498     * Removes a listener function from the specified event.
499     * When passed a regular expression as the event name, it will remove the listener from all events that match it.
500     *
501     * @param {String|RegExp} evt Name of the event to remove the listener from.
502     * @param {Function} listener Method to remove from the event.
503     * @return {Object} Current instance of EventEmitter for chaining.
504     */
505    proto.removeListener = function removeListener(evt, listener) {
506        var listeners = this.getListenersAsObject(evt);
507        var index;
508        var key;
509
510        for (key in listeners) {
511            if (listeners.hasOwnProperty(key)) {
512                index = indexOfListener(listeners[key], listener);
513
514                if (index !== -1) {
515                    listeners[key].splice(index, 1);
516                }
517            }
518        }
519
520        return this;
521    };
522
523    /**
524     * Alias of removeListener
525     */
526    proto.off = alias('removeListener');
527
528    /**
529     * Adds listeners in bulk using the manipulateListeners method.
530     * 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.
531     * You can also pass it a regular expression to add the array of listeners to all events that match it.
532     * Yeah, this function does quite a bit. That's probably a bad thing.
533     *
534     * @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.
535     * @param {Function[]} [listeners] An optional array of listener functions to add.
536     * @return {Object} Current instance of EventEmitter for chaining.
537     */
538    proto.addListeners = function addListeners(evt, listeners) {
539        // Pass through to manipulateListeners
540        return this.manipulateListeners(false, evt, listeners);
541    };
542
543    /**
544     * Removes listeners in bulk using the manipulateListeners method.
545     * 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.
546     * You can also pass it an event name and an array of listeners to be removed.
547     * You can also pass it a regular expression to remove the listeners from all events that match it.
548     *
549     * @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.
550     * @param {Function[]} [listeners] An optional array of listener functions to remove.
551     * @return {Object} Current instance of EventEmitter for chaining.
552     */
553    proto.removeListeners = function removeListeners(evt, listeners) {
554        // Pass through to manipulateListeners
555        return this.manipulateListeners(true, evt, listeners);
556    };
557
558    /**
559     * 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.
560     * The first argument will determine if the listeners are removed (true) or added (false).
561     * 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.
562     * You can also pass it an event name and an array of listeners to be added/removed.
563     * You can also pass it a regular expression to manipulate the listeners of all events that match it.
564     *
565     * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
566     * @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.
567     * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
568     * @return {Object} Current instance of EventEmitter for chaining.
569     */
570    proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
571        var i;
572        var value;
573        var single = remove ? this.removeListener : this.addListener;
574        var multiple = remove ? this.removeListeners : this.addListeners;
575
576        // If evt is an object then pass each of it's properties to this method
577        if (typeof evt === 'object' && !(evt instanceof RegExp)) {
578            for (i in evt) {
579                if (evt.hasOwnProperty(i) && (value = evt[i])) {
580                    // Pass the single listener straight through to the singular method
581                    if (typeof value === 'function') {
582                        single.call(this, i, value);
583                    } else {
584                        // Otherwise pass back to the multiple function
585                        multiple.call(this, i, value);
586                    }
587                }
588            }
589        } else {
590            // So evt must be a string
591            // And listeners must be an array of listeners
592            // Loop over it and pass each one to the multiple method
593            i = listeners.length;
594            while (i--) {
595                single.call(this, evt, listeners[i]);
596            }
597        }
598
599        return this;
600    };
601
602    /**
603     * Removes all listeners from a specified event.
604     * If you do not specify an event then all listeners will be removed.
605     * That means every event will be emptied.
606     * You can also pass a regex to remove all events that match it.
607     *
608     * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
609     * @return {Object} Current instance of EventEmitter for chaining.
610     */
611    proto.removeEvent = function removeEvent(evt) {
612        var type = typeof evt;
613        var events = this._getEvents();
614        var key;
615
616        // Remove different things depending on the state of evt
617        if (type === 'string') {
618            // Remove all listeners for the specified event
619            delete events[evt];
620        } else if (evt instanceof RegExp) {
621            // Remove all events matching the regex.
622            for (key in events) {
623                if (events.hasOwnProperty(key) && evt.test(key)) {
624                    delete events[key];
625                }
626            }
627        } else {
628            // Remove all listeners in all events
629            delete this._events;
630        }
631
632        return this;
633    };
634
635    /**
636     * Alias of removeEvent.
637     *
638     * Added to mirror the node API.
639     */
640    proto.removeAllListeners = alias('removeEvent');
641
642    /**
643     * Emits an event of your choice.
644     * When emitted, every listener attached to that event will be executed.
645     * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
646     * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
647     * So they will not arrive within the array on the other side, they will be separate.
648     * You can also pass a regular expression to emit to all events that match it.
649     *
650     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
651     * @param {Array} [args] Optional array of arguments to be passed to each listener.
652     * @return {Object} Current instance of EventEmitter for chaining.
653     */
654    proto.emitEvent = function emitEvent(evt, args) {
655        var listeners = this.getListenersAsObject(evt);
656        var listener;
657        var i;
658        var key;
659        var response;
660
661        for (key in listeners) {
662            if (listeners.hasOwnProperty(key)) {
663                i = listeners[key].length;
664
665                while (i--) {
666                    // If the listener returns true then it shall be removed from the event
667                    // The function is executed either with a basic call or an apply if there is an args array
668                    listener = listeners[key][i];
669
670                    if (listener.once === true) {
671                        this.removeListener(evt, listener.listener);
672                    }
673
674                    response = listener.listener.apply(this, args || []);
675
676                    if (response === this._getOnceReturnValue()) {
677                        this.removeListener(evt, listener.listener);
678                    }
679                }
680            }
681        }
682
683        return this;
684    };
685
686    /**
687     * Alias of emitEvent
688     */
689    proto.trigger = alias('emitEvent');
690
691    /**
692     * 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.
693     * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
694     *
695     * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
696     * @param {...*} Optional additional arguments to be passed to each listener.
697     * @return {Object} Current instance of EventEmitter for chaining.
698     */
699    proto.emit = function emit(evt) {
700        var args = Array.prototype.slice.call(arguments, 1);
701        return this.emitEvent(evt, args);
702    };
703
704    /**
705     * Sets the current value to check against when executing listeners. If a
706     * listeners return value matches the one set here then it will be removed
707     * after execution. This value defaults to true.
708     *
709     * @param {*} value The new value to check for when executing listeners.
710     * @return {Object} Current instance of EventEmitter for chaining.
711     */
712    proto.setOnceReturnValue = function setOnceReturnValue(value) {
713        this._onceReturnValue = value;
714        return this;
715    };
716
717    /**
718     * Fetches the current value to check against when executing listeners. If
719     * the listeners return value matches this one then it should be removed
720     * automatically. It will return true by default.
721     *
722     * @return {*|Boolean} The current value to check for or the default, true.
723     * @api private
724     */
725    proto._getOnceReturnValue = function _getOnceReturnValue() {
726        if (this.hasOwnProperty('_onceReturnValue')) {
727            ret
727urn this._onceReturnValue;
728        } else {
729            return true;
730        }
731    };
732
733    /**
734     * Fetches the events object and creates one if required.
735     *
736     * @return {Object} The events storage object.
737     * @api private
738     */
739    proto._getEvents = function _getEvents() {
740        return this._events || (this._events = {});
741    };
742
743    /**
744     * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
745     *
746     * @return {Function} Non conflicting EventEmitter class.
747     */
748    EventEmitter.noConflict = function noConflict() {
749        exports.EventEmitter = originalGlobalValue;
750        return EventEmitter;
751    };
752
753    // Expose the class either via AMD, CommonJS or the global object
754    if (typeof define === 'function' && define.amd) {
755        define('eventEmitter/EventEmitter', [], function() {
756            return EventEmitter;
757        });
758    } else if (typeof module === 'object' && module.exports) {
759        module.exports = EventEmitter;
760    } else {
761        this.EventEmitter = EventEmitter;
762    }
763}.call(this));
764
765/*!
766 * getStyleProperty v1.0.3
767 * original by kangax
768 * http://perfectionkills.com/feature-testing-css-properties/
769 */
770
771/*jshint browser: true, strict: true, undef: true */
772/*global define: false, exports: false, module: false */
773
774(function(window) {
775
776
777
778    var prefixes = 'Webkit Moz ms Ms O'.split(' ');
779    var docElemStyle = document.documentElement.style;
780
781    function getStyleProperty(propName) {
782        if (!propName) {
783            return;
784        }
785
786        // test standard property first
787        if (typeof docElemStyle[propName] === 'string') {
788            return propName;
789        }
790
791        // capitalize
792        propName = propName.charAt(0).toUpperCase() + propName.slice(1);
793
794        // test vendor specific properties
795        var prefixed;
796        for (var i = 0, len = prefixes.length; i < len; i++) {
797            prefixed = prefixes[i] + propName;
798            if (typeof docElemStyle[prefixed] === 'string') {
799                return prefixed;
800            }
801        }
802    }
803
804    // transport
805    if (typeof define === 'function' && define.amd) {
806        // AMD
807        define('get-style-property/get-style-property', [], function() {
808            return getStyleProperty;
809        });
810    } else if (typeof exports === 'object') {
811        // CommonJS for Component
812        module.exports = getStyleProperty;
813    } else {
814        // browser global
815        window.getStyleProperty = getStyleProperty;
816    }
817
818})(window);
819
820/**
821 * getSize v1.1.7
822 * measure size of elements
823 */
824
825/*jshint browser: true, strict: true, undef: true, unused: true */
826/*global define: false, exports: false, require: false, module: false */
827
828(function(window, undefined) {
829
830
831
832    // -------------------------- helpers -------------------------- //
833
834    var getComputedStyle = window.getComputedStyle;
835    var getStyle = getComputedStyle ?
836            function(elem) {
837                return getComputedStyle(elem, null);
838        } :
839            function(elem) {
840                return elem.currentStyle;
841        };
842
843    // get a number from a string, not a percentage
844    function getStyleSize(value) {
845        var num = parseFloat(value);
846        // not a percent like '100%', and a number
847        var isValid = value.indexOf('%') === -1 && !isNaN(num);
848        return isValid && num;
849    }
850
851    // -------------------------- measurements -------------------------- //
852
853    var measurements = [
854        'paddingLeft',
855        'paddingRight',
856        'paddingTop',
857        'paddingBottom',
858        'marginLeft',
859        'marginRight',
860        'marginTop',
861        'marginBottom',
862        'borderLeftWidth',
863        'borderRightWidth',
864        'borderTopWidth',
865        'borderBottomWidth'
866    ];
867
868    function getZeroSize() {
869        var size = {
870            width: 0,
871            height: 0,
872            innerWidth: 0,
873            innerHeight: 0,
874            outerWidth: 0,
875            outerHeight: 0
876        };
877        for (var i = 0, len = measurements.length; i < len; i++) {
878            var measurement = measurements[i];
879            size[measurement] = 0;
880        }
881        return size;
882    }
883
884
885
886    function defineGetSize(getStyleProperty) {
887
888        // -------------------------- box sizing -------------------------- //
889
890        var boxSizingProp = getStyleProperty('boxSizing');
891        var isBoxSizeOuter;
892
893        /**
894         * WebKit measures the outer-width on style.width on border-box elems
895         * IE & Firefox measures the inner-width
896         */
897        (function() {
898            if (!boxSizingProp) {
899                return;
900            }
901
902            var div = document.createElement('div');
903            div.style.width = '200px';
904            div.style.padding = '1px 2px 3px 4px';
905            div.style.borderStyle = 'solid';
906            div.style.borderWidth = '1px 2px 3px 4px';
907            div.style[boxSizingProp] = 'border-box';
908
909            var body = document.body || document.documentElement;
910            body.appendChild(div);
911            var style = getStyle(div);
912
913            isBoxSizeOuter = getStyleSize(style.width) === 200;
914            body.removeChild(div);
915        })();
916
917
918        // -------------------------- getSize -------------------------- //
919
920        function getSize(elem) {
921            // use querySeletor if elem is string
922            if (typeof elem === 'string') {
923                elem = document.querySelector(elem);
924            }
925
926            // do not proceed on non-objects
927            if (!elem || typeof elem !== 'object' || !elem.nodeType) {
928                return;
929            }
930
931            var style = getStyle(elem);
932
933            // if hidden, everything is 0
934            if (style.display === 'none') {
935                return getZeroSize();
936            }
937
938            var size = {};
939            size.width = elem.offsetWidth;
940            size.height = elem.offsetHeight;
941
942            var isBorderBox = size.isBorderBox = !! (boxSizingProp &&
943                style[boxSizingProp] && style[boxSizingProp] === 'border-box');
944
945            // get all measurements
946            for (var i = 0, len = measurements.length; i < len; i++) {
947                var measurement = measurements[i];
948                var value = style[measurement];
949                value = mungeNonPixel(elem, value);
950                var num = parseFloat(value);
951                // any 'auto', 'medium' value will be 0
952                size[measurement] = !isNaN(num) ? num : 0;
953            }
954
955            var paddingWidth = size.paddingLeft + size.paddingRight;
956            var paddingHeight = size.paddingTop + size.paddingBottom;
957            var marginWidth = size.marginLeft + size.marginRight;
958            var marginHeight = size.marginTop + size.marginBottom;
959            var borderWidth = size.borderLeftWidth + size.borderRightWidth;
960            var borderHeight = size.borderTopWidth + size.borderBottomWidth;
961
962            var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
963
964            // overwrite width and height if we can get it from style
965            var styleWidth = getStyleSize(style.width);
966            if (styleWidth !== false) {
967                size.width = styleWidth +
968                // add padding and border unless it's already including it
969                (isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth);
970            }
971
972            var styleHeight = getStyleSize(style.height);
973            if (styleHeight !== false) {
974                size.height = styleHeight +
975                // add padding and border unless it's already including it
976                (isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight);
977            }
978
979            size.innerWidth = size.width - (paddingWidth + borderWidth);
980            size.innerHeight = size.height - (paddingHeight + borderHeight);
981
982            size.outerWidth = size.width + marginWidth;
983            size.outerHeight = size.height + marginHeight;
984
985            return size;
986        }
987
988        // IE8 returns percent values, not pixels
989        // taken from jQuery's curCSS
990        function mungeNonPixel(elem, value) {
991            // IE8 and has percent value
992            if (getComputedStyle || value.indexOf('%') === -1) {
993                return value;
994            }
995            var style = elem.style;
996            // Remember the original values
997            var left = style.left;
998            var rs = elem.runtimeStyle;
999            var rsLeft = rs && rs.left;
1000
1001            // Put in the new values to get a computed value out
1002            if (rsLeft) {
1003                rs.left = elem.currentStyle.left;
1004            }
1005            style.left = value;
1006            value = style.pixelLeft;
1007
1008            // Revert the changed values
1009            style.left = left;
1010            if (rsLeft) {
1011                rs.left = rsLeft;
1012            }
1013
1014            return value;
1015        }
1016
1017        return getSize;
1018
1019    }
1020
1021    // transport
1022    if (typeof define === 'function' && define.amd) {
1023        // AMD for RequireJS
1024        define('get-size/get-size', ['get-style-property/get-style-property'], defineGetSize);
1025    } else if (typeof exports === 'object') {
1026        // CommonJS for Component
1027        module.exports = defineGetSize(require('get-style-property'));
1028    } else {
1029        // browser global
1030        window.getSize = defineGetSize(window.getStyleProperty);
1031    }
1032
1033})(window);
1034
1035/**
1036 * matchesSelector helper v1.0.1
1037 *
1038 * @name matchesSelector
1039 *   @param {Element} elem
1040 *   @param {String} selector
1041 */
1042
1043/*jshint browser: true, strict: true, undef: true, unused: true */
1044/*global define: false */
1045
1046(function(global, ElemProto) {
1047
1048
1049
1050    var matchesMethod = (function() {
1051        // check un-prefixed
1052        if (ElemProto.matchesSelector) {
1053            return 'matchesSelector';
1054        }
1055        // check vendor prefixes
1056        var prefixes = ['webkit', 'moz', 'ms', 'o'];
1057
1058        for (var i = 0, len = prefixes.length; i < len; i++) {
1059            var prefix = prefixes[i];
1060            var method = prefix + 'MatchesSelector';
1061            if (ElemProto[method]) {
1062                return method;
1063            }
1064        }
1065    })();
1066
1067    // ----- match ----- //
1068
1069    function match(elem, selector) {
1070        return elem[matchesMethod](selector);
1071    }
1072
1073    // ----- appendToFragment ----- //
1074
1075    function checkParent(elem) {
1076        // not needed if already has parent
1077        if (elem.parentNode) {
1078            return;
1079        }
1080        var fragment = document.createDocumentFragment();
1081        fragment.appendChild(elem);
1082    }
1083
1084    // ----- query ----- //
1085
1086    // fall back to using QSA
1087    // thx @jonathantneal https://gist.github.com/3062955
1088    function query(elem, selector) {
1089        // append to fragment if no parent
1090        checkParent(elem);
1091
1092        // match elem with all selected elems of parent
1093        var elems = elem.parentNode.querySelectorAll(selector);
1094        for (var i = 0, len = elems.length; i < len; i++) {
1095            // return true if match
1096            if (elems[i] === elem) {
1097                return true;
1098            }
1099        }
1100        // otherwise return false
1101        return false;
1102    }
1103
1104    // ----- matchChild ----- //
1105
1106    function matchChild(elem, selector) {
1107        checkParent(elem);
1108        return match(elem, selector);
1109    }
1110
1111    // ----- matchesSelector ----- //
1112
1113    var matchesSelector;
1114
1115    if (matchesMethod) {
1116        // IE9 supports matchesSelector, but doesn't work on orphaned elems
1117        // check for that
1118        var div = document.createElement('div');
1119        var supportsOrphans = match(div, 'div');
1120        matchesSelector = supportsOrphans ? match : matchChild;
1121    } else {
1122        matchesSelector = query;
1123    }
1124
1125    // transport
1126    if (typeof define === 'function' && define.amd) {
1127        // AMD
1128        define('matches-selector/matches-selector', [], function() {
1129            return matchesSelector;
1130        });
1131    } else {
1132        // browser global
1133        window.matchesSelector = matchesSelector;
1134    }
1135
1136})(this, Element.prototype);
1137
1138/**
1139 * Outlayer Item
1140 */
1141
1142(function(window) {
1143
1144
1145
1146    // ----- get style ----- //
1147
1148    var getComputedStyle = window.getComputedStyle;
1149    var getStyle = getComputedStyle ?
1150            function(elem) {
1151                return getComputedStyle(elem, null);
1152        } :
1153            function(elem) {
1154                return elem.currentStyle;
1155        };
1156
1157
1158    // extend objects
1159    function extend(a, b) {
1160        for (var prop in b) {
1161            a[prop] = b[prop];
1162        }
1163        return a;
1164    }
1165
1166    function isEmptyObj(obj) {
1167        for (var prop in obj) {
1168            return false;
1169        }
1170        prop = null;
1171        return true;
1172    }
1173
1174    // http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
1175    function toDash(str) {
1176        return str.replace(/([A-Z])/g, function($1) {
1177            return '-' + $1.toLowerCase();
1178        });
1179    }
1180
1181    // -------------------------- Outlayer definition -------------------------- //
1182
1183    function outlayerItemDefinition(EventEmitter, getSize, getStyleProperty) {
1184
1185        // -------------------------- CSS3 support -------------------------- //
1186
1187        var transitionProperty = getStyleProperty('transition');
1188        var transformProperty = getStyleProperty('transform');
1189        var supportsCSS3 = transitionProperty && transformProperty;
1190        var is3d = !! getStyleProperty('perspective');
1191
1192        var transitionEndEvent = {
1193            WebkitTransition: 'webkitTransitionEnd',
1194            MozTransition: 'transitionend',
1195            OTransition: 'otransitionend',
1196            transition: 'transitionend'
1197        }[transitionProperty];
1198
1199        // properties that could have vendor prefix
1200        var prefixableProperties = [
1201            'transform',
1202            'transition',
1203            'transitionDuration',
1204            'transitionProperty'
1205        ];
1206
1207        // cache all vendor properties
1208        var vendorProperties = (function() {
1209            var cache = {};
1210            for (var i = 0, len = prefixableProperties.length; i < len; i++) {
1211                var prop = prefixableProperties[i];
1212                var supportedProp = getStyleProperty(prop);
1213                if (supportedProp && supportedProp !== prop) {
1214                    cache[prop] = supportedProp;
1215                }
1216            }
1217            return cache;
1218        })();
1219
1220        // -------------------------- Item -------------------------- //
1221
1222        function Item(element, layout) {
1223            if (!element) {
1224                return;
1225            }
1226
1227            this.element = element;
1228            // parent layout class, i.e. Masonry, Isotope, or Packery
1229            this.layout = layout;
1230            this.position = {
1231                x: 0,
1232                y: 0
1233            };
1234
1235            this._create();
1236        }
1237
1238        // inherit EventEmitter
1239        extend(Item.prototype, EventEmitter.prototype);
1240
1241        Item.prototype._create = function() {
1242            // transition objects
1243            this._transn = {
1244                ingProperties: {},
1245                clean: {},
1246                onEnd: {}
1247            };
1248
1249            this.css({
1250                position: 'absolute'
1251            });
1252        };
1253
1254        // trigger specified handler for event type
1255        Item.prototype.handleEvent = function(event) {
1256            var method = 'on' + event.type;
1257            if (this[method]) {
1258                this[method](event);
1259            }
1260        };
1261
1262        Item.prototype.getSize = function() {
1263            this.size = getSize(this.element);
1264        };
1265
1266        /**
1267         * apply CSS styles to element
1268         * @param {Object} style
1269         */
1270        Item.prototype.css = function(style) {
1271            var elemStyle = this.element.style;
1272
1273            for (var prop in style) {
1274                // use vendor property if available
1275                var supportedProp = vendorProperties[prop] || prop;
1276                elemStyle[supportedProp] = style[prop];
1277            }
1278        };
1279
1280        // measure position, and sets it
1281        Item.prototype.getPosition = function() {
1282            var style = getStyle(this.element);
1283            var layoutOptions = this.layout.options;
1284            var isOriginLeft = layoutOptions.isOriginLeft;
1285            var isOriginTop = layoutOptions.isOriginTop;
1286            var x = parseInt(style[isOriginLeft ? 'left' : 'right'], 10);
1287            var y = parseInt(style[isOriginTop ? 'top' : 'bottom'], 10);
1288
1289            // clean up 'auto' or other non-integer values
1290            x = isNaN(x) ? 0 : x;
1291            y = isNaN(y) ? 0 : y;
1292            // remove padding from measurement
1293            var layoutSize = this.layout.size;
1294            x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
1295            y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
1296
1297            this.position.x = x;
1298            this.position.y = y;
1299        };
1300
1301        // set settled position, apply padding
1302        Item.prototype.layoutPosition = function() {
1303            var layoutSize = this.layout.size;
1304            var layoutOptions = this.layout.options;
1305            var style = {};
1306
1307            if (layoutOptions.isOriginLeft) {
1308                style.left = (this.position.x + layoutSize.paddingLeft) + 'px';
1309                // reset other property
1310                style.right = '';
1311            } else {
1312                style.right = (this.position.x + layoutSize.paddingRight) + 'px';
1313                style.left = '';
1314            }
1315
1316            if (layoutOptions.isOriginTop) {
1317                style.top = (this.position.y + layoutSize.paddingTop) + 'px';
1318                style.bottom = '';
1319            } else {
1320                style.bottom = (this.position.y + layoutSize.paddingBottom) + 'px';
1321                style.top = '';
1322            }
1323
1324            this.css(style);
1325            this.emitEvent('layout', [this]);
1326        };
1327
1328
1329        // transform translate function
1330        var translate = is3d ?
1331                function(x, y) {
1332                    return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
1333            } :
1334                function(x, y) {
1335                    return 'translate(' + x + 'px, ' + y + 'px)';
1336            };
1337
1338
1339        Item.prototype._transitionTo = function(x, y) {
1340            this.getPosition();
1341            // get current x & y from top/left
1342            var curX = this.position.x;
1343            var curY = this.position.y;
1344
1345            var compareX = parseInt(x, 10);
1346            var compareY = parseInt(y, 10);
1347            var didNotMove = compareX === this.position.x && compareY === this.position.y;
1348
1349            // save end position
1350            this.setPosition(x, y);
1351
1352            // if did not move and not transitioning, just go to layout
1353            if (didNotMove && !this.isTransitioning) {
1354                this.layoutPosition();
1355                return;
1356            }
1357
1358            var transX = x - curX;
1359            var transY = y - curY;
1360            var transitionStyle = {};
1361            // flip cooridinates if origin on right or bottom
1362            var layoutOptions = this.layout.options;
1363            transX = layoutOptions.isOriginLeft ? transX : -transX;
1364            transY = layoutOptions.isOriginTop ? transY : -transY;
1365            transitionStyle.transform = translate(transX, transY);
1366
1367            this.transition({
1368                to: transitionStyle,
1369                onTransitionEnd: {
1370                    transform: this.layoutPosition
1371                },
1372                isCleaning: true
1373            });
1374        };
1375
1376        // non transition + transform support
1377        Item.prototype.goTo = function(x, y) {
1378            this.setPosition(x, y);
1379            this.layoutPosition();
1380        };
1381
1382        // use transition and transforms if supported
1383        Item.prototype.moveTo = supportsCSS3 ?
1384            Item.prototype._transitionTo : Item.prototype.goTo;
1385
1386        Item.prototype.setPosition = function(x, y) {
1387            this.position.x = parseInt(x, 10);
1388            this.position.y = parseInt(y, 10);
1389        };
1390
1391        // ----- transition ----- //
1392
1393        /**
1394         * @param {Object} style - CSS
1395         * @param {Function} onTransitionEnd
1396         */
1397
1398        // non transition, just trigger callback
1399        Item.prototype._nonTransition = function(args) {
1400            this.css(args.to);
1401            if (args.isCleaning) {
1402                this._removeStyles(args.to);
1403            }
1404            for (var prop in args.onTransitionEnd) {
1405                args.onTransitionEnd[prop].call(this);
1406            }
1407        };
1408
1409        /**
1410         * proper transition
1411         * @param {Object} args - arguments
1412         *   @param {Object} to - style to transition to
1413         *   @param {Object} from - style to start transition from
1414         *   @param {Boolean} isCleaning - removes transition styles after transition
1415         *   @param {Function} onTransitionEnd - callback
1416         */
1417        Item.prototype._transition = function(args) {
1418            // redirect to nonTransition if no transition duration
1419            if (!parseFloat(this.layout.options.transitionDuration)) {
1420                this._nonTransition(args);
1421                return;
1422            }
1423
1424            var _transition = this._transn;
1425            // keep track of onTransitionEnd callback by css property
1426            for (var prop in args.onTransitionEnd) {
1427                _transition.onEnd[prop] = args.onTransitionEnd[prop];
1428            }
1429            // keep track of properties that are transitioning
1430            for (prop in args.to) {
1431                _transition.ingProperties[prop] = true;
1432                // keep track of properties to clean up when transition is done
1433                if (args.isCleaning) {
1434                    _transition.clean[prop] = true;
1435                }
1436            }
1437
1438            // set from styles
1439            if (args.from) {
1440                this.css(args.from);
1441                // force redraw. http://blog.alexmaccaw.com/css-transitions
1442                var h = this.element.offsetHeight;
1443                // hack for JSHint to hush about unused var
1444                h = null;
1445            }
1446            // enable transition
1447            this.enableTransition(args.to);
1448            // set styles that are transitioning
1449            this.css(args.to);
1450
1451            this.isTransitioning = true;
1452
1453        };
1454
1455        var itemTransitionProperties = transformProperty && (toDash(transformProperty) +
1456            ',opacity');
1457
1458        Item.prototype.enableTransition = function( /* style */ ) {
1459            // only enable if not already transitioning
1460            // bug in IE10 were re-setting transition style will prevent
1461            // transitionend event from triggering
1462            if (this.isTransitioning) {
1463                return;
1464            }
1465
1466            // make transition: foo, bar, baz from style object
1467            // TODO uncomment this bit when IE10 bug is resolved
1468            // var transitionValue = [];
1469            // for ( var prop in style ) {
1470            //   // dash-ify camelCased properties like WebkitTransition
1471            //   transitionValue.push( toDash( prop ) );
1472            // }
1473            // enable transition styles
1474            // HACK always enable transform,opacity for IE10
1475            this.css({
1476                transitionProperty: itemTransitionProperties,
1477                transitionDuration: this.layout.options.transitionDuration
1478            });
1479            // listen for transition end event
1480            this.element.addEventListener(transitionEndEvent, this, false);
1481        };
1482
1483        Item.prototype.transition = Item.prototype[transitionProperty ? '_transition' : '_nonTransition'];
1484
1485        // ----- events ----- //
1486
1487        Item.prototype.onwebkitTransitionEnd = function(event) {
1488            this.ontransitionend(event);
1489        };
1490
1491        Item.prototype.onotransitionend = function(event) {
1492            this.ontransitionend(event);
1493        };
1494
1495        // properties that I munge to make my life easier
1496        var dashedVendorProperties = {
1497            '-webkit-transform': 'transform',
1498            '-moz-transform': 'transform',
1499            '-o-transform': 'transform'
1500        };
1501
1502        Item.prototype.ontransitionend = function(event) {
1503            // disregard bubbled events from children
1504            if (event.target !== this.element) {
1505                return;
1506            }
1507            var _transition = this._transn;
1508            // get property name of transitioned property, convert to prefix-free
1509            var propertyName = dashedVendorProperties[event.propertyName] || event.propertyName;
1510
1511            // remove property that has completed transitioning
1512            delete _transition.ingProperties[propertyName];
1513            // check if any properties are still transitioning
1514            if (isEmptyObj(_transition.ingProperties)) {
1515                // all properties have completed transitioning
1516                this.disableTransition();
1517            }
1518            // clean style
1519            if (propertyName in _transition.clean) {
1520                // clean up style
1521                this.element.style[event.propertyName] = '';
1522                delete _transition.clean[propertyName];
1523            }
1524            // trigger onTransitionEnd callback
1525            if (propertyName in _transition.onEnd) {
1526                var onTransitionEnd = _transition.onEnd[propertyName];
1527                onTransitionEnd.call(this);
1528                delete _transition.onEnd[propertyName];
1529            }
1530
1531            this.emitEvent('transitionEnd', [this]);
1532        };
1533
1534        Item.prototype.disableTransition = function() {
1535            this.removeTransitionStyles();
1536            this.element.removeEventListener(transitionEndEvent, this, false);
1537            this.isTransitioning = false;
1538        };
1539
1540        /**
1541         * removes style property from element
1542         * @param {Object} style
1543         **/
1544        Item.prototype._removeStyles = function(style) {
1545            // clean up transition styles
1546            var cleanStyle = {};
1547            for (var prop in style) {
1548                cleanStyle[prop] = '';
1549            }
1550            this.css(cleanStyle);
1551        };
1552
1553        var cleanTransitionStyle = {
1554            transitionProperty: '',
1555            transitionDuration: ''
1556        };
1557
1558        Item.prototype.removeTransitionStyles = function() {
1559            // remove transition
1560            this.css(cleanTransitionStyle);
1561        };
1562
1563        // ----- show/hide/remove ----- //
1564
1565        // remove element from DOM
1566        Item.prototype.removeElem = function() {
1567            this.element.parentNode.removeChild(this.element);
1568            this.emitEvent('remove', [this]);
1569        };
1570
1571        Item.prototype.remove = function() {
1572            // just remove element if no transition support or no transition
1573            if (!transitionProperty || !parseFloat(this.layout.options.transitionDuration)) {
1574                this.removeElem();
1575                return;
1576            }
1577
1578            // start transition
1579            var _this = this;
1580            this.on('transitionEnd', function() {
1581                _this.removeElem();
1582                return true; // bind once
1583            });
1584            this.hide();
1585        };
1586
1587        Item.prototype.reveal = function() {
1588            delete this.isHidden;
1589            // remove display: none
1590            this.css({
1591                display: ''
1592            });
1593
1594            var options = this.layout.options;
1595            this.transition({
1596                from: options.hiddenStyle,
1597                to: options.visibleStyle,
1598                isCleaning: true
1599            });
1600        };
1601
1602        Item.prototype.hide = function() {
1603            // set flag
1604            this.isHidden = true;
1605            // remove display: none
1606            this.css({
1607                display: ''
1608            });
1609
1610            var options = this.layout.options;
1611            this.transition({
1612                from: options.visibleStyle,
1613                to: options.hiddenStyle,
1614                // keep hidden stuff hidden
1615                isCleaning: true,
1616                onTransitionEnd: {
1617                    opacity: function() {
1618                        // check if still hidden
1619                        // during transition, item may have been un-hidden
1620                        if (this.isHidden) {
1621                            this.css({
1622                                display: 'none'
1623                            });
1624                        }
1625                    }
1626                }
1627            });
1628        };
1629
1630        Item.prototype.destroy = function() {
1631            this.css({
1632                position: '',
1633                left: '',
1634                right: '',
1635                top: '',
1636                bottom: '',
1637                transition: '',
1638                transform: ''
1639            });
1640        };
1641
1642        return Item;
1643
1644    }
1645
1646    // -------------------------- transport -------------------------- //
1647
1648    if (typeof define === 'function' && define.amd) {
1649        // AMD
1650        define('outlayer/item', [
1651                'eventEmitter/EventEmitter',
1652                'get-size/get-size',
1653                'get-style-property/get-style-property'
1654            ],
1655            outlayerItemDefinition);
1656    } else {
1657        // browser global
1658        window.Outlayer = {};
1659        window.Outlayer.Item = outlayerItemDefinition(
1660            window.EventEmitter,
1661            window.getSize,
1662            window.getStyleProperty
1663        );
1664    }
1665
1666})(window);
1667
1668/*!
1669 * Outlayer v1.2.0
1670 * the brains and guts of a layout library
1671 * MIT license
1672 */
1673
1674(function(window) {
1675
1676
1677
1678    // ----- vars ----- //
1679
1680    var document = window.document;
1681    var console = window.console;
1682    var jQuery = window.jQuery;
1683
1684    var noop = function() {};
1685
1686    // -------------------------- helpers -------------------------- //
1687
1688    // extend objects
1689    function extend(a, b) {
1690        for (var prop in b) {
1691            a[prop] = b[prop];
1692        }
1693        return a;
1694    }
1695
1696
1697    var objToString = Object.prototype.toString;
1698
1699    function isArray(obj) {
1700        return objToString.call(obj) === '[object Array]';
1701    }
1702
1703    // turn element or nodeList into an array
1704    function makeArray(obj) {
1705        var ary = [];
1706        if (isArray(obj)) {
1707            // use object if already an array
1708            ary = obj;
1709        } else if (obj && typeof obj.length === 'number') {
1710            // convert nodeList to array
1711            for (var i = 0, len = obj.length; i < len; i++) {
1712                ary.push(obj[i]);
1713            }
1714        } else {
1715            // array of single index
1716            ary.push(obj);
1717        }
1718        return ary;
1719    }
1720
1721    // http://stackoverflow.com/a/384380/182183
1722    var isElement = (typeof HTMLElement === 'object') ?
1723            function isElementDOM2(obj) {
1724                return obj instanceof HTMLElement;
1725        } :
1726            function isElementQuirky(obj) {
1727                return obj && typeof obj === 'object' &&
1728                    obj.nodeType === 1 && typeof obj.nodeName === 'string';
1729        };
1730
1731    // index of helper cause IE8
1732    var indexOf = Array.prototype.indexOf ? function(ary, obj) {
1733            return ary.indexOf(obj);
1734        } : function(ary, obj) {
1735            for (var i = 0, len = ary.length; i < len; i++) {
1736                if (ary[i] === obj) {
1737                    return i;
1738                }
1739            }
1740            return -1;
1741        };
1742
1743    function removeFrom(obj, ary) {
1744        var index = indexOf(ary, obj);
1745        if (index !== -1) {
1746            ary.splice(index, 1);
1747        }
1748    }
1749
1750    // http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
1751    function toDashed(str) {
1752        return str.replace(/(.)([A-Z])/g, function(match, $1, $2) {
1753            return $1 + '-' + $2;
1754        }).toLowerCase();
1755    }
1756
1757
1758    function outlayerDefinition(eventie, docReady, EventEmitter, getSize, matchesSelector, Item) {
1759
1760        // -------------------------- Outlayer -------------------------- //
1761
1762        // globally unique identifiers
1763        var GUID = 0;
1764        // internal store of all Outlayer intances
1765        var instances = {};
1766
1767
1768        /**
1769         * @param {Element, String} element
1770         * @param {Object} options
1771         * @constructor
1772         */
1773        function Outlayer(element, options) {
1774            // use element as selector string
1775            if (typeof element === 'string') {
1776                element = document.querySelector(element);
1777            }
1778
1779            // bail out if not proper element
1780            if (!element || !isElement(element)) {
1781                if (console) {
1782                    console.error('Bad ' + this.constructor.namespace + ' element: ' + element);
1783                }
1784                return;
1785            }
1786
1787            this.element = element;
1788
1789            // options
1790            this.options = extend({}, this.constructor.defaults);
1791            this.option(options);
1792
1793            // add id for Outlayer.getFromElement
1794            var id = ++GUID;
1795            this.element.outlayerGUID = id; // expando
1796            instances[id] = this; // associate via id
1797
1798            // kick it off
1799            this._create();
1800
1801            if (this.options.isInitLayout) {
1802                this.layout();
1803            }
1804        }
1805
1806        // settings are for internal use only
1807        Outlayer.namespace = 'outlayer';
1808        Outlayer.Item = Item;
1809
1810        // default options
1811        Outlayer.defaults = {
1812            containerStyle: {
1813                position: 'relative'
1814            },
1815            isInitLayout: true,
1816            isOriginLeft: true,
1817            isOriginTop: true,
1818            isResizeBound: true,
1819            isResizingContainer: true,
1820            // item options
1821            transitionDuration: '0.4s',
1822            hiddenStyle: {
1823                opacity: 0,
1824                transform: 'scale(0.001)'
1825            },
1826            visibleStyle: {
1827                opacity: 1,
1828                transform: 'scale(1)'
1829            }
1830        };
1831
1832        // inherit EventEmitter
1833        extend(Outlayer.prototype, EventEmitter.prototype);
1834
1835        /**
1836         * set options
1837         * @param {Object} opts
1838         */
1839        Outlayer.prototype.option = function(opts) {
1840            extend(this.options, opts);
1841        };
1842
1843        Outlayer.prototype._create = function() {
1844            // get items from children
1845            this.reloadItems();
1846            // elements that affect layout, but are not laid out
1847            this.stamps = [];
1848            this.stamp(this.options.stamp);
1849            // set container style
1850            extend(this.element.style, this.options.containerStyle);
1851
1852            // bind resize method
1853            if (this.options.isResizeBound) {
1854                this.bindResize();
1855            }
1856        };
1857
1858        // goes through all children again and gets bricks in proper order
1859        Outlayer.prototype.reloadItems = function() {
1860            // collection of item elements
1861            this.items = this._itemize(this.element.children);
1862        };
1863
1864
1865        /**
1866         * turn elements into Outlayer.Items to be used in layout
1867         * @param {Array or NodeList or HTMLElement} elems
1868         * @returns {Array} items - collection of new Outlayer Items
1869         */
1870        Outlayer.prototype._itemize = function(elems) {
1871
1872            var itemElems = this._filterFindItemElements(elems);
1873            var Item = this.constructor.Item;
1874
1875            // create new Outlayer Items for collection
1876            var items = [];
1877            for (var i = 0, len = itemElems.length; i < len; i++) {
1878                var elem = itemElems[i];
1879                var item = new Item(elem, this);
1880                items.push(item);
1881            }
1882
1883            return items;
1884        };
1885
1886        /**
1887         * get item elements to be used in layout
1888         * @param {Array or NodeList or HTMLElement} elems
1889         * @returns {Array} items - item elements
1890         */
1891        Outlayer.prototype._filterFindItemElements = function(elems) {
1892            // make array of elems
1893            elems = makeArray(elems);
1894            var itemSelector = this.options.itemSelector;
1895            var itemElems = [];
1896
1897            for (var i = 0, len = elems.length; i < len; i++) {
1898                var elem = elems[i];
1899                // check that elem is an actual element
1900                if (!isElement(elem)) {
1901                    continue;
1902                }
1903                // filter & find items if we have an item selector
1904                if (itemSelector) {
1905                    // filter siblings
1906                    if (matchesSelector(elem, itemSelector)) {
1907                        itemElems.push(elem);
1908                    }
1909                    // find children
1910                    var childElems = elem.querySelectorAll(itemSelector);
1911                    // concat childElems to filterFound array
1912                    for (var j = 0, jLen = childElems.length; j < jLen; j++) {
1913                        itemElems.push(childElems[j]);
1914                    }
1915                } else {
1916                    itemElems.push(elem);
1917                }
1918            }
1919
1920            return itemElems;
1921        };
1922
1923        /**
1924         * getter method for getting item elements
1925         * @returns {Array} elems - collection of item elements
1926         */
1927        Outlayer.prototype.getItemElements = function() {
1928            var elems = [];
1929            for (var i = 0, len = this.items.length; i < len; i++) {
1930                elems.push(this.items[i].element);
1931            }
1932            return elems;
1933        };
1934
1935        // ----- init & layout ----- //
1936
1937        /**
1938         * lays out all items
1939         */
1940        Outlayer.prototype.layout = function() {
1941            this._resetLayout();
1942            this._manageStamps();
1943
1944            // don't animate first layout
1945            var isInstant = this.options.isLayoutInstant !== undefined ?
1946                this.options.isLayoutInstant : !this._isLayoutInited;
1947            this.layoutItems(this.items, isInstant);
1948
1949            // flag for initalized
1950            this._isLayoutInited = true;
1951        };
1952
1953        // _init is alias for layout
1954        Outlayer.prototype._init = Outlayer.prototype.layout;
1955
1956        /**
1957         * logic before any new layout
1958         */
1959        Outlayer.prototype._resetLayout = function() {
1960            this.getSize();
1961        };
1962
1963
1964        Outlayer.prototype.getSize = function() {
1965            this.size = getSize(this.element);
1966        };
1967
1968        /**
1969         * get measurement from option, for columnWidth, rowHeight, gutter
1970         * if option is String -> get element from selector string, & get size of element
1971         * if option is Element -> get size of element
1972         * else use option as a number
1973         *
1974         * @param {String} measurement
1975         * @param {String} size - width or height
1976         * @private
1977         */
1978        Outlayer.prototype._getMeasurement = function(measurement, size) {
1979            var option = this.options[measurement];
1980            var elem;
1981            if (!option) {
1982                // default to 0
1983                this[measurement] = 0;
1984            } else {
1985                // use option as an element
1986                if (typeof option === 'string') {
1987                    elem = this.element.querySelector(option);
1988                } else if (isElement(option)) {
1989                    elem = option;
1990                }
1991                // use size of element, if element
1992                this[measurement] = elem ? getSize(elem)[size] : option;
1993            }
1994        };
1995
1996        /**
1997         * layout a collection of item elements
1998         * @api public
1999         */
2000        Outlayer.prototype.layoutItems = function(items, isInstant) {
2001            items = this._getItemsForLayout(items);
2002
2003            this._layoutItems(items, isInstant);
2004
2005            this._postLayout();
2006        };
2007
2008        /**
2009         * get the items to be laid out
2010         * you may want to skip over some items
2011         * @param {Array} items
2012         * @returns {Array} items
2013         */
2014        Outlayer.prototype._getItemsForLayout = function(items) {
2015            var layoutItems = [];
2016            for (var i = 0, len = items.length; i < len; i++) {
2017                var item = items[i];
2018                if (!item.isIgnored) {
2019                    layoutItems.push(item);
2020                }
2021            }
2022            return layoutItems;
2023        };
2024
2025        /**
2026         * layout items
2027         * @param {Array} items
2028         * @param {Boolean} isInstant
2029         */
2030        Outlayer.prototype._layoutItems = function(items, isInstant) {
2031            var _this = this;
2032
2033            function onItemsLayout() {
2034                _this.emitEvent('layoutComplete', [_this, items]);
2035            }
2036
2037            if (!items || !items.length) {
2038                // no items, emit event with empty array
2039                onItemsLayout();
2040                return;
2041            }
2042
2043            // emit layoutComplete when done
2044            this._itemsOn(items, 'layout', onItemsLayout);
2045
2046            var queue = [];
2047
2048            for (var i = 0, len = items.length; i < len; i++) {
2049                var item = items[i];
2050                // get x/y object from method
2051                var position = this._getItemLayoutPosition(item);
2052                // enqueue
2053                position.item = item;
2054                position.isInstant = isInstant || item.isLayoutInstant;
2055                queue.push(position);
2056            }
2057
2058            this._processLayoutQueue(queue);
2059        };
2060
2061        /**
2062         * get item layout position
2063         * @param {Outlayer.Item} item
2064         * @returns {Object} x and y position
2065         */
2066        Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) {
2067            return {
2068                x: 0,
2069                y: 0
2070            };
2071        };
2072
2073        /**
2074         * iterate over array and position each item
2075         * Reason being - separating this logic prevents 'layout invalidation'
2076         * thx @paul_irish
2077         * @param {Array} queue
2078         */
2079        Outlayer.prototype._processLayoutQueue = function(queue) {
2080            for (var i = 0, len = queue.length; i < len; i++) {
2081                var obj = queue[i];
2082                this._positionItem(obj.item, obj.x, obj.y, obj.isInstant);
2083            }
2084        };
2085
2086        /**
2087         * Sets position of item in DOM
2088         * @param {Outlayer.Item} item
2089         * @param {Number} x - horizontal position
2090         * @param {Number} y - vertical position
2091         * @param {Boolean} isInstant - disables transitions
2092         */
2093        Outlayer.prototype._positionItem = function(item, x, y, isInstant) {
2094            if (isInstant) {
2095                // if not transition, just set CSS
2096                item.goTo(x, y);
2097            } else {
2098                item.moveTo(x, y);
2099            }
2100        };
2101
2102        /**
2103         * Any logic you want to do after each layout,
2104         * i.e. size the container
2105         */
2106        Outlayer.prototype._postLayout = function() {
2107            this.resizeContainer();
2108        };
2109
2110        Outlayer.prototype.resizeContainer = function() {
2111            if (!this.options.isResizingContainer) {
2112                return;
2113            }
2114            var size = this._getContainerSize();
2115            if (size) {
2116                this._setContainerMeasure(size.width, true);
2117                this._setContainerMeasure(size.height, false);
2118            }
2119        };
2120
2121        /**
2122         * Sets width or height of container if returned
2123         * @returns {Object} size
2124         *   @param {Number} width
2125         *   @param {Number} height
2126         */
2127        Outlayer.prototype._getContainerSize = noop;
2128
2129        /**
2130         * @param {Number} measure - size of width or height
2131         * @param {Boolean} isWidth
2132         */
2133        Outlayer.prototype._setContainerMeasure = function(measure, isWidth) {
2134            if (measure === undefined) {
2135                return;
2136            }
2137
2138            var elemSize = this.size;
2139            // add padding and border width if border box
2140            if (elemSize.isBorderBox) {
2141                measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
2142                    elemSize.borderLeftWidth + elemSize.borderRightWidth :
2143                    elemSize.paddingBottom + elemSize.paddingTop +
2144                    elemSize.borderTopWidth + elemSize.borderBottomWidth;
2145            }
2146
2147            measure = Math.max(measure, 0);
2148            this.element.style[isWidth ? 'width' : 'height'] = measure + 'px';
2149        };
2150
2151        /**
2152         * trigger a callback for a collection of items events
2153         * @param {Array} items - Outlayer.Items
2154         * @param {String} eventName
2155         * @param {Function} callback
2156         */
2157        Outlayer.prototype._itemsOn = function(items, eventName, callback) {
2158            var doneCount = 0;
2159            var count = items.length;
2160            // event callback
2161            var _this = this;
2162
2163            function tick() {
2164                doneCount++;
2165                if (doneCount === count) {
2166                    callback.call(_this);
2167                }
2168                return true; // bind once
2169            }
2170            // bind callback
2171            for (var i = 0, len = items.length; i < len; i++) {
2172                var item = items[i];
2173                item.on(eventName, tick);
2174            }
2175        };
2176
2177        // -------------------------- ignore & stamps -------------------------- //
2178
2179
2180        /**
2181         * keep item in collection, but do not lay it out
2182         * ignored items do not get skipped in layout
2183         * @param {Element} elem
2184         */
2185        Outlayer.prototype.ignore = function(elem) {
2186            var item = this.getItem(elem);
2187            if (item) {
2188                item.isIgnored = true;
2189            }
2190        };
2191
2192        /**
2193         * return item to layout collection
2194         * @param {Element} elem
2195         */
2196        Outlayer.prototype.unignore = function(elem) {
2197            var item = this.getItem(elem);
2198            if (item) {
2199                delete item.isIgnored;
2200            }
2201        };
2202
2203        /**
2204         * adds elements to stamps
2205         * @param {NodeList, Array, Element, or String} elems
2206         */
2207        Outlayer.prototype.stamp = function(elems) {
2208            elems = this._find(elems);
2209            if (!elems) {
2210                return;
2211            }
2212
2213            this.stamps = this.stamps.concat(elems);
2214            // ignore
2215            for (var i = 0, len = elems.length; i < len; i++) {
2216                var elem = elems[i];
2217                this.ignore(elem);
2218            }
2219        };
2220
2221        /**
2222         * removes elements to stamps
2223         * @param {NodeList, Array, or Element} elems
2224         */
2225        Outlayer.prototype.unstamp = function(elems) {
2226            elems = this._find(elems);
2227            if (!elems) {
2228                return;
2229            }
2230
2231            for (var i = 0, len = elems.length; i < len; i++) {
2232                var elem = elems[i];
2233                // filter out removed stamp elements
2234                removeFrom(elem, this.stamps);
2235                this.unignore(elem);
2236            }
2237
2238        };
2239
2240        /**
2241         * finds child elements
2242         * @param {NodeList, Array, Element, or String} elems
2243         * @returns {Array} elems
2244         */
2245        Outlayer.prototype._find = function(elems) {
2246            if (!elems) {
2247                return;
2248            }
2249            // if string, use argument as selector string
2250            if (typeof elems === 'string') {
2251                elems = this.element.querySelectorAll(elems);
2252            }
2253            elems = makeArray(elems);
2254            return elems;
2255        };
2256
2257        Outlayer.prototype._manageStamps = function() {
2258            if (!this.stamps || !this.stamps.length) {
2259                return;
2260            }
2261
2262            this._getBoundingRect();
2263
2264            for (var i = 0, len = this.stamps.length; i < len; i++) {
2265                var stamp = this.stamps[i];
2266                this._manageStamp(stamp);
2267            }
2268        };
2269
2270        // update boundingLeft / Top
2271        Outlayer.prototype._getBoundingRect = function() {
2272            // get bounding rect for container element
2273            var boundingRect = this.element.getBoundingClientRect();
2274            var size = this.size;
2275            this._boundingRect = {
2276                left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
2277                top: boundingRect.top + size.paddingTop + size.borderTopWidth,
2278                right: boundingRect.right - (size.paddingRight + size.borderRightWidth),
2279                bottom: boundingRect.bottom - (size.paddingBottom + size.borderBottomWidth)
2280            };
2281        };
2282
2283        /**
2284         * @param {Element} stamp
2285         **/
2286        Outlayer.prototype._manageStamp = noop;
2287
2288        /**
2289         * get x/y position of element relative to container element
2290         * @param {Element} elem
2291         * @returns {Object} offset - has left, top, right, bottom
2292         */
2293        Outlayer.prototype._getElementOffset = function(elem) {
2294            var boundingRect = elem.getBoundingClientRect();
2295            var thisRect = this._boundingRect;
2296            var size = getSize(elem);
2297            var offset = {
2298                left: boundingRect.left - thisRect.left - size.marginLeft,
2299                top: boundingRect.top - thisRect.top - size.marginTop,
2300                right: thisRect.right - boundingRect.right - size.marginRight,
2301                bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
2302            };
2303            return offset;
2304        };
2305
2306        // -------------------------- resize -------------------------- //
2307
2308        // enable event handlers for listeners
2309        // i.e. resize -> onresize
2310        Outlayer.prototype.handleEvent = function(event) {
2311            var method = 'on' + event.type;
2312            if (this[method]) {
2313                this[method](event);
2314            }
2315        };
2316
2317        /**
2318         * Bind layout to window resizing
2319         */
2320        Outlayer.prototype.bindResize = function() {
2321            // bind just one listener
2322            if (this.isResizeBound) {
2323                return;
2324            }
2325            eventie.bind(window, 'resize', this);
2326            this.isResizeBound = true;
2327        };
2328
2329        /**
2330         * Unbind layout to window resizing
2331         */
2332        Outlayer.prototype.unbindResize = function() {
2333            if (this.isResizeBound) {
2334                eventie.unbind(window, 'resize', this);
2335            }
2336            this.isResizeBound = false;
2337        };
2338
2339        // original debounce by John Hann
2340        // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
2341
2342        // this fires every resize
2343        Outlayer.prototype.onresize = function() {
2344            if (this.resizeTimeout) {
2345                clearTimeout(this.resizeTimeout);
2346            }
2347
2348            var _this = this;
2349
2350            function delayed() {
2351                _this.resize();
2352                delete _this.resizeTimeout;
2353            }
2354
2355            this.resizeTimeout = setTimeout(delayed, 100);
2356        };
2357
2358        // debounced, layout on resize
2359        Outlayer.prototype.resize = function() {
2360            // don't trigger if size did not change
2361            // or if resize was unbound. See #9
2362
2363            if (!this.isResizeBound || !this.needsResizeLayout()) {
2364                return;
2365            }
2366
2367            this.layout();
2368        };
2369
2370        /**
2371         * check if layout is needed post layout
2372         * @returns Boolean
2373         */
2374        Outlayer.prototype.needsResizeLayout = function() {
2375            var size = getSize(this.element);
2376            // check that this.size and size are there
2377            // IE8 triggers resize on body size change, so they might not be
2378            var hasSizes = this.size && size;
2379            return hasSizes && size.innerWidth !== this.size.innerWidth;
2380        };
2381
2382        // -------------------------- methods -------------------------- //
2383
2384        /**
2385         * add items to Outlayer instance
2386         * @param {Array or NodeList or Element} elems
2387         * @returns {Array} items - Outlayer.Items
2388         **/
2389        Outlayer.prototype.addItems = function(elems) {
2390            var items = this._itemize(elems);
2391            // add items to collection
2392            if (items.length) {
2393                this.items = this.items.concat(items);
2394            }
2395            return items;
2396        };
2397
2398        /**
2399         * Layout newly-appended item elements
2400         * @param {Array or NodeList or Element} elems
2401         */
2402        Outlayer.prototype.appended = function(elems) {
2403            var items = this.addItems(elems);
2404            if (!items.length) {
2405                return;
2406            }
2407            // layout and reveal just the new items
2408            this.layoutItems(items, true);
2409            this.reveal(items);
2410        };
2411
2412        /**
2413         * Layout prepended elements
2414         * @param {Array or NodeList or Element} elems
2415         */
2416        Outlayer.prototype.prepended = function(elems) {
2417            var items = this._itemize(elems);
2418            if (!items.length) {
2419                return;
2420            }
2421            // add items to beginning of collection
2422            var previousItems = this.items.slice(0);
2423            this.items = items.concat(previousItems);
2424            // start new layout
2425            this._resetLayout();
2426            this._manageStamps();
2427            // layout new stuff without transition
2428            this.layoutItems(items, true);
2429            this.reveal(items);
2430            // layout previous items
2431            this.layoutItems(previousItems);
2432        };
2433
2434        /**
2435         * reveal a collection of items
2436         * @param {Array of Outlayer.Items} items
2437         */
2438        Outlayer.prototype.reveal = function(items) {
2439            var len = items && items.length;
2440            if (!len) {
2441                return;
2442            }
2443            for (var i = 0; i < len; i++) {
2444                var item = items[i];
2445                item.reveal();
2446            }
2447        };
2448
2449        /**
2450         * hide a collection of items
2451         * @param {Array of Outlayer.Items} items
2452         */
2453        Outlayer.prototype.hide = function(items) {
2454            var len = items && items.length;
2455            if (!len) {
2456                return;
2457            }
2458            for (var i = 0; i < len; i++) {
2459                var item = items[i];
2460                item.hide();
2461            }
2462        };
2463
2464        /**
2465         * get Outlayer.Item, given an Element
2466         * @param {Element} elem
2467         * @param {Function} callback
2468         * @returns {Outlayer.Item} item
2469         */
2470        Outlayer.prototype.getItem = function(elem) {
2471            // loop through items to get the one that matches
2472            for (var i = 0, len = this.items.length; i < len; i++) {
2473                var item = this.items[i];
2474                if (item.element === elem) {
2475                    // return item
2476                    return item;
2477                }
2478            }
2479        };
2480
2481        /**
2482         * get collection of Outlayer.Items, given Elements
2483         * @param {Array} elems
2484         * @returns {Array} items - Outlayer.Items
2485         */
2486        Outlayer.prototype.getItems = function(elems) {
2487            if (!elems || !elems.length) {
2488                return;
2489            }
2490            var items = [];
2491            for (var i = 0, len = elems.length; i < len; i++) {
2492                var elem = elems[i];
2493                var item = this.getItem(elem);
2494                if (item) {
2495                    items.push(item);
2496                }
2497            }
2498
2499            return items;
2500        };
2501
2502        /**
2503         * remove element(s) from instance and DOM
2504         * @param {Array or NodeList or Element} elems
2505         */
2506        Outlayer.prototype.remove = function(elems) {
2507            elems = makeArray(elems);
2508
2509            var removeItems = this.getItems(elems);
2510            // bail if no items to remove
2511            if (!removeItems || !removeItems.length) {
2512                return;
2513            }
2514
2515            this._itemsOn(removeItems, 'remove', function() {
2516                this.emitEvent('removeComplete', [this, removeItems]);
2517            });
2518
2519            for (var i = 0, len = removeItems.length; i < len; i++) {
2520                var item = removeItems[i];
2521                item.remove();
2522                // remove item from collection
2523                removeFrom(item, this.items);
2524            }
2525        };
2526
2527        // ----- destroy ----- //
2528
2529        // remove and disable Outlayer instance
2530        Outlayer.prototype.destroy = function() {
2531            // clean up dynamic styles
2532            var style = this.element.style;
2533            style.height = '';
2534            style.position = '';
2535            style.width = '';
2536            // destroy items
2537            for (var i = 0, len = this.items.length; i < len; i++) {
2538                var item = this.items[i];
2539                item.destroy();
2540            }
2541
2542            this.unbindResize();
2543
2544            delete this.element.outlayerGUID;
2545            // remove data for jQuery
2546            if (jQuery) {
2547                jQuery.removeData(this.element, this.constructor.namespace);
2548            }
2549
2550        };
2551
2552        // -------------------------- data -------------------------- //
2553
2554        /**
2555         * get Outlayer instance from element
2556         * @param {Element} elem
2557         * @returns {Outlayer}
2558         */
2559        Outlayer.data = function(elem) {
2560            var id = elem && elem.outlayerGUID;
2561            return id && instances[id];
2562        };
2563
2564
2565        // -------------------------- create Outlayer class -------------------------- //
2566
2567        /**
2568         * create a layout class
2569         * @param {String} namespace
2570         */
2571        Outlayer.create = function(namespace, options) {
2572            // sub-class Outlayer
2573            function Layout() {
2574                Outlayer.apply(this, arguments);
2575            }
2576            // inherit Outlayer prototype, use Object.create if there
2577            if (Object.create) {
2578                Layout.prototype = Object.create(Outlayer.prototype);
2579            } else {
2580                extend(Layout.prototype, Outlayer.prototype);
2581            }
2582            // set contructor, used for namespace and Item
2583            Layout.prototype.constructor = Layout;
2584
2585            Layout.defaults = extend({}, Outlayer.defaults);
2586            // apply new options
2587            extend(Layout.defaults, options);
2588            // keep prototype.settings for backwards compatibility (Packery v1.2.0)
2589            Layout.prototype.settings = {};
2590
2591            Layout.namespace = namespace;
2592
2593            Layout.data = Outlayer.data;
2594
2595            // sub-class Item
2596            Layout.Item = function LayoutItem() {
2597                Item.apply(this, arguments);
2598            };
2599
2600            Layout.Item.prototype = new Item();
2601
2602            // -------------------------- declarative -------------------------- //
2603
2604            /**
2605             * allow user to initialize Outlayer via .js-namespace class
2606             * options are parsed from data-namespace-option attribute
2607             */
2608            docReady(function() {
2609                var dashedNamespace = toDashed(namespace);
2610                var elems = document.querySelectorAll('.js-' + dashedNamespace);
2611                var dataAttr = 'data-' + dashedNamespace + '-options';
2612
2613                for (var i = 0, len = elems.length; i < len; i++) {
2614                    var elem = elems[i];
2615                    var attr = elem.getAttribute(dataAttr);
2616                    var options;
2617                    try {
2618                        options = attr && JSON.parse(attr);
2619                    } catch (error) {
2620                        // log error, do not initialize
2621                        if (console) {
2622                            console.error('Error parsing ' + dataAttr + ' on ' +
2623                                elem.nodeName.toLowerCase() + (elem.id ? '#' + elem.id : '') + ': ' +
2624                                error);
2625                        }
2626                        continue;
2627                    }
2628                    // initialize
2629                    var instance = new Layout(elem, options);
2630                    // make available via $().data('layoutname')
2631                    if (jQuery) {
2632                        jQuery.data(elem, namespace, instance);
2633                    }
2634                }
2635            });
2636
2637            // -------------------------- jQuery bridge -------------------------- //
2638
2639            // make into jQuery plugin
2640            if (jQuery && jQuery.bridget) {
2641                jQuery.bridget(namespace, Layout);
2642            }
2643
2644            return Layout;
2645        };
2646
2647        // ----- fin ----- //
2648
2649        // back in global
2650        Outlayer.Item = Item;
2651
2652        return Outlayer;
2653
2654    }
2655
2656    // -------------------------- transport -------------------------- //
2657
2658    if (typeof define === 'function' && define.amd) {
2659        // AMD
2660        define('outlayer/outlayer', [
2661                'eventie/eventie',
2662                'doc-ready/doc-ready',
2663                'eventEmitter/EventEmitter',
2664                'get-size/get-size',
2665                'matches-selector/matches-selector',
2666                './item'
2667            ],
2668            outlayerDefinition);
2669    } else {
2670        // browser global
2671        window.Outlayer = outlayerDefinition(
2672            window.eventie,
2673            window.docReady,
2674            window.EventEmitter,
2675            window.getSize,
2676            window.matchesSelector,
2677            window.Outlayer.Item
2678        );
2679    }
2680
2681})(window);
2682
2683/*!
2684 * Masonry v3.1.5
2685 * Cascading grid layout library
2686 * http://masonry.desandro.com
2687 * MIT License
2688 * by David DeSandro
2689 */
2690
2691(function(window) {
2692
2693
2694
2695    // -------------------------- helpers -------------------------- //
2696
2697    var indexOf = Array.prototype.indexOf ?
2698            function(items, value) {
2699                return items.indexOf(value);
2700        } :
2701            function(items, value) {
2702                for (var i = 0, len = items.length; i < len; i++) {
2703                    var item = items[i];
2704                    if (item === value) {
2705                        return i;
2706                    }
2707                }
2708                return -1;
2709        };
2710
2711    // -------------------------- masonryDefinition -------------------------- //
2712
2713    // used for AMD definition and requires
2714    function masonryDefinition(Outlayer, getSize) {
2715        // create an Outlayer layout class
2716        var Masonry = Outlayer.create('masonry');
2717
2718        Masonry.prototype._resetLayout = function() {
2719            this.getSize();
2720            this._getMeasurement('columnWidth', 'outerWidth');
2721            this._getMeasurement('gutter', 'outerWidth');
2722            this.measureColumns();
2723
2724            // reset column Y
2725            var i = this.cols;
2726            this.colYs = [];
2727            while (i--) {
2728                this.colYs.push(0);
2729            }
2730
2731            this.maxY = 0;
2732        };
2733
2734        Masonry.prototype.measureColumns = function() {
2735            this.getContainerWidth();
2736            // if columnWidth is 0, default to outerWidth of first item
2737            if (!this.columnWidth) {
2738                var firstItem = this.items[0];
2739                var firstItemElem = firstItem && firstItem.element;
2740                // columnWidth fall back to item of first element
2741                this.columnWidth = firstItemElem && getSize(firstItemElem).outerWidth ||
2742                // if first elem has no width, default to size of container
2743                this.containerWidth;
2744            }
2745
2746            this.columnWidth += this.gutter;
2747
2748            this.cols = Math.floor((this.containerWidth + this.gutter) / this.columnWidth);
2749            this.cols = Math.max(this.cols, 1);
2750        };
2751
2752        Masonry.prototype.getContainerWidth = function() {
2753            // container is parent if fit width
2754            var container = this.options.isFitWidth ? this.element.parentNode : this.element;
2755            // check that this.size and size are there
2756            // IE8 triggers resize on body size change, so they might not be
2757            var size = getSize(container);
2758            this.containerWidth = size && size.innerWidth;
2759        };
2760
2761        Masonry.prototype._getItemLayoutPosition = function(item) {
2762            item.getSize();
2763            // how many columns does this brick span
2764            var remainder = item.size.outerWidth % this.columnWidth;
2765            var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
2766            // round if off by 1 pixel, otherwise use ceil
2767            var colSpan = Math[mathMethod](item.size.outerWidth / this.columnWidth);
2768            colSpan = Math.min(colSpan, this.cols);
2769
2770            var colGroup = this._getColGroup(colSpan);
2771            // get the minimum Y value from the columns
2772            var minimumY = Math.min.apply(Math, colGroup);
2773            var shortColIndex = indexOf(colGroup, minimumY);
2774
2775            // position the brick
2776            var position = {
2777                x: this.columnWidth * shortColIndex,
2778                y: minimumY
2779            };
2780
2781            // apply setHeight to necessary columns
2782            var setHeight = minimumY + item.size.outerHeight;
2783            var setSpan = this.cols + 1 - colGroup.length;
2784            for (var i = 0; i < setSpan; i++) {
2785                this.colYs[shortColIndex + i] = setHeight;
2786            }
2787
2788            return position;
2789        };
2790
2791        /**
2792         * @param {Number} colSpan - number of columns the element spans
2793         * @returns {Array} colGroup
2794         */
2795        Masonry.prototype._getColGroup = function(colSpan) {
2796            if (colSpan < 2) {
2797                // if brick spans only one column, use all the column Ys
2798                return this.colYs;
2799            }
2800
2801            var colGroup = [];
2802            // how many different places could this brick fit horizontally
2803            var groupCount = this.cols + 1 - colSpan;
2804            // for each group potential horizontal position
2805            for (var i = 0; i < groupCount; i++) {
2806                // make an array of colY values for that one group
2807                var groupColYs = this.colYs.slice(i, i + colSpan);
2808                // and get the max value of the array
2809                colGroup[i] = Math.max.apply(Math, groupColYs);
2810            }
2811            return colGroup;
2812        };
2813
2814        Masonry.prototype._manageStamp = function(stamp) {
2815            var stampSize = getSize(stamp);
2816            var offset = this._getElementOffset(stamp);
2817            // get the columns that this stamp affects
2818            var firstX = this.options.isOriginLeft ? offset.left : offset.right;
2819            var lastX = firstX + stampSize.outerWidth;
2820            var firstCol = Math.floor(firstX / this.columnWidth);
2821            firstCol = Math.max(0, firstCol);
2822            var lastCol = Math.floor(lastX / this.columnWidth);
2823            // lastCol should not go over if multiple of columnWidth #425
2824            lastCol -= lastX % this.columnWidth ? 0 : 1;
2825            lastCol = Math.min(this.cols - 1, lastCol);
2826            // set colYs to bottom of the stamp
2827            var stampMaxY = (this.options.isOriginTop ? offset.top : offset.bottom) +
2828                stampSize.outerHeight;
2829            for (var i = firstCol; i <= lastCol; i++) {
2830                this.colYs[i] = Math.max(stampMaxY, this.colYs[i]);
2831            }
2832        };
2833
2834        Masonry.prototype._getContainerSize = function() {
2835            this.maxY = Math.max.apply(Math, this.colYs);
2836            var size = {
2837                height: this.maxY
2838            };
2839
2840            if (this.options.isFitWidth) {
2841                size.width = this._getContainerFitWidth();
2842            }
2843
2844            return size;
2845        };
2846
2847        Masonry.prototype._getContainerFitWidth = function() {
2848            var unusedCols = 0;
2849            // count unused columns
2850            var i = this.cols;
2851            while (--i) {
2852                if (this.colYs[i] !== 0) {
2853                    break;
2854                }
2855                unusedCols++;
2856            }
2857            // fit container to columns that have been used
2858            return (this.cols - unusedCols) * this.columnWidth - this.gutter;
2859        };
2860
2861        Masonry.prototype.needsResizeLayout = function() {
2862            var previousWidth = this.containerWidth;
2863            this.getContainerWidth();
2864            return previousWidth !== this.containerWidth;
2865        };
2866
2867        return Masonry;
2868    }
2869
2870    // -------------------------- transport -------------------------- //
2871
2872    if (typeof define === 'function' && define.amd) {
2873        // AMD
2874        define([
2875                'outlayer/outlayer',
2876                'get-size/get-size'
2877            ],
2878            masonryDefinition);
2879    } else {
2880        // browser global
2881        window.Masonry = masonryDefinition(
2882            window.Outlayer,
2883            window.getSize
2884        );
2885    }
2886
2887})(window);

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.