PageSourceSearch

https://europe-aliens.org/wp-content/themes/boomi/modules/blog/assets/js/isotope.pkgd.js?ver=7.1.2

js europe-aliens.org collected 2026-10-02 03:57:41 UTC 100,913 bytes, 3,557 lines download raw bytes

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

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.