PageSourceSearch

https://ifgroup.org/typo3conf/ext/ifgroup_template/Resources/Public/js/isotope.pkgd.js?1688478599

js ifgroup.org collected 2026-10-04 00:20:36 UTC 119,754 bytes, 4,045 lines download raw bytes

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

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.