PageSourceSearch

https://di-re.org/assets/di-re.org/wp-content/plugins/addons-for-v…/assets/js/isotope.pkgd-30f337fc57.js

js di-re.org collected 2026-10-05 18:38:19 UTC 105,965 bytes, 3,556 lines download raw bytes

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

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.