JAVASCRIPT   36

isotope.js

Guest on 12th August 2021 06:56:33 PM

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

Raw Paste


Login or Register to edit or fork this paste. It's free.