PageSourceSearch

https://uama.us/wp-content/plugins/bighearts-core/includes/elementor/assets/js/isotope.pkgd.min.js?ver=1.0.0

js uama.us collected 2026-10-01 23:46:22 UTC 109,973 bytes, 3,571 lines download raw bytes

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

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.