/*!

 * Isotope PACKAGED v3.0.6

 *

 * Licensed GPLv3 for open source use

 * or Isotope Commercial License for commercial use

 *

 * https://isotope.metafizzy.co

 * Copyright 2010-2018 Metafizzy

 */



/**

 * Bridget makes jQuery widgets

 * v2.0.1

 * MIT license

 */



/* jshint browser: true, strict: true, undef: true, unused: true */



( function( window, factory ) {

  // universal module definition

  /*jshint strict: false */ /* globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {

      return factory( window, jQuery );

    });

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory(

      window,

      require('jquery')

    );

  } else {

    // browser global

    window.jQueryBridget = factory(

      window,

      window.jQuery

    );

  }



}( window, function factory( window, jQuery ) {

'use strict';



// ----- utils ----- //



var arraySlice = Array.prototype.slice;



// helper function for logging errors

// $.error breaks jQuery chaining

var console = window.console;

var logError = typeof console == 'undefined' ? function() {} :

  function( message ) {

    console.error( message );

  };



// ----- jQueryBridget ----- //



function jQueryBridget( namespace, PluginClass, $ ) {

  $ = $ || jQuery || window.jQuery;

  if ( !$ ) {

    return;

  }



  // add option method -> $().plugin('option', {...})

  if ( !PluginClass.prototype.option ) {

    // option setter

    PluginClass.prototype.option = function( opts ) {

      // bail out if not an object

      if ( !$.isPlainObject( opts ) ){

        return;

      }

      this.options = $.extend( true, this.options, opts );

    };

  }



  // make jQuery plugin

  $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {

    if ( typeof arg0 == 'string' ) {

      // method call $().plugin( 'methodName', { options } )

      // shift arguments by 1

      var args = arraySlice.call( arguments, 1 );

      return methodCall( this, arg0, args );

    }

    // just $().plugin({ options })

    plainCall( this, arg0 );

    return this;

  };



  // $().plugin('methodName')

  function methodCall( $elems, methodName, args ) {

    var returnValue;

    var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';



    $elems.each( function( i, elem ) {

      // get instance

      var instance = $.data( elem, namespace );

      if ( !instance ) {

        logError( namespace + ' not initialized. Cannot call methods, i.e. ' +

          pluginMethodStr );

        return;

      }



      var method = instance[ methodName ];

      if ( !method || methodName.charAt(0) == '_' ) {

        logError( pluginMethodStr + ' is not a valid method' );

        return;

      }



      // apply method, get return value

      var value = method.apply( instance, args );

      // set return value if value is returned, use only first value

      returnValue = returnValue === undefined ? value : returnValue;

    });



    return returnValue !== undefined ? returnValue : $elems;

  }



  function plainCall( $elems, options ) {

    $elems.each( function( i, elem ) {

      var instance = $.data( elem, namespace );

      if ( instance ) {

        // set options & init

        instance.option( options );

        instance._init();

      } else {

        // initialize new instance

        instance = new PluginClass( elem, options );

        $.data( elem, namespace, instance );

      }

    });

  }



  updateJQuery( $ );



}



// ----- updateJQuery ----- //



// set $.bridget for v1 backwards compatibility

function updateJQuery( $ ) {

  if ( !$ || ( $ && $.bridget ) ) {

    return;

  }

  $.bridget = jQueryBridget;

}



updateJQuery( jQuery || window.jQuery );



// -----  ----- //



return jQueryBridget;



}));



/**

 * EvEmitter v1.1.0

 * Lil' event emitter

 * MIT License

 */



/* jshint unused: true, undef: true, strict: true */



( function( global, factory ) {

  // universal module definition

  /* jshint strict: false */ /* globals define, module, window */

  if ( typeof define == 'function' && define.amd ) {

    // AMD - RequireJS

    define( 'ev-emitter/ev-emitter',factory );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS - Browserify, Webpack

    module.exports = factory();

  } else {

    // Browser globals

    global.EvEmitter = factory();

  }



}( typeof window != 'undefined' ? window : this, function() {







function EvEmitter() {}



var proto = EvEmitter.prototype;



proto.on = function( eventName, listener ) {

  if ( !eventName || !listener ) {

    return;

  }

  // set events hash

  var events = this._events = this._events || {};

  // set listeners array

  var listeners = events[ eventName ] = events[ eventName ] || [];

  // only add once

  if ( listeners.indexOf( listener ) == -1 ) {

    listeners.push( listener );

  }



  return this;

};



proto.once = function( eventName, listener ) {

  if ( !eventName || !listener ) {

    return;

  }

  // add event

  this.on( eventName, listener );

  // set once flag

  // set onceEvents hash

  var onceEvents = this._onceEvents = this._onceEvents || {};

  // set onceListeners object

  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};

  // set flag

  onceListeners[ listener ] = true;



  return this;

};



proto.off = function( eventName, listener ) {

  var listeners = this._events && this._events[ eventName ];

  if ( !listeners || !listeners.length ) {

    return;

  }

  var index = listeners.indexOf( listener );

  if ( index != -1 ) {

    listeners.splice( index, 1 );

  }



  return this;

};



proto.emitEvent = function( eventName, args ) {

  var listeners = this._events && this._events[ eventName ];

  if ( !listeners || !listeners.length ) {

    return;

  }

  // copy over to avoid interference if .off() in listener

  listeners = listeners.slice(0);

  args = args || [];

  // once stuff

  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];



  for ( var i=0; i < listeners.length; i++ ) {

    var listener = listeners[i]

    var isOnce = onceListeners && onceListeners[ listener ];

    if ( isOnce ) {

      // remove listener

      // remove before trigger to prevent recursion

      this.off( eventName, listener );

      // unset once flag

      delete onceListeners[ listener ];

    }

    // trigger listener

    listener.apply( this, args );

  }



  return this;

};



proto.allOff = function() {

  delete this._events;

  delete this._onceEvents;

};



return EvEmitter;



}));



/*!

 * getSize v2.0.3

 * measure size of elements

 * MIT license

 */



/* jshint browser: true, strict: true, undef: true, unused: true */

/* globals console: false */



( function( window, factory ) {

  /* jshint strict: false */ /* globals define, module */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'get-size/get-size',factory );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory();

  } else {

    // browser global

    window.getSize = factory();

  }



})( window, function factory() {

'use strict';



// -------------------------- helpers -------------------------- //



// get a number from a string, not a percentage

function getStyleSize( value ) {

  var num = parseFloat( value );

  // not a percent like '100%', and a number

  var isValid = value.indexOf('%') == -1 && !isNaN( num );

  return isValid && num;

}



function noop() {}



var logError = typeof console == 'undefined' ? noop :

  function( message ) {

    console.error( message );

  };



// -------------------------- measurements -------------------------- //



var measurements = [

  'paddingLeft',

  'paddingRight',

  'paddingTop',

  'paddingBottom',

  'marginLeft',

  'marginRight',

  'marginTop',

  'marginBottom',

  'borderLeftWidth',

  'borderRightWidth',

  'borderTopWidth',

  'borderBottomWidth'

];



var measurementsLength = measurements.length;



function getZeroSize() {

  var size = {

    width: 0,

    height: 0,

    innerWidth: 0,

    innerHeight: 0,

    outerWidth: 0,

    outerHeight: 0

  };

  for ( var i=0; i < measurementsLength; i++ ) {

    var measurement = measurements[i];

    size[ measurement ] = 0;

  }

  return size;

}



// -------------------------- getStyle -------------------------- //



/**

 * getStyle, get style of element, check for Firefox bug

 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397

 */

function getStyle( elem ) {

  var style = getComputedStyle( elem );

  if ( !style ) {

    logError( 'Style returned ' + style +

      '. Are you running this code in a hidden iframe on Firefox? ' +

      'See https://bit.ly/getsizebug1' );

  }

  return style;

}



// -------------------------- setup -------------------------- //



var isSetup = false;



var isBoxSizeOuter;



/**

 * setup

 * check isBoxSizerOuter

 * do on first getSize() rather than on page load for Firefox bug

 */

function setup() {

  // setup once

  if ( isSetup ) {

    return;

  }

  isSetup = true;



  // -------------------------- box sizing -------------------------- //



  /**

   * Chrome & Safari measure the outer-width on style.width on border-box elems

   * IE11 & Firefox<29 measures the inner-width

   */

  var div = document.createElement('div');

  div.style.width = '200px';

  div.style.padding = '1px 2px 3px 4px';

  div.style.borderStyle = 'solid';

  div.style.borderWidth = '1px 2px 3px 4px';

  div.style.boxSizing = 'border-box';



  var body = document.body || document.documentElement;

  body.appendChild( div );

  var style = getStyle( div );

  // round value for browser zoom. desandro/masonry#928

  isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;

  getSize.isBoxSizeOuter = isBoxSizeOuter;



  body.removeChild( div );

}



// -------------------------- getSize -------------------------- //



function getSize( elem ) {

  setup();



  // use querySeletor if elem is string

  if ( typeof elem == 'string' ) {

    elem = document.querySelector( elem );

  }



  // do not proceed on non-objects

  if ( !elem || typeof elem != 'object' || !elem.nodeType ) {

    return;

  }



  var style = getStyle( elem );



  // if hidden, everything is 0

  if ( style.display == 'none' ) {

    return getZeroSize();

  }



  var size = {};

  size.width = elem.offsetWidth;

  size.height = elem.offsetHeight;



  var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';



  // get all measurements

  for ( var i=0; i < measurementsLength; i++ ) {

    var measurement = measurements[i];

    var value = style[ measurement ];

    var num = parseFloat( value );

    // any 'auto', 'medium' value will be 0

    size[ measurement ] = !isNaN( num ) ? num : 0;

  }



  var paddingWidth = size.paddingLeft + size.paddingRight;

  var paddingHeight = size.paddingTop + size.paddingBottom;

  var marginWidth = size.marginLeft + size.marginRight;

  var marginHeight = size.marginTop + size.marginBottom;

  var borderWidth = size.borderLeftWidth + size.borderRightWidth;

  var borderHeight = size.borderTopWidth + size.borderBottomWidth;



  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;



  // overwrite width and height if we can get it from style

  var styleWidth = getStyleSize( style.width );

  if ( styleWidth !== false ) {

    size.width = styleWidth +

      // add padding and border unless it's already including it

      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );

  }



  var styleHeight = getStyleSize( style.height );

  if ( styleHeight !== false ) {

    size.height = styleHeight +

      // add padding and border unless it's already including it

      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );

  }



  size.innerWidth = size.width - ( paddingWidth + borderWidth );

  size.innerHeight = size.height - ( paddingHeight + borderHeight );



  size.outerWidth = size.width + marginWidth;

  size.outerHeight = size.height + marginHeight;



  return size;

}



return getSize;



});



/**

 * matchesSelector v2.0.2

 * matchesSelector( element, '.selector' )

 * MIT license

 */



/*jshint browser: true, strict: true, undef: true, unused: true */



( function( window, factory ) {

  /*global define: false, module: false */

  'use strict';

  // universal module definition

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'desandro-matches-selector/matches-selector',factory );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory();

  } else {

    // browser global

    window.matchesSelector = factory();

  }



}( window, function factory() {

  'use strict';



  var matchesMethod = ( function() {

    var ElemProto = window.Element.prototype;

    // check for the standard method name first

    if ( ElemProto.matches ) {

      return 'matches';

    }

    // check un-prefixed

    if ( ElemProto.matchesSelector ) {

      return 'matchesSelector';

    }

    // check vendor prefixes

    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];



    for ( var i=0; i < prefixes.length; i++ ) {

      var prefix = prefixes[i];

      var method = prefix + 'MatchesSelector';

      if ( ElemProto[ method ] ) {

        return method;

      }

    }

  })();



  return function matchesSelector( elem, selector ) {

    return elem[ matchesMethod ]( selector );

  };



}));



/**

 * Fizzy UI utils v2.0.7

 * MIT license

 */



/*jshint browser: true, undef: true, unused: true, strict: true */



( function( window, factory ) {

  // universal module definition

  /*jshint strict: false */ /*globals define, module, require */



  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'fizzy-ui-utils/utils',[

      'desandro-matches-selector/matches-selector'

    ], function( matchesSelector ) {

      return factory( window, matchesSelector );

    });

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory(

      window,

      require('desandro-matches-selector')

    );

  } else {

    // browser global

    window.fizzyUIUtils = factory(

      window,

      window.matchesSelector

    );

  }



}( window, function factory( window, matchesSelector ) {







var utils = {};



// ----- extend ----- //



// extends objects

utils.extend = function( a, b ) {

  for ( var prop in b ) {

    a[ prop ] = b[ prop ];

  }

  return a;

};



// ----- modulo ----- //



utils.modulo = function( num, div ) {

  return ( ( num % div ) + div ) % div;

};



// ----- makeArray ----- //



var arraySlice = Array.prototype.slice;



// turn element or nodeList into an array

utils.makeArray = function( obj ) {

  if ( Array.isArray( obj ) ) {

    // use object if already an array

    return obj;

  }

  // return empty array if undefined or null. #6

  if ( obj === null || obj === undefined ) {

    return [];

  }



  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';

  if ( isArrayLike ) {

    // convert nodeList to array

    return arraySlice.call( obj );

  }



  // array of single index

  return [ obj ];

};



// ----- removeFrom ----- //



utils.removeFrom = function( ary, obj ) {

  var index = ary.indexOf( obj );

  if ( index != -1 ) {

    ary.splice( index, 1 );

  }

};



// ----- getParent ----- //



utils.getParent = function( elem, selector ) {

  while ( elem.parentNode && elem != document.body ) {

    elem = elem.parentNode;

    if ( matchesSelector( elem, selector ) ) {

      return elem;

    }

  }

};



// ----- getQueryElement ----- //



// use element as selector string

utils.getQueryElement = function( elem ) {

  if ( typeof elem == 'string' ) {

    return document.querySelector( elem );

  }

  return elem;

};



// ----- handleEvent ----- //



// enable .ontype to trigger from .addEventListener( elem, 'type' )

utils.handleEvent = function( event ) {

  var method = 'on' + event.type;

  if ( this[ method ] ) {

    this[ method ]( event );

  }

};



// ----- filterFindElements ----- //



utils.filterFindElements = function( elems, selector ) {

  // make array of elems

  elems = utils.makeArray( elems );

  var ffElems = [];



  elems.forEach( function( elem ) {

    // check that elem is an actual element

    if ( !( elem instanceof HTMLElement ) ) {

      return;

    }

    // add elem if no selector

    if ( !selector ) {

      ffElems.push( elem );

      return;

    }

    // filter & find items if we have a selector

    // filter

    if ( matchesSelector( elem, selector ) ) {

      ffElems.push( elem );

    }

    // find children

    var childElems = elem.querySelectorAll( selector );

    // concat childElems to filterFound array

    for ( var i=0; i < childElems.length; i++ ) {

      ffElems.push( childElems[i] );

    }

  });



  return ffElems;

};



// ----- debounceMethod ----- //



utils.debounceMethod = function( _class, methodName, threshold ) {

  threshold = threshold || 100;

  // original method

  var method = _class.prototype[ methodName ];

  var timeoutName = methodName + 'Timeout';



  _class.prototype[ methodName ] = function() {

    var timeout = this[ timeoutName ];

    clearTimeout( timeout );



    var args = arguments;

    var _this = this;

    this[ timeoutName ] = setTimeout( function() {

      method.apply( _this, args );

      delete _this[ timeoutName ];

    }, threshold );

  };

};



// ----- docReady ----- //



utils.docReady = function( callback ) {

  var readyState = document.readyState;

  if ( readyState == 'complete' || readyState == 'interactive' ) {

    // do async to allow for other scripts to run. metafizzy/flickity#441

    setTimeout( callback );

  } else {

    document.addEventListener( 'DOMContentLoaded', callback );

  }

};



// ----- htmlInit ----- //



// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/

utils.toDashed = function( str ) {

  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {

    return $1 + '-' + $2;

  }).toLowerCase();

};



var console = window.console;

/**

 * allow user to initialize classes via [data-namespace] or .js-namespace class

 * htmlInit( Widget, 'widgetName' )

 * options are parsed from data-namespace-options

 */

utils.htmlInit = function( WidgetClass, namespace ) {

  utils.docReady( function() {

    var dashedNamespace = utils.toDashed( namespace );

    var dataAttr = 'data-' + dashedNamespace;

    var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );

    var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );

    var elems = utils.makeArray( dataAttrElems )

      .concat( utils.makeArray( jsDashElems ) );

    var dataOptionsAttr = dataAttr + '-options';

    var jQuery = window.jQuery;



    elems.forEach( function( elem ) {

      var attr = elem.getAttribute( dataAttr ) ||

        elem.getAttribute( dataOptionsAttr );

      var options;

      try {

        options = attr && JSON.parse( attr );

      } catch ( error ) {

        // log error, do not initialize

        if ( console ) {

          console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +

          ': ' + error );

        }

        return;

      }

      // initialize

      var instance = new WidgetClass( elem, options );

      // make available via $().data('namespace')

      if ( jQuery ) {

        jQuery.data( elem, namespace, instance );

      }

    });



  });

};



// -----  ----- //



return utils;



}));



/**

 * Outlayer Item

 */



( function( window, factory ) {

  // universal module definition

  /* jshint strict: false */ /* globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD - RequireJS

    define( 'outlayer/item',[

        'ev-emitter/ev-emitter',

        'get-size/get-size'

      ],

      factory

    );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS - Browserify, Webpack

    module.exports = factory(

      require('ev-emitter'),

      require('get-size')

    );

  } else {

    // browser global

    window.Outlayer = {};

    window.Outlayer.Item = factory(

      window.EvEmitter,

      window.getSize

    );

  }



}( window, function factory( EvEmitter, getSize ) {

'use strict';



// ----- helpers ----- //



function isEmptyObj( obj ) {

  for ( var prop in obj ) {

    return false;

  }

  prop = null;

  return true;

}



// -------------------------- CSS3 support -------------------------- //





var docElemStyle = document.documentElement.style;



var transitionProperty = typeof docElemStyle.transition == 'string' ?

  'transition' : 'WebkitTransition';

var transformProperty = typeof docElemStyle.transform == 'string' ?

  'transform' : 'WebkitTransform';



var transitionEndEvent = {

  WebkitTransition: 'webkitTransitionEnd',

  transition: 'transitionend'

}[ transitionProperty ];



// cache all vendor properties that could have vendor prefix

var vendorProperties = {

  transform: transformProperty,

  transition: transitionProperty,

  transitionDuration: transitionProperty + 'Duration',

  transitionProperty: transitionProperty + 'Property',

  transitionDelay: transitionProperty + 'Delay'

};



// -------------------------- Item -------------------------- //



function Item( element, layout ) {

  if ( !element ) {

    return;

  }



  this.element = element;

  // parent layout class, i.e. Masonry, Isotope, or Packery

  this.layout = layout;

  this.position = {

    x: 0,

    y: 0

  };



  this._create();

}



// inherit EvEmitter

var proto = Item.prototype = Object.create( EvEmitter.prototype );

proto.constructor = Item;



proto._create = function() {

  // transition objects

  this._transn = {

    ingProperties: {},

    clean: {},

    onEnd: {}

  };



  this.css({

    position: 'absolute'

  });

};



// trigger specified handler for event type

proto.handleEvent = function( event ) {

  var method = 'on' + event.type;

  if ( this[ method ] ) {

    this[ method ]( event );

  }

};



proto.getSize = function() {

  this.size = getSize( this.element );

};



/**

 * apply CSS styles to element

 * @param {Object} style

 */

proto.css = function( style ) {

  var elemStyle = this.element.style;



  for ( var prop in style ) {

    // use vendor property if available

    var supportedProp = vendorProperties[ prop ] || prop;

    elemStyle[ supportedProp ] = style[ prop ];

  }

};



 // measure position, and sets it

proto.getPosition = function() {

  var style = getComputedStyle( this.element );

  var isOriginLeft = this.layout._getOption('originLeft');

  var isOriginTop = this.layout._getOption('originTop');

  var xValue = style[ isOriginLeft ? 'left' : 'right' ];

  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];

  var x = parseFloat( xValue );

  var y = parseFloat( yValue );

  // convert percent to pixels

  var layoutSize = this.layout.size;

  if ( xValue.indexOf('%') != -1 ) {

    x = ( x / 100 ) * layoutSize.width;

  }

  if ( yValue.indexOf('%') != -1 ) {

    y = ( y / 100 ) * layoutSize.height;

  }

  // clean up 'auto' or other non-integer values

  x = isNaN( x ) ? 0 : x;

  y = isNaN( y ) ? 0 : y;

  // remove padding from measurement

  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;

  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;



  this.position.x = x;

  this.position.y = y;

};



// set settled position, apply padding

proto.layoutPosition = function() {

  var layoutSize = this.layout.size;

  var style = {};

  var isOriginLeft = this.layout._getOption('originLeft');

  var isOriginTop = this.layout._getOption('originTop');



  // x

  var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';

  var xProperty = isOriginLeft ? 'left' : 'right';

  var xResetProperty = isOriginLeft ? 'right' : 'left';



  var x = this.position.x + layoutSize[ xPadding ];

  // set in percentage or pixels

  style[ xProperty ] = this.getXValue( x );

  // reset other property

  style[ xResetProperty ] = '';



  // y

  var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';

  var yProperty = isOriginTop ? 'top' : 'bottom';

  var yResetProperty = isOriginTop ? 'bottom' : 'top';



  var y = this.position.y + layoutSize[ yPadding ];

  // set in percentage or pixels

  style[ yProperty ] = this.getYValue( y );

  // reset other property

  style[ yResetProperty ] = '';



  this.css( style );

  this.emitEvent( 'layout', [ this ] );

};



proto.getXValue = function( x ) {

  var isHorizontal = this.layout._getOption('horizontal');

  return this.layout.options.percentPosition && !isHorizontal ?

    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';

};



proto.getYValue = function( y ) {

  var isHorizontal = this.layout._getOption('horizontal');

  return this.layout.options.percentPosition && isHorizontal ?

    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';

};



proto._transitionTo = function( x, y ) {

  this.getPosition();

  // get current x & y from top/left

  var curX = this.position.x;

  var curY = this.position.y;



  var didNotMove = x == this.position.x && y == this.position.y;



  // save end position

  this.setPosition( x, y );



  // if did not move and not transitioning, just go to layout

  if ( didNotMove && !this.isTransitioning ) {

    this.layoutPosition();

    return;

  }



  var transX = x - curX;

  var transY = y - curY;

  var transitionStyle = {};

  transitionStyle.transform = this.getTranslate( transX, transY );



  this.transition({

    to: transitionStyle,

    onTransitionEnd: {

      transform: this.layoutPosition

    },

    isCleaning: true

  });

};



proto.getTranslate = function( x, y ) {

  // flip cooridinates if origin on right or bottom

  var isOriginLeft = this.layout._getOption('originLeft');

  var isOriginTop = this.layout._getOption('originTop');

  x = isOriginLeft ? x : -x;

  y = isOriginTop ? y : -y;

  return 'translate3d(' + x + 'px, ' + y + 'px, 0)';

};



// non transition + transform support

proto.goTo = function( x, y ) {

  this.setPosition( x, y );

  this.layoutPosition();

};



proto.moveTo = proto._transitionTo;



proto.setPosition = function( x, y ) {

  this.position.x = parseFloat( x );

  this.position.y = parseFloat( y );

};



// ----- transition ----- //



/**

 * @param {Object} style - CSS

 * @param {Function} onTransitionEnd

 */



// non transition, just trigger callback

proto._nonTransition = function( args ) {

  this.css( args.to );

  if ( args.isCleaning ) {

    this._removeStyles( args.to );

  }

  for ( var prop in args.onTransitionEnd ) {

    args.onTransitionEnd[ prop ].call( this );

  }

};



/**

 * proper transition

 * @param {Object} args - arguments

 *   @param {Object} to - style to transition to

 *   @param {Object} from - style to start transition from

 *   @param {Boolean} isCleaning - removes transition styles after transition

 *   @param {Function} onTransitionEnd - callback

 */

proto.transition = function( args ) {

  // redirect to nonTransition if no transition duration

  if ( !parseFloat( this.layout.options.transitionDuration ) ) {

    this._nonTransition( args );

    return;

  }



  var _transition = this._transn;

  // keep track of onTransitionEnd callback by css property

  for ( var prop in args.onTransitionEnd ) {

    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];

  }

  // keep track of properties that are transitioning

  for ( prop in args.to ) {

    _transition.ingProperties[ prop ] = true;

    // keep track of properties to clean up when transition is done

    if ( args.isCleaning ) {

      _transition.clean[ prop ] = true;

    }

  }



  // set from styles

  if ( args.from ) {

    this.css( args.from );

    // force redraw. http://blog.alexmaccaw.com/css-transitions

    var h = this.element.offsetHeight;

    // hack for JSHint to hush about unused var

    h = null;

  }

  // enable transition

  this.enableTransition( args.to );

  // set styles that are transitioning

  this.css( args.to );



  this.isTransitioning = true;



};



// dash before all cap letters, including first for

// WebkitTransform => -webkit-transform

function toDashedAll( str ) {

  return str.replace( /([A-Z])/g, function( $1 ) {

    return '-' + $1.toLowerCase();

  });

}



var transitionProps = 'opacity,' + toDashedAll( transformProperty );



proto.enableTransition = function(/* style */) {

  // HACK changing transitionProperty during a transition

  // will cause transition to jump

  if ( this.isTransitioning ) {

    return;

  }



  // make `transition: foo, bar, baz` from style object

  // HACK un-comment this when enableTransition can work

  // while a transition is happening

  // var transitionValues = [];

  // for ( var prop in style ) {

  //   // dash-ify camelCased properties like WebkitTransition

  //   prop = vendorProperties[ prop ] || prop;

  //   transitionValues.push( toDashedAll( prop ) );

  // }

  // munge number to millisecond, to match stagger

  var duration = this.layout.options.transitionDuration;

  duration = typeof duration == 'number' ? duration + 'ms' : duration;

  // enable transition styles

  this.css({

    transitionProperty: transitionProps,

    transitionDuration: duration,

    transitionDelay: this.staggerDelay || 0

  });

  // listen for transition end event

  this.element.addEventListener( transitionEndEvent, this, false );

};



// ----- events ----- //



proto.onwebkitTransitionEnd = function( event ) {

  this.ontransitionend( event );

};



proto.onotransitionend = function( event ) {

  this.ontransitionend( event );

};



// properties that I munge to make my life easier

var dashedVendorProperties = {

  '-webkit-transform': 'transform'

};



proto.ontransitionend = function( event ) {

  // disregard bubbled events from children

  if ( event.target !== this.element ) {

    return;

  }

  var _transition = this._transn;

  // get property name of transitioned property, convert to prefix-free

  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;



  // remove property that has completed transitioning

  delete _transition.ingProperties[ propertyName ];

  // check if any properties are still transitioning

  if ( isEmptyObj( _transition.ingProperties ) ) {

    // all properties have completed transitioning

    this.disableTransition();

  }

  // clean style

  if ( propertyName in _transition.clean ) {

    // clean up style

    this.element.style[ event.propertyName ] = '';

    delete _transition.clean[ propertyName ];

  }

  // trigger onTransitionEnd callback

  if ( propertyName in _transition.onEnd ) {

    var onTransitionEnd = _transition.onEnd[ propertyName ];

    onTransitionEnd.call( this );

    delete _transition.onEnd[ propertyName ];

  }



  this.emitEvent( 'transitionEnd', [ this ] );

};



proto.disableTransition = function() {

  this.removeTransitionStyles();

  this.element.removeEventListener( transitionEndEvent, this, false );

  this.isTransitioning = false;

};



/**

 * removes style property from element

 * @param {Object} style

**/

proto._removeStyles = function( style ) {

  // clean up transition styles

  var cleanStyle = {};

  for ( var prop in style ) {

    cleanStyle[ prop ] = '';

  }

  this.css( cleanStyle );

};



var cleanTransitionStyle = {

  transitionProperty: '',

  transitionDuration: '',

  transitionDelay: ''

};



proto.removeTransitionStyles = function() {

  // remove transition

  this.css( cleanTransitionStyle );

};



// ----- stagger ----- //



proto.stagger = function( delay ) {

  delay = isNaN( delay ) ? 0 : delay;

  this.staggerDelay = delay + 'ms';

};



// ----- show/hide/remove ----- //



// remove element from DOM

proto.removeElem = function() {

  this.element.parentNode.removeChild( this.element );

  // remove display: none

  this.css({ display: '' });

  this.emitEvent( 'remove', [ this ] );

};



proto.remove = function() {

  // just remove element if no transition support or no transition

  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {

    this.removeElem();

    return;

  }



  // start transition

  this.once( 'transitionEnd', function() {

    this.removeElem();

  });

  this.hide();

};



proto.reveal = function() {

  delete this.isHidden;

  // remove display: none

  this.css({ display: '' });



  var options = this.layout.options;



  var onTransitionEnd = {};

  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');

  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;



  this.transition({

    from: options.hiddenStyle,

    to: options.visibleStyle,

    isCleaning: true,

    onTransitionEnd: onTransitionEnd

  });

};



proto.onRevealTransitionEnd = function() {

  // check if still visible

  // during transition, item may have been hidden

  if ( !this.isHidden ) {

    this.emitEvent('reveal');

  }

};



/**

 * get style property use for hide/reveal transition end

 * @param {String} styleProperty - hiddenStyle/visibleStyle

 * @returns {String}

 */

proto.getHideRevealTransitionEndProperty = function( styleProperty ) {

  var optionStyle = this.layout.options[ styleProperty ];

  // use opacity

  if ( optionStyle.opacity ) {

    return 'opacity';

  }

  // get first property

  for ( var prop in optionStyle ) {

    return prop;

  }

};



proto.hide = function() {

  // set flag

  this.isHidden = true;

  // remove display: none

  this.css({ display: '' });



  var options = this.layout.options;



  var onTransitionEnd = {};

  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');

  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;



  this.transition({

    from: options.visibleStyle,

    to: options.hiddenStyle,

    // keep hidden stuff hidden

    isCleaning: true,

    onTransitionEnd: onTransitionEnd

  });

};



proto.onHideTransitionEnd = function() {

  // check if still hidden

  // during transition, item may have been un-hidden

  if ( this.isHidden ) {

    this.css({ display: 'none' });

    this.emitEvent('hide');

  }

};



proto.destroy = function() {

  this.css({

    position: '',

    left: '',

    right: '',

    top: '',

    bottom: '',

    transition: '',

    transform: ''

  });

};



return Item;



}));



/*!

 * Outlayer v2.1.1

 * the brains and guts of a layout library

 * MIT license

 */



( function( window, factory ) {

  'use strict';

  // universal module definition

  /* jshint strict: false */ /* globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD - RequireJS

    define( 'outlayer/outlayer',[

        'ev-emitter/ev-emitter',

        'get-size/get-size',

        'fizzy-ui-utils/utils',

        './item'

      ],

      function( EvEmitter, getSize, utils, Item ) {

        return factory( window, EvEmitter, getSize, utils, Item);

      }

    );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS - Browserify, Webpack

    module.exports = factory(

      window,

      require('ev-emitter'),

      require('get-size'),

      require('fizzy-ui-utils'),

      require('./item')

    );

  } else {

    // browser global

    window.Outlayer = factory(

      window,

      window.EvEmitter,

      window.getSize,

      window.fizzyUIUtils,

      window.Outlayer.Item

    );

  }



}( window, function factory( window, EvEmitter, getSize, utils, Item ) {

'use strict';



// ----- vars ----- //



var console = window.console;

var jQuery = window.jQuery;

var noop = function() {};



// -------------------------- Outlayer -------------------------- //



// globally unique identifiers

var GUID = 0;

// internal store of all Outlayer intances

var instances = {};





/**

 * @param {Element, String} element

 * @param {Object} options

 * @constructor

 */

function Outlayer( element, options ) {

  var queryElement = utils.getQueryElement( element );

  if ( !queryElement ) {

    if ( console ) {

      console.error( 'Bad element for ' + this.constructor.namespace +

        ': ' + ( queryElement || element ) );

    }

    return;

  }

  this.element = queryElement;

  // add jQuery

  if ( jQuery ) {

    this.$element = jQuery( this.element );

  }



  // options

  this.options = utils.extend( {}, this.constructor.defaults );

  this.option( options );



  // add id for Outlayer.getFromElement

  var id = ++GUID;

  this.element.outlayerGUID = id; // expando

  instances[ id ] = this; // associate via id



  // kick it off

  this._create();



  var isInitLayout = this._getOption('initLayout');

  if ( isInitLayout ) {

    this.layout();

  }

}



// settings are for internal use only

Outlayer.namespace = 'outlayer';

Outlayer.Item = Item;



// default options

Outlayer.defaults = {

  containerStyle: {

    position: 'relative'

  },

  initLayout: true,

  originLeft: true,

  originTop: true,

  resize: true,

  resizeContainer: true,

  // item options

  transitionDuration: '0.4s',

  hiddenStyle: {

    opacity: 0,

    transform: 'scale(0.001)'

  },

  visibleStyle: {

    opacity: 1,

    transform: 'scale(1)'

  }

};



var proto = Outlayer.prototype;

// inherit EvEmitter

utils.extend( proto, EvEmitter.prototype );



/**

 * set options

 * @param {Object} opts

 */

proto.option = function( opts ) {

  utils.extend( this.options, opts );

};



/**

 * get backwards compatible option value, check old name

 */

proto._getOption = function( option ) {

  var oldOption = this.constructor.compatOptions[ option ];

  return oldOption && this.options[ oldOption ] !== undefined ?

    this.options[ oldOption ] : this.options[ option ];

};



Outlayer.compatOptions = {

  // currentName: oldName

  initLayout: 'isInitLayout',

  horizontal: 'isHorizontal',

  layoutInstant: 'isLayoutInstant',

  originLeft: 'isOriginLeft',

  originTop: 'isOriginTop',

  resize: 'isResizeBound',

  resizeContainer: 'isResizingContainer'

};



proto._create = function() {

  // get items from children

  this.reloadItems();

  // elements that affect layout, but are not laid out

  this.stamps = [];

  this.stamp( this.options.stamp );

  // set container style

  utils.extend( this.element.style, this.options.containerStyle );



  // bind resize method

  var canBindResize = this._getOption('resize');

  if ( canBindResize ) {

    this.bindResize();

  }

};



// goes through all children again and gets bricks in proper order

proto.reloadItems = function() {

  // collection of item elements

  this.items = this._itemize( this.element.children );

};





/**

 * turn elements into Outlayer.Items to be used in layout

 * @param {Array or NodeList or HTMLElement} elems

 * @returns {Array} items - collection of new Outlayer Items

 */

proto._itemize = function( elems ) {



  var itemElems = this._filterFindItemElements( elems );

  var Item = this.constructor.Item;



  // create new Outlayer Items for collection

  var items = [];

  for ( var i=0; i < itemElems.length; i++ ) {

    var elem = itemElems[i];

    var item = new Item( elem, this );

    items.push( item );

  }



  return items;

};



/**

 * get item elements to be used in layout

 * @param {Array or NodeList or HTMLElement} elems

 * @returns {Array} items - item elements

 */

proto._filterFindItemElements = function( elems ) {

  return utils.filterFindElements( elems, this.options.itemSelector );

};



/**

 * getter method for getting item elements

 * @returns {Array} elems - collection of item elements

 */

proto.getItemElements = function() {

  return this.items.map( function( item ) {

    return item.element;

  });

};



// ----- init & layout ----- //



/**

 * lays out all items

 */

proto.layout = function() {

  this._resetLayout();

  this._manageStamps();



  // don't animate first layout

  var layoutInstant = this._getOption('layoutInstant');

  var isInstant = layoutInstant !== undefined ?

    layoutInstant : !this._isLayoutInited;

  this.layoutItems( this.items, isInstant );



  // flag for initalized

  this._isLayoutInited = true;

};



// _init is alias for layout

proto._init = proto.layout;



/**

 * logic before any new layout

 */

proto._resetLayout = function() {

  this.getSize();

};





proto.getSize = function() {

  this.size = getSize( this.element );

};



/**

 * get measurement from option, for columnWidth, rowHeight, gutter

 * if option is String -> get element from selector string, & get size of element

 * if option is Element -> get size of element

 * else use option as a number

 *

 * @param {String} measurement

 * @param {String} size - width or height

 * @private

 */

proto._getMeasurement = function( measurement, size ) {

  var option = this.options[ measurement ];

  var elem;

  if ( !option ) {

    // default to 0

    this[ measurement ] = 0;

  } else {

    // use option as an element

    if ( typeof option == 'string' ) {

      elem = this.element.querySelector( option );

    } else if ( option instanceof HTMLElement ) {

      elem = option;

    }

    // use size of element, if element

    this[ measurement ] = elem ? getSize( elem )[ size ] : option;

  }

};



/**

 * layout a collection of item elements

 * @api public

 */

proto.layoutItems = function( items, isInstant ) {

  items = this._getItemsForLayout( items );



  this._layoutItems( items, isInstant );



  this._postLayout();

};



/**

 * get the items to be laid out

 * you may want to skip over some items

 * @param {Array} items

 * @returns {Array} items

 */

proto._getItemsForLayout = function( items ) {

  return items.filter( function( item ) {

    return !item.isIgnored;

  });

};



/**

 * layout items

 * @param {Array} items

 * @param {Boolean} isInstant

 */

proto._layoutItems = function( items, isInstant ) {

  this._emitCompleteOnItems( 'layout', items );



  if ( !items || !items.length ) {

    // no items, emit event with empty array

    return;

  }



  var queue = [];



  items.forEach( function( item ) {

    // get x/y object from method

    var position = this._getItemLayoutPosition( item );

    // enqueue

    position.item = item;

    position.isInstant = isInstant || item.isLayoutInstant;

    queue.push( position );

  }, this );



  this._processLayoutQueue( queue );

};



/**

 * get item layout position

 * @param {Outlayer.Item} item

 * @returns {Object} x and y position

 */

proto._getItemLayoutPosition = function( /* item */ ) {

  return {

    x: 0,

    y: 0

  };

};



/**

 * iterate over array and position each item

 * Reason being - separating this logic prevents 'layout invalidation'

 * thx @paul_irish

 * @param {Array} queue

 */

proto._processLayoutQueue = function( queue ) {

  this.updateStagger();

  queue.forEach( function( obj, i ) {

    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );

  }, this );

};



// set stagger from option in milliseconds number

proto.updateStagger = function() {

  var stagger = this.options.stagger;

  if ( stagger === null || stagger === undefined ) {

    this.stagger = 0;

    return;

  }

  this.stagger = getMilliseconds( stagger );

  return this.stagger;

};



/**

 * Sets position of item in DOM

 * @param {Outlayer.Item} item

 * @param {Number} x - horizontal position

 * @param {Number} y - vertical position

 * @param {Boolean} isInstant - disables transitions

 */

proto._positionItem = function( item, x, y, isInstant, i ) {

  if ( isInstant ) {

    // if not transition, just set CSS

    item.goTo( x, y );

  } else {

    item.stagger( i * this.stagger );

    item.moveTo( x, y );

  }

};



/**

 * Any logic you want to do after each layout,

 * i.e. size the container

 */

proto._postLayout = function() {

  this.resizeContainer();

};



proto.resizeContainer = function() {

  var isResizingContainer = this._getOption('resizeContainer');

  if ( !isResizingContainer ) {

    return;

  }

  var size = this._getContainerSize();

  if ( size ) {

    this._setContainerMeasure( size.width, true );

    this._setContainerMeasure( size.height, false );

  }

};



/**

 * Sets width or height of container if returned

 * @returns {Object} size

 *   @param {Number} width

 *   @param {Number} height

 */

proto._getContainerSize = noop;



/**

 * @param {Number} measure - size of width or height

 * @param {Boolean} isWidth

 */

proto._setContainerMeasure = function( measure, isWidth ) {

  if ( measure === undefined ) {

    return;

  }



  var elemSize = this.size;

  // add padding and border width if border box

  if ( elemSize.isBorderBox ) {

    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +

      elemSize.borderLeftWidth + elemSize.borderRightWidth :

      elemSize.paddingBottom + elemSize.paddingTop +

      elemSize.borderTopWidth + elemSize.borderBottomWidth;

  }



  measure = Math.max( measure, 0 );

  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';

};



/**

 * emit eventComplete on a collection of items events

 * @param {String} eventName

 * @param {Array} items - Outlayer.Items

 */

proto._emitCompleteOnItems = function( eventName, items ) {

  var _this = this;

  function onComplete() {

    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );

  }



  var count = items.length;

  if ( !items || !count ) {

    onComplete();

    return;

  }



  var doneCount = 0;

  function tick() {

    doneCount++;

    if ( doneCount == count ) {

      onComplete();

    }

  }



  // bind callback

  items.forEach( function( item ) {

    item.once( eventName, tick );

  });

};



/**

 * emits events via EvEmitter and jQuery events

 * @param {String} type - name of event

 * @param {Event} event - original event

 * @param {Array} args - extra arguments

 */

proto.dispatchEvent = function( type, event, args ) {

  // add original event to arguments

  var emitArgs = event ? [ event ].concat( args ) : args;

  this.emitEvent( type, emitArgs );



  if ( jQuery ) {

    // set this.$element

    this.$element = this.$element || jQuery( this.element );

    if ( event ) {

      // create jQuery event

      var $event = jQuery.Event( event );

      $event.type = type;

      this.$element.trigger( $event, args );

    } else {

      // just trigger with type if no event available

      this.$element.trigger( type, args );

    }

  }

};



// -------------------------- ignore & stamps -------------------------- //





/**

 * keep item in collection, but do not lay it out

 * ignored items do not get skipped in layout

 * @param {Element} elem

 */

proto.ignore = function( elem ) {

  var item = this.getItem( elem );

  if ( item ) {

    item.isIgnored = true;

  }

};



/**

 * return item to layout collection

 * @param {Element} elem

 */

proto.unignore = function( elem ) {

  var item = this.getItem( elem );

  if ( item ) {

    delete item.isIgnored;

  }

};



/**

 * adds elements to stamps

 * @param {NodeList, Array, Element, or String} elems

 */

proto.stamp = function( elems ) {

  elems = this._find( elems );

  if ( !elems ) {

    return;

  }



  this.stamps = this.stamps.concat( elems );

  // ignore

  elems.forEach( this.ignore, this );

};



/**

 * removes elements to stamps

 * @param {NodeList, Array, or Element} elems

 */

proto.unstamp = function( elems ) {

  elems = this._find( elems );

  if ( !elems ){

    return;

  }



  elems.forEach( function( elem ) {

    // filter out removed stamp elements

    utils.removeFrom( this.stamps, elem );

    this.unignore( elem );

  }, this );

};



/**

 * finds child elements

 * @param {NodeList, Array, Element, or String} elems

 * @returns {Array} elems

 */

proto._find = function( elems ) {

  if ( !elems ) {

    return;

  }

  // if string, use argument as selector string

  if ( typeof elems == 'string' ) {

    elems = this.element.querySelectorAll( elems );

  }

  elems = utils.makeArray( elems );

  return elems;

};



proto._manageStamps = function() {

  if ( !this.stamps || !this.stamps.length ) {

    return;

  }



  this._getBoundingRect();



  this.stamps.forEach( this._manageStamp, this );

};



// update boundingLeft / Top

proto._getBoundingRect = function() {

  // get bounding rect for container element

  var boundingRect = this.element.getBoundingClientRect();

  var size = this.size;

  this._boundingRect = {

    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,

    top: boundingRect.top + size.paddingTop + size.borderTopWidth,

    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),

    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )

  };

};



/**

 * @param {Element} stamp

**/

proto._manageStamp = noop;



/**

 * get x/y position of element relative to container element

 * @param {Element} elem

 * @returns {Object} offset - has left, top, right, bottom

 */

proto._getElementOffset = function( elem ) {

  var boundingRect = elem.getBoundingClientRect();

  var thisRect = this._boundingRect;

  var size = getSize( elem );

  var offset = {

    left: boundingRect.left - thisRect.left - size.marginLeft,

    top: boundingRect.top - thisRect.top - size.marginTop,

    right: thisRect.right - boundingRect.right - size.marginRight,

    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom

  };

  return offset;

};



// -------------------------- resize -------------------------- //



// enable event handlers for listeners

// i.e. resize -> onresize

proto.handleEvent = utils.handleEvent;



/**

 * Bind layout to window resizing

 */

proto.bindResize = function() {

  window.addEventListener( 'resize', this );

  this.isResizeBound = true;

};



/**

 * Unbind layout to window resizing

 */

proto.unbindResize = function() {

  window.removeEventListener( 'resize', this );

  this.isResizeBound = false;

};



proto.onresize = function() {

  this.resize();

};



utils.debounceMethod( Outlayer, 'onresize', 100 );



proto.resize = function() {

  // don't trigger if size did not change

  // or if resize was unbound. See #9

  if ( !this.isResizeBound || !this.needsResizeLayout() ) {

    return;

  }



  this.layout();

};



/**

 * check if layout is needed post layout

 * @returns Boolean

 */

proto.needsResizeLayout = function() {

  var size = getSize( this.element );

  // check that this.size and size are there

  // IE8 triggers resize on body size change, so they might not be

  var hasSizes = this.size && size;

  return hasSizes && size.innerWidth !== this.size.innerWidth;

};



// -------------------------- methods -------------------------- //



/**

 * add items to Outlayer instance

 * @param {Array or NodeList or Element} elems

 * @returns {Array} items - Outlayer.Items

**/

proto.addItems = function( elems ) {

  var items = this._itemize( elems );

  // add items to collection

  if ( items.length ) {

    this.items = this.items.concat( items );

  }

  return items;

};



/**

 * Layout newly-appended item elements

 * @param {Array or NodeList or Element} elems

 */

proto.appended = function( elems ) {

  var items = this.addItems( elems );

  if ( !items.length ) {

    return;

  }

  // layout and reveal just the new items

  this.layoutItems( items, true );

  this.reveal( items );

};



/**

 * Layout prepended elements

 * @param {Array or NodeList or Element} elems

 */

proto.prepended = function( elems ) {

  var items = this._itemize( elems );

  if ( !items.length ) {

    return;

  }

  // add items to beginning of collection

  var previousItems = this.items.slice(0);

  this.items = items.concat( previousItems );

  // start new layout

  this._resetLayout();

  this._manageStamps();

  // layout new stuff without transition

  this.layoutItems( items, true );

  this.reveal( items );

  // layout previous items

  this.layoutItems( previousItems );

};



/**

 * reveal a collection of items

 * @param {Array of Outlayer.Items} items

 */

proto.reveal = function( items ) {

  this._emitCompleteOnItems( 'reveal', items );

  if ( !items || !items.length ) {

    return;

  }

  var stagger = this.updateStagger();

  items.forEach( function( item, i ) {

    item.stagger( i * stagger );

    item.reveal();

  });

};



/**

 * hide a collection of items

 * @param {Array of Outlayer.Items} items

 */

proto.hide = function( items ) {

  this._emitCompleteOnItems( 'hide', items );

  if ( !items || !items.length ) {

    return;

  }

  var stagger = this.updateStagger();

  items.forEach( function( item, i ) {

    item.stagger( i * stagger );

    item.hide();

  });

};



/**

 * reveal item elements

 * @param {Array}, {Element}, {NodeList} items

 */

proto.revealItemElements = function( elems ) {

  var items = this.getItems( elems );

  this.reveal( items );

};



/**

 * hide item elements

 * @param {Array}, {Element}, {NodeList} items

 */

proto.hideItemElements = function( elems ) {

  var items = this.getItems( elems );

  this.hide( items );

};



/**

 * get Outlayer.Item, given an Element

 * @param {Element} elem

 * @param {Function} callback

 * @returns {Outlayer.Item} item

 */

proto.getItem = function( elem ) {

  // loop through items to get the one that matches

  for ( var i=0; i < this.items.length; i++ ) {

    var item = this.items[i];

    if ( item.element == elem ) {

      // return item

      return item;

    }

  }

};



/**

 * get collection of Outlayer.Items, given Elements

 * @param {Array} elems

 * @returns {Array} items - Outlayer.Items

 */

proto.getItems = function( elems ) {

  elems = utils.makeArray( elems );

  var items = [];

  elems.forEach( function( elem ) {

    var item = this.getItem( elem );

    if ( item ) {

      items.push( item );

    }

  }, this );



  return items;

};



/**

 * remove element(s) from instance and DOM

 * @param {Array or NodeList or Element} elems

 */

proto.remove = function( elems ) {

  var removeItems = this.getItems( elems );



  this._emitCompleteOnItems( 'remove', removeItems );



  // bail if no items to remove

  if ( !removeItems || !removeItems.length ) {

    return;

  }



  removeItems.forEach( function( item ) {

    item.remove();

    // remove item from collection

    utils.removeFrom( this.items, item );

  }, this );

};



// ----- destroy ----- //



// remove and disable Outlayer instance

proto.destroy = function() {

  // clean up dynamic styles

  var style = this.element.style;

  style.height = '';

  style.position = '';

  style.width = '';

  // destroy items

  this.items.forEach( function( item ) {

    item.destroy();

  });



  this.unbindResize();



  var id = this.element.outlayerGUID;

  delete instances[ id ]; // remove reference to instance by id

  delete this.element.outlayerGUID;

  // remove data for jQuery

  if ( jQuery ) {

    jQuery.removeData( this.element, this.constructor.namespace );

  }



};



// -------------------------- data -------------------------- //



/**

 * get Outlayer instance from element

 * @param {Element} elem

 * @returns {Outlayer}

 */

Outlayer.data = function( elem ) {

  elem = utils.getQueryElement( elem );

  var id = elem && elem.outlayerGUID;

  return id && instances[ id ];

};





// -------------------------- create Outlayer class -------------------------- //



/**

 * create a layout class

 * @param {String} namespace

 */

Outlayer.create = function( namespace, options ) {

  // sub-class Outlayer

  var Layout = subclass( Outlayer );

  // apply new options and compatOptions

  Layout.defaults = utils.extend( {}, Outlayer.defaults );

  utils.extend( Layout.defaults, options );

  Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );



  Layout.namespace = namespace;



  Layout.data = Outlayer.data;



  // sub-class Item

  Layout.Item = subclass( Item );



  // -------------------------- declarative -------------------------- //



  utils.htmlInit( Layout, namespace );



  // -------------------------- jQuery bridge -------------------------- //



  // make into jQuery plugin

  if ( jQuery && jQuery.bridget ) {

    jQuery.bridget( namespace, Layout );

  }



  return Layout;

};



function subclass( Parent ) {

  function SubClass() {

    Parent.apply( this, arguments );

  }



  SubClass.prototype = Object.create( Parent.prototype );

  SubClass.prototype.constructor = SubClass;



  return SubClass;

}



// ----- helpers ----- //



// how many milliseconds are in each unit

var msUnits = {

  ms: 1,

  s: 1000

};



// munge time-like parameter into millisecond number

// '0.4s' -> 40

function getMilliseconds( time ) {

  if ( typeof time == 'number' ) {

    return time;

  }

  var matches = time.match( /(^\d*\.?\d*)(\w*)/ );

  var num = matches && matches[1];

  var unit = matches && matches[2];

  if ( !num.length ) {

    return 0;

  }

  num = parseFloat( num );

  var mult = msUnits[ unit ] || 1;

  return num * mult;

}



// ----- fin ----- //



// back in global

Outlayer.Item = Item;



return Outlayer;



}));



/**

 * Isotope Item

**/



( function( window, factory ) {

  // universal module definition

  /* jshint strict: false */ /*globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'isotope-layout/js/item',[

        'outlayer/outlayer'

      ],

      factory );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory(

      require('outlayer')

    );

  } else {

    // browser global

    window.Isotope = window.Isotope || {};

    window.Isotope.Item = factory(

      window.Outlayer

    );

  }



}( window, function factory( Outlayer ) {

'use strict';



// -------------------------- Item -------------------------- //



// sub-class Outlayer Item

function Item() {

  Outlayer.Item.apply( this, arguments );

}



var proto = Item.prototype = Object.create( Outlayer.Item.prototype );



var _create = proto._create;

proto._create = function() {

  // assign id, used for original-order sorting

  this.id = this.layout.itemGUID++;

  _create.call( this );

  this.sortData = {};

};



proto.updateSortData = function() {

  if ( this.isIgnored ) {

    return;

  }

  // default sorters

  this.sortData.id = this.id;

  // for backward compatibility

  this.sortData['original-order'] = this.id;

  this.sortData.random = Math.random();

  // go thru getSortData obj and apply the sorters

  var getSortData = this.layout.options.getSortData;

  var sorters = this.layout._sorters;

  for ( var key in getSortData ) {

    var sorter = sorters[ key ];

    this.sortData[ key ] = sorter( this.element, this );

  }

};



var _destroy = proto.destroy;

proto.destroy = function() {

  // call super

  _destroy.apply( this, arguments );

  // reset display, #741

  this.css({

    display: ''

  });

};



return Item;



}));



/**

 * Isotope LayoutMode

 */



( function( window, factory ) {

  // universal module definition

  /* jshint strict: false */ /*globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'isotope-layout/js/layout-mode',[

        'get-size/get-size',

        'outlayer/outlayer'

      ],

      factory );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory(

      require('get-size'),

      require('outlayer')

    );

  } else {

    // browser global

    window.Isotope = window.Isotope || {};

    window.Isotope.LayoutMode = factory(

      window.getSize,

      window.Outlayer

    );

  }



}( window, function factory( getSize, Outlayer ) {

  'use strict';



  // layout mode class

  function LayoutMode( isotope ) {

    this.isotope = isotope;

    // link properties

    if ( isotope ) {

      this.options = isotope.options[ this.namespace ];

      this.element = isotope.element;

      this.items = isotope.filteredItems;

      this.size = isotope.size;

    }

  }



  var proto = LayoutMode.prototype;



  /**

   * some methods should just defer to default Outlayer method

   * and reference the Isotope instance as `this`

  **/

  var facadeMethods = [

    '_resetLayout',

    '_getItemLayoutPosition',

    '_manageStamp',

    '_getContainerSize',

    '_getElementOffset',

    'needsResizeLayout',

    '_getOption'

  ];



  facadeMethods.forEach( function( methodName ) {

    proto[ methodName ] = function() {

      return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );

    };

  });



  // -----  ----- //



  // for horizontal layout modes, check vertical size

  proto.needsVerticalResizeLayout = function() {

    // don't trigger if size did not change

    var size = getSize( this.isotope.element );

    // check that this.size and size are there

    // IE8 triggers resize on body size change, so they might not be

    var hasSizes = this.isotope.size && size;

    return hasSizes && size.innerHeight != this.isotope.size.innerHeight;

  };



  // ----- measurements ----- //



  proto._getMeasurement = function() {

    this.isotope._getMeasurement.apply( this, arguments );

  };



  proto.getColumnWidth = function() {

    this.getSegmentSize( 'column', 'Width' );

  };



  proto.getRowHeight = function() {

    this.getSegmentSize( 'row', 'Height' );

  };



  /**

   * get columnWidth or rowHeight

   * segment: 'column' or 'row'

   * size 'Width' or 'Height'

  **/

  proto.getSegmentSize = function( segment, size ) {

    var segmentName = segment + size;

    var outerSize = 'outer' + size;

    // columnWidth / outerWidth // rowHeight / outerHeight

    this._getMeasurement( segmentName, outerSize );

    // got rowHeight or columnWidth, we can chill

    if ( this[ segmentName ] ) {

      return;

    }

    // fall back to item of first element

    var firstItemSize = this.getFirstItemSize();

    this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||

      // or size of container

      this.isotope.size[ 'inner' + size ];

  };



  proto.getFirstItemSize = function() {

    var firstItem = this.isotope.filteredItems[0];

    return firstItem && firstItem.element && getSize( firstItem.element );

  };



  // ----- methods that should reference isotope ----- //



  proto.layout = function() {

    this.isotope.layout.apply( this.isotope, arguments );

  };



  proto.getSize = function() {

    this.isotope.getSize();

    this.size = this.isotope.size;

  };



  // -------------------------- create -------------------------- //



  LayoutMode.modes = {};



  LayoutMode.create = function( namespace, options ) {



    function Mode() {

      LayoutMode.apply( this, arguments );

    }



    Mode.prototype = Object.create( proto );

    Mode.prototype.constructor = Mode;



    // default options

    if ( options ) {

      Mode.options = options;

    }



    Mode.prototype.namespace = namespace;

    // register in Isotope

    LayoutMode.modes[ namespace ] = Mode;



    return Mode;

  };



  return LayoutMode;



}));



/*!

 * Masonry v4.2.1

 * Cascading grid layout library

 * https://masonry.desandro.com

 * MIT License

 * by David DeSandro

 */



( function( window, factory ) {

  // universal module definition

  /* jshint strict: false */ /*globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'masonry-layout/masonry',[

        'outlayer/outlayer',

        'get-size/get-size'

      ],

      factory );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory(

      require('outlayer'),

      require('get-size')

    );

  } else {

    // browser global

    window.Masonry = factory(

      window.Outlayer,

      window.getSize

    );

  }



}( window, function factory( Outlayer, getSize ) {







// -------------------------- masonryDefinition -------------------------- //



  // create an Outlayer layout class

  var Masonry = Outlayer.create('masonry');

  // isFitWidth -> fitWidth

  Masonry.compatOptions.fitWidth = 'isFitWidth';



  var proto = Masonry.prototype;



  proto._resetLayout = function() {

    this.getSize();

    this._getMeasurement( 'columnWidth', 'outerWidth' );

    this._getMeasurement( 'gutter', 'outerWidth' );

    this.measureColumns();



    // reset column Y

    this.colYs = [];

    for ( var i=0; i < this.cols; i++ ) {

      this.colYs.push( 0 );

    }



    this.maxY = 0;

    this.horizontalColIndex = 0;

  };



  proto.measureColumns = function() {

    this.getContainerWidth();

    // if columnWidth is 0, default to outerWidth of first item

    if ( !this.columnWidth ) {

      var firstItem = this.items[0];

      var firstItemElem = firstItem && firstItem.element;

      // columnWidth fall back to item of first element

      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||

        // if first elem has no width, default to size of container

        this.containerWidth;

    }



    var columnWidth = this.columnWidth += this.gutter;



    // calculate columns

    var containerWidth = this.containerWidth + this.gutter;

    var cols = containerWidth / columnWidth;

    // fix rounding errors, typically with gutters

    var excess = columnWidth - containerWidth % columnWidth;

    // if overshoot is less than a pixel, round up, otherwise floor it

    var mathMethod = excess && excess < 1 ? 'round' : 'floor';

    cols = Math[ mathMethod ]( cols );

    this.cols = Math.max( cols, 1 );

  };



  proto.getContainerWidth = function() {

    // container is parent if fit width

    var isFitWidth = this._getOption('fitWidth');

    var container = isFitWidth ? this.element.parentNode : this.element;

    // check that this.size and size are there

    // IE8 triggers resize on body size change, so they might not be

    var size = getSize( container );

    this.containerWidth = size && size.innerWidth;

  };



  proto._getItemLayoutPosition = function( item ) {

    item.getSize();

    // how many columns does this brick span

    var remainder = item.size.outerWidth % this.columnWidth;

    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';

    // round if off by 1 pixel, otherwise use ceil

    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );

    colSpan = Math.min( colSpan, this.cols );

    // use horizontal or top column position

    var colPosMethod = this.options.horizontalOrder ?

      '_getHorizontalColPosition' : '_getTopColPosition';

    var colPosition = this[ colPosMethod ]( colSpan, item );

    // position the brick

    var position = {

      x: this.columnWidth * colPosition.col,

      y: colPosition.y

    };

    // apply setHeight to necessary columns

    var setHeight = colPosition.y + item.size.outerHeight;

    var setMax = colSpan + colPosition.col;

    for ( var i = colPosition.col; i < setMax; i++ ) {

      this.colYs[i] = setHeight;

    }



    return position;

  };



  proto._getTopColPosition = function( colSpan ) {

    var colGroup = this._getTopColGroup( colSpan );

    // get the minimum Y value from the columns

    var minimumY = Math.min.apply( Math, colGroup );



    return {

      col: colGroup.indexOf( minimumY ),

      y: minimumY,

    };

  };



  /**

   * @param {Number} colSpan - number of columns the element spans

   * @returns {Array} colGroup

   */

  proto._getTopColGroup = function( colSpan ) {

    if ( colSpan < 2 ) {

      // if brick spans only one column, use all the column Ys

      return this.colYs;

    }



    var colGroup = [];

    // how many different places could this brick fit horizontally

    var groupCount = this.cols + 1 - colSpan;

    // for each group potential horizontal position

    for ( var i = 0; i < groupCount; i++ ) {

      colGroup[i] = this._getColGroupY( i, colSpan );

    }

    return colGroup;

  };



  proto._getColGroupY = function( col, colSpan ) {

    if ( colSpan < 2 ) {

      return this.colYs[ col ];

    }

    // make an array of colY values for that one group

    var groupColYs = this.colYs.slice( col, col + colSpan );

    // and get the max value of the array

    return Math.max.apply( Math, groupColYs );

  };



  // get column position based on horizontal index. #873

  proto._getHorizontalColPosition = function( colSpan, item ) {

    var col = this.horizontalColIndex % this.cols;

    var isOver = colSpan > 1 && col + colSpan > this.cols;

    // shift to next row if item can't fit on current row

    col = isOver ? 0 : col;

    // don't let zero-size items take up space

    var hasSize = item.size.outerWidth && item.size.outerHeight;

    this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;



    return {

      col: col,

      y: this._getColGroupY( col, colSpan ),

    };

  };



  proto._manageStamp = function( stamp ) {

    var stampSize = getSize( stamp );

    var offset = this._getElementOffset( stamp );

    // get the columns that this stamp affects

    var isOriginLeft = this._getOption('originLeft');

    var firstX = isOriginLeft ? offset.left : offset.right;

    var lastX = firstX + stampSize.outerWidth;

    var firstCol = Math.floor( firstX / this.columnWidth );

    firstCol = Math.max( 0, firstCol );

    var lastCol = Math.floor( lastX / this.columnWidth );

    // lastCol should not go over if multiple of columnWidth #425

    lastCol -= lastX % this.columnWidth ? 0 : 1;

    lastCol = Math.min( this.cols - 1, lastCol );

    // set colYs to bottom of the stamp



    var isOriginTop = this._getOption('originTop');

    var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +

      stampSize.outerHeight;

    for ( var i = firstCol; i <= lastCol; i++ ) {

      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );

    }

  };



  proto._getContainerSize = function() {

    this.maxY = Math.max.apply( Math, this.colYs );

    var size = {

      height: this.maxY

    };



    if ( this._getOption('fitWidth') ) {

      size.width = this._getContainerFitWidth();

    }



    return size;

  };



  proto._getContainerFitWidth = function() {

    var unusedCols = 0;

    // count unused columns

    var i = this.cols;

    while ( --i ) {

      if ( this.colYs[i] !== 0 ) {

        break;

      }

      unusedCols++;

    }

    // fit container to columns that have been used

    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;

  };



  proto.needsResizeLayout = function() {

    var previousWidth = this.containerWidth;

    this.getContainerWidth();

    return previousWidth != this.containerWidth;

  };



  return Masonry;



}));



/*!

 * Masonry layout mode

 * sub-classes Masonry

 * https://masonry.desandro.com

 */



( function( window, factory ) {

  // universal module definition

  /* jshint strict: false */ /*globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'isotope-layout/js/layout-modes/masonry',[

        '../layout-mode',

        'masonry-layout/masonry'

      ],

      factory );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory(

      require('../layout-mode'),

      require('masonry-layout')

    );

  } else {

    // browser global

    factory(

      window.Isotope.LayoutMode,

      window.Masonry

    );

  }



}( window, function factory( LayoutMode, Masonry ) {

'use strict';



// -------------------------- masonryDefinition -------------------------- //



  // create an Outlayer layout class

  var MasonryMode = LayoutMode.create('masonry');



  var proto = MasonryMode.prototype;



  var keepModeMethods = {

    _getElementOffset: true,

    layout: true,

    _getMeasurement: true

  };



  // inherit Masonry prototype

  for ( var method in Masonry.prototype ) {

    // do not inherit mode methods

    if ( !keepModeMethods[ method ] ) {

      proto[ method ] = Masonry.prototype[ method ];

    }

  }



  var measureColumns = proto.measureColumns;

  proto.measureColumns = function() {

    // set items, used if measuring first item

    this.items = this.isotope.filteredItems;

    measureColumns.call( this );

  };



  // point to mode options for fitWidth

  var _getOption = proto._getOption;

  proto._getOption = function( option ) {

    if ( option == 'fitWidth' ) {

      return this.options.isFitWidth !== undefined ?

        this.options.isFitWidth : this.options.fitWidth;

    }

    return _getOption.apply( this.isotope, arguments );

  };



  return MasonryMode;



}));



/**

 * fitRows layout mode

 */



( function( window, factory ) {

  // universal module definition

  /* jshint strict: false */ /*globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'isotope-layout/js/layout-modes/fit-rows',[

        '../layout-mode'

      ],

      factory );

  } else if ( typeof exports == 'object' ) {

    // CommonJS

    module.exports = factory(

      require('../layout-mode')

    );

  } else {

    // browser global

    factory(

      window.Isotope.LayoutMode

    );

  }



}( window, function factory( LayoutMode ) {

'use strict';



var FitRows = LayoutMode.create('fitRows');



var proto = FitRows.prototype;



proto._resetLayout = function() {

  this.x = 0;

  this.y = 0;

  this.maxY = 0;

  this._getMeasurement( 'gutter', 'outerWidth' );

};



proto._getItemLayoutPosition = function( item ) {

  item.getSize();



  var itemWidth = item.size.outerWidth + this.gutter;

  // if this element cannot fit in the current row

  var containerWidth = this.isotope.size.innerWidth + this.gutter;

  if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {

    this.x = 0;

    this.y = this.maxY;

  }



  var position = {

    x: this.x,

    y: this.y

  };



  this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );

  this.x += itemWidth;



  return position;

};



proto._getContainerSize = function() {

  return { height: this.maxY };

};



return FitRows;



}));



/**

 * vertical layout mode

 */



( function( window, factory ) {

  // universal module definition

  /* jshint strict: false */ /*globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( 'isotope-layout/js/layout-modes/vertical',[

        '../layout-mode'

      ],

      factory );

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory(

      require('../layout-mode')

    );

  } else {

    // browser global

    factory(

      window.Isotope.LayoutMode

    );

  }



}( window, function factory( LayoutMode ) {

'use strict';



var Vertical = LayoutMode.create( 'vertical', {

  horizontalAlignment: 0

});



var proto = Vertical.prototype;



proto._resetLayout = function() {

  this.y = 0;

};



proto._getItemLayoutPosition = function( item ) {

  item.getSize();

  var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *

    this.options.horizontalAlignment;

  var y = this.y;

  this.y += item.size.outerHeight;

  return { x: x, y: y };

};



proto._getContainerSize = function() {

  return { height: this.y };

};



return Vertical;



}));



/*!

 * Isotope v3.0.6

 *

 * Licensed GPLv3 for open source use

 * or Isotope Commercial License for commercial use

 *

 * https://isotope.metafizzy.co

 * Copyright 2010-2018 Metafizzy

 */



( function( window, factory ) {

  // universal module definition

  /* jshint strict: false */ /*globals define, module, require */

  if ( typeof define == 'function' && define.amd ) {

    // AMD

    define( [

        'outlayer/outlayer',

        'get-size/get-size',

        'desandro-matches-selector/matches-selector',

        'fizzy-ui-utils/utils',

        'isotope-layout/js/item',

        'isotope-layout/js/layout-mode',

        // include default layout modes

        'isotope-layout/js/layout-modes/masonry',

        'isotope-layout/js/layout-modes/fit-rows',

        'isotope-layout/js/layout-modes/vertical'

      ],

      function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {

        return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );

      });

  } else if ( typeof module == 'object' && module.exports ) {

    // CommonJS

    module.exports = factory(

      window,

      require('outlayer'),

      require('get-size'),

      require('desandro-matches-selector'),

      require('fizzy-ui-utils'),

      require('isotope-layout/js/item'),

      require('isotope-layout/js/layout-mode'),

      // include default layout modes

      require('isotope-layout/js/layout-modes/masonry'),

      require('isotope-layout/js/layout-modes/fit-rows'),

      require('isotope-layout/js/layout-modes/vertical')

    );

  } else {

    // browser global

    window.Isotope = factory(

      window,

      window.Outlayer,

      window.getSize,

      window.matchesSelector,

      window.fizzyUIUtils,

      window.Isotope.Item,

      window.Isotope.LayoutMode

    );

  }



}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,

  Item, LayoutMode ) {







// -------------------------- vars -------------------------- //



var jQuery = window.jQuery;



// -------------------------- helpers -------------------------- //



var trim = String.prototype.trim ?

  function( str ) {

    return str.trim();

  } :

  function( str ) {

    return str.replace( /^\s+|\s+$/g, '' );

  };



// -------------------------- isotopeDefinition -------------------------- //



  // create an Outlayer layout class

  var Isotope = Outlayer.create( 'isotope', {

    layoutMode: 'masonry',

    isJQueryFiltering: true,

    sortAscending: true

  });



  Isotope.Item = Item;

  Isotope.LayoutMode = LayoutMode;



  var proto = Isotope.prototype;



  proto._create = function() {

    this.itemGUID = 0;

    // functions that sort items

    this._sorters = {};

    this._getSorters();

    // call super

    Outlayer.prototype._create.call( this );



    // create layout modes

    this.modes = {};

    // start filteredItems with all items

    this.filteredItems = this.items;

    // keep of track of sortBys

    this.sortHistory = [ 'original-order' ];

    // create from registered layout modes

    for ( var name in LayoutMode.modes ) {

      this._initLayoutMode( name );

    }

  };



  proto.reloadItems = function() {

    // reset item ID counter

    this.itemGUID = 0;

    // call super

    Outlayer.prototype.reloadItems.call( this );

  };



  proto._itemize = function() {

    var items = Outlayer.prototype._itemize.apply( this, arguments );

    // assign ID for original-order

    for ( var i=0; i < items.length; i++ ) {

      var item = items[i];

      item.id = this.itemGUID++;

    }

    this._updateItemsSortData( items );

    return items;

  };





  // -------------------------- layout -------------------------- //



  proto._initLayoutMode = function( name ) {

    var Mode = LayoutMode.modes[ name ];

    // set mode options

    // HACK extend initial options, back-fill in default options

    var initialOpts = this.options[ name ] || {};

    this.options[ name ] = Mode.options ?

      utils.extend( Mode.options, initialOpts ) : initialOpts;

    // init layout mode instance

    this.modes[ name ] = new Mode( this );

  };





  proto.layout = function() {

    // if first time doing layout, do all magic

    if ( !this._isLayoutInited && this._getOption('initLayout') ) {

      this.arrange();

      return;

    }

    this._layout();

  };



  // private method to be used in layout() & magic()

  proto._layout = function() {

    // don't animate first layout

    var isInstant = this._getIsInstant();

    // layout flow

    this._resetLayout();

    this._manageStamps();

    this.layoutItems( this.filteredItems, isInstant );



    // flag for initalized

    this._isLayoutInited = true;

  };



  // filter + sort + layout

  proto.arrange = function( opts ) {

    // set any options pass

    this.option( opts );

    this._getIsInstant();

    // filter, sort, and layout



    // filter

    var filtered = this._filter( this.items );

    this.filteredItems = filtered.matches;



    this._bindArrangeComplete();



    if ( this._isInstant ) {

      this._noTransition( this._hideReveal, [ filtered ] );

    } else {

      this._hideReveal( filtered );

    }



    this._sort();

    this._layout();

  };

  // alias to _init for main plugin method

  proto._init = proto.arrange;



  proto._hideReveal = function( filtered ) {

    this.reveal( filtered.needReveal );

    this.hide( filtered.needHide );

  };



  // HACK

  // Don't animate/transition first layout

  // Or don't animate/transition other layouts

  proto._getIsInstant = function() {

    var isLayoutInstant = this._getOption('layoutInstant');

    var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :

      !this._isLayoutInited;

    this._isInstant = isInstant;

    return isInstant;

  };



  // listen for layoutComplete, hideComplete and revealComplete

  // to trigger arrangeComplete

  proto._bindArrangeComplete = function() {

    // listen for 3 events to trigger arrangeComplete

    var isLayoutComplete, isHideComplete, isRevealComplete;

    var _this = this;

    function arrangeParallelCallback() {

      if ( isLayoutComplete && isHideComplete && isRevealComplete ) {

        _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );

      }

    }

    this.once( 'layoutComplete', function() {

      isLayoutComplete = true;

      arrangeParallelCallback();

    });

    this.once( 'hideComplete', function() {

      isHideComplete = true;

      arrangeParallelCallback();

    });

    this.once( 'revealComplete', function() {

      isRevealComplete = true;

      arrangeParallelCallback();

    });

  };



  // -------------------------- filter -------------------------- //



  proto._filter = function( items ) {

    var filter = this.options.filter;

    filter = filter || '*';

    var matches = [];

    var hiddenMatched = [];

    var visibleUnmatched = [];



    var test = this._getFilterTest( filter );



    // test each item

    for ( var i=0; i < items.length; i++ ) {

      var item = items[i];

      if ( item.isIgnored ) {

        continue;

      }

      // add item to either matched or unmatched group

      var isMatched = test( item );

      // item.isFilterMatched = isMatched;

      // add to matches if its a match

      if ( isMatched ) {

        matches.push( item );

      }

      // add to additional group if item needs to be hidden or revealed

      if ( isMatched && item.isHidden ) {

        hiddenMatched.push( item );

      } else if ( !isMatched && !item.isHidden ) {

        visibleUnmatched.push( item );

      }

    }



    // return collections of items to be manipulated

    return {

      matches: matches,

      needReveal: hiddenMatched,

      needHide: visibleUnmatched

    };

  };



  // get a jQuery, function, or a matchesSelector test given the filter

  proto._getFilterTest = function( filter ) {

    if ( jQuery && this.options.isJQueryFiltering ) {

      // use jQuery

      return function( item ) {

        return jQuery( item.element ).is( filter );

      };

    }

    if ( typeof filter == 'function' ) {

      // use filter as function

      return function( item ) {

        return filter( item.element );

      };

    }

    // default, use filter as selector string

    return function( item ) {

      return matchesSelector( item.element, filter );

    };

  };



  // -------------------------- sorting -------------------------- //



  /**

   * @params {Array} elems

   * @public

   */

  proto.updateSortData = function( elems ) {

    // get items

    var items;

    if ( elems ) {

      elems = utils.makeArray( elems );

      items = this.getItems( elems );

    } else {

      // update all items if no elems provided

      items = this.items;

    }



    this._getSorters();

    this._updateItemsSortData( items );

  };



  proto._getSorters = function() {

    var getSortData = this.options.getSortData;

    for ( var key in getSortData ) {

      var sorter = getSortData[ key ];

      this._sorters[ key ] = mungeSorter( sorter );

    }

  };



  /**

   * @params {Array} items - of Isotope.Items

   * @private

   */

  proto._updateItemsSortData = function( items ) {

    // do not update if no items

    var len = items && items.length;



    for ( var i=0; len && i < len; i++ ) {

      var item = items[i];

      item.updateSortData();

    }

  };



  // ----- munge sorter ----- //



  // encapsulate this, as we just need mungeSorter

  // other functions in here are just for munging

  var mungeSorter = ( function() {

    // add a magic layer to sorters for convienent shorthands

    // `.foo-bar` will use the text of .foo-bar querySelector

    // `[foo-bar]` will use attribute

    // you can also add parser

    // `.foo-bar parseInt` will parse that as a number

    function mungeSorter( sorter ) {

      // if not a string, return function or whatever it is

      if ( typeof sorter != 'string' ) {

        return sorter;

      }

      // parse the sorter string

      var args = trim( sorter ).split(' ');

      var query = args[0];

      // check if query looks like [an-attribute]

      var attrMatch = query.match( /^\[(.+)\]$/ );

      var attr = attrMatch && attrMatch[1];

      var getValue = getValueGetter( attr, query );

      // use second argument as a parser

      var parser = Isotope.sortDataParsers[ args[1] ];

      // parse the value, if there was a parser

      sorter = parser ? function( elem ) {

        return elem && parser( getValue( elem ) );

      } :

      // otherwise just return value

      function( elem ) {

        return elem && getValue( elem );

      };



      return sorter;

    }



    // get an attribute getter, or get text of the querySelector

    function getValueGetter( attr, query ) {

      // if query looks like [foo-bar], get attribute

      if ( attr ) {

        return function getAttribute( elem ) {

          return elem.getAttribute( attr );

        };

      }



      // otherwise, assume its a querySelector, and get its text

      return function getChildText( elem ) {

        var child = elem.querySelector( query );

        return child && child.textContent;

      };

    }



    return mungeSorter;

  })();



  // parsers used in getSortData shortcut strings

  Isotope.sortDataParsers = {

    'parseInt': function( val ) {

      return parseInt( val, 10 );

    },

    'parseFloat': function( val ) {

      return parseFloat( val );

    }

  };



  // ----- sort method ----- //



  // sort filteredItem order

  proto._sort = function() {

    if ( !this.options.sortBy ) {

      return;

    }

    // keep track of sortBy History

    var sortBys = utils.makeArray( this.options.sortBy );

    if ( !this._getIsSameSortBy( sortBys ) ) {

      // concat all sortBy and sortHistory, add to front, oldest goes in last

      this.sortHistory = sortBys.concat( this.sortHistory );

    }

    // sort magic

    var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );

    this.filteredItems.sort( itemSorter );

  };



  // check if sortBys is same as start of sortHistory

  proto._getIsSameSortBy = function( sortBys ) {

    for ( var i=0; i < sortBys.length; i++ ) {

      if ( sortBys[i] != this.sortHistory[i] ) {

        return false;

      }

    }

    return true;

  };



  // returns a function used for sorting

  function getItemSorter( sortBys, sortAsc ) {

    return function sorter( itemA, itemB ) {

      // cycle through all sortKeys

      for ( var i = 0; i < sortBys.length; i++ ) {

        var sortBy = sortBys[i];

        var a = itemA.sortData[ sortBy ];

        var b = itemB.sortData[ sortBy ];

        if ( a > b || a < b ) {

          // if sortAsc is an object, use the value given the sortBy key

          var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;

          var direction = isAscending ? 1 : -1;

          return ( a > b ? 1 : -1 ) * direction;

        }

      }

      return 0;

    };

  }



  // -------------------------- methods -------------------------- //



  // get layout mode

  proto._mode = function() {

    var layoutMode = this.options.layoutMode;

    var mode = this.modes[ layoutMode ];

    if ( !mode ) {

      // TODO console.error

      throw new Error( 'No layout mode: ' + layoutMode );

    }

    // HACK sync mode's options

    // any options set after init for layout mode need to be synced

    mode.options = this.options[ layoutMode ];

    return mode;

  };



  proto._resetLayout = function() {

    // trigger original reset layout

    Outlayer.prototype._resetLayout.call( this );

    this._mode()._resetLayout();

  };



  proto._getItemLayoutPosition = function( item  ) {

    return this._mode()._getItemLayoutPosition( item );

  };



  proto._manageStamp = function( stamp ) {

    this._mode()._manageStamp( stamp );

  };



  proto._getContainerSize = function() {

    return this._mode()._getContainerSize();

  };



  proto.needsResizeLayout = function() {

    return this._mode().needsResizeLayout();

  };



  // -------------------------- adding & removing -------------------------- //



  // HEADS UP overwrites default Outlayer appended

  proto.appended = function( elems ) {

    var items = this.addItems( elems );

    if ( !items.length ) {

      return;

    }

    // filter, layout, reveal new items

    var filteredItems = this._filterRevealAdded( items );

    // add to filteredItems

    this.filteredItems = this.filteredItems.concat( filteredItems );

  };



  // HEADS UP overwrites default Outlayer prepended

  proto.prepended = function( elems ) {

    var items = this._itemize( elems );

    if ( !items.length ) {

      return;

    }

    // start new layout

    this._resetLayout();

    this._manageStamps();

    // filter, layout, reveal new items

    var filteredItems = this._filterRevealAdded( items );

    // layout previous items

    this.layoutItems( this.filteredItems );

    // add to items and filteredItems

    this.filteredItems = filteredItems.concat( this.filteredItems );

    this.items = items.concat( this.items );

  };



  proto._filterRevealAdded = function( items ) {

    var filtered = this._filter( items );

    this.hide( filtered.needHide );

    // reveal all new items

    this.reveal( filtered.matches );

    // layout new items, no transition

    this.layoutItems( filtered.matches, true );

    return filtered.matches;

  };



  /**

   * Filter, sort, and layout newly-appended item elements

   * @param {Array or NodeList or Element} elems

   */

  proto.insert = function( elems ) {

    var items = this.addItems( elems );

    if ( !items.length ) {

      return;

    }

    // append item elements

    var i, item;

    var len = items.length;

    for ( i=0; i < len; i++ ) {

      item = items[i];

      this.element.appendChild( item.element );

    }

    // filter new stuff

    var filteredInsertItems = this._filter( items ).matches;

    // set flag

    for ( i=0; i < len; i++ ) {

      items[i].isLayoutInstant = true;

    }

    this.arrange();

    // reset flag

    for ( i=0; i < len; i++ ) {

      delete items[i].isLayoutInstant;

    }

    this.reveal( filteredInsertItems );

  };



  var _remove = proto.remove;

  proto.remove = function( elems ) {

    elems = utils.makeArray( elems );

    var removeItems = this.getItems( elems );

    // do regular thing

    _remove.call( this, elems );

    // bail if no items to remove

    var len = removeItems && removeItems.length;

    // remove elems from filteredItems

    for ( var i=0; len && i < len; i++ ) {

      var item = removeItems[i];

      // remove item from collection

      utils.removeFrom( this.filteredItems, item );

    }

  };



  proto.shuffle = function() {

    // update random sortData

    for ( var i=0; i < this.items.length; i++ ) {

      var item = this.items[i];

      item.sortData.random = Math.random();

    }

    this.options.sortBy = 'random';

    this._sort();

    this._layout();

  };



  /**

   * trigger fn without transition

   * kind of hacky to have this in the first place

   * @param {Function} fn

   * @param {Array} args

   * @returns ret

   * @private

   */

  proto._noTransition = function( fn, args ) {

    // save transitionDuration before disabling

    var transitionDuration = this.options.transitionDuration;

    // disable transition

    this.options.transitionDuration = 0;

    // do it

    var returnValue = fn.apply( this, args );

    // re-enable transition for reveal

    this.options.transitionDuration = transitionDuration;

    return returnValue;

  };



  // ----- helper methods ----- //



  /**

   * getter method for getting filtered item elements

   * @returns {Array} elems - collection of item elements

   */

  proto.getFilteredItemElements = function() {

    return this.filteredItems.map( function( item ) {

      return item.element;

    });

  };



  // -----  ----- //



  return Isotope;



}));







/*!

 * Packery layout mode PACKAGED v2.0.1

 * sub-classes Packery

 */



!function(a,b){"function"==typeof define&&define.amd?define("packery/js/rect",b):"object"==typeof module&&module.exports?module.exports=b():(a.Packery=a.Packery||{},a.Packery.Rect=b())}(window,function(){function a(b){for(var c in a.defaults)this[c]=a.defaults[c];for(c in b)this[c]=b[c]}a.defaults={x:0,y:0,width:0,height:0};var b=a.prototype;return b.contains=function(a){var b=a.width||0,c=a.height||0;return this.x<=a.x&&this.y<=a.y&&this.x+this.width>=a.x+b&&this.y+this.height>=a.y+c},b.overlaps=function(a){var b=this.x+this.width,c=this.y+this.height,d=a.x+a.width,e=a.y+a.height;return this.x<d&&b>a.x&&this.y<e&&c>a.y},b.getMaximalFreeRects=function(b){if(!this.overlaps(b))return!1;var c,d=[],e=this.x+this.width,f=this.y+this.height,g=b.x+b.width,h=b.y+b.height;return this.y<b.y&&(c=new a({x:this.x,y:this.y,width:this.width,height:b.y-this.y}),d.push(c)),e>g&&(c=new a({x:g,y:this.y,width:e-g,height:this.height}),d.push(c)),f>h&&(c=new a({x:this.x,y:h,width:this.width,height:f-h}),d.push(c)),this.x<b.x&&(c=new a({x:this.x,y:this.y,width:b.x-this.x,height:this.height}),d.push(c)),d},b.canFit=function(a){return this.width>=a.width&&this.height>=a.height},a}),function(a,b){if("function"==typeof define&&define.amd)define("packery/js/packer",["./rect"],b);else if("object"==typeof module&&module.exports)module.exports=b(require("./rect"));else{var c=a.Packery=a.Packery||{};c.Packer=b(c.Rect)}}(window,function(a){function b(a,b,c){this.width=a||0,this.height=b||0,this.sortDirection=c||"downwardLeftToRight",this.reset()}var c=b.prototype;c.reset=function(){this.spaces=[];var b=new a({x:0,y:0,width:this.width,height:this.height});this.spaces.push(b),this.sorter=d[this.sortDirection]||d.downwardLeftToRight},c.pack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b];if(c.canFit(a)){this.placeInSpace(a,c);break}}},c.columnPack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b],d=c.x<=a.x&&c.x+c.width>=a.x+a.width&&c.height>=a.height-.01;if(d){a.y=c.y,this.placed(a);break}}},c.rowPack=function(a){for(var b=0;b<this.spaces.length;b++){var c=this.spaces[b],d=c.y<=a.y&&c.y+c.height>=a.y+a.height&&c.width>=a.width-.01;if(d){a.x=c.x,this.placed(a);break}}},c.placeInSpace=function(a,b){a.x=b.x,a.y=b.y,this.placed(a)},c.placed=function(a){for(var b=[],c=0;c<this.spaces.length;c++){var d=this.spaces[c],e=d.getMaximalFreeRects(a);e?b.push.apply(b,e):b.push(d)}this.spaces=b,this.mergeSortSpaces()},c.mergeSortSpaces=function(){b.mergeRects(this.spaces),this.spaces.sort(this.sorter)},c.addSpace=function(a){this.spaces.push(a),this.mergeSortSpaces()},b.mergeRects=function(a){var b=0,c=a[b];a:for(;c;){for(var d=0,e=a[b+d];e;){if(e==c)d++;else{if(e.contains(c)){a.splice(b,1),c=a[b];continue a}c.contains(e)?a.splice(b+d,1):d++}e=a[b+d]}b++,c=a[b]}return a};var d={downwardLeftToRight:function(a,b){return a.y-b.y||a.x-b.x},rightwardTopToBottom:function(a,b){return a.x-b.x||a.y-b.y}};return b}),function(a,b){"function"==typeof define&&define.amd?define("packery/js/item",["outlayer/outlayer","./rect"],b):"object"==typeof module&&module.exports?module.exports=b(require("outlayer"),require("./rect")):a.Packery.Item=b(a.Outlayer,a.Packery.Rect)}(window,function(a,b){var c=document.documentElement.style,d="string"==typeof c.transform?"transform":"WebkitTransform",e=function(){a.Item.apply(this,arguments)},f=e.prototype=Object.create(a.Item.prototype),g=f._create;f._create=function(){g.call(this),this.rect=new b};var h=f.moveTo;return f.moveTo=function(a,b){var c=Math.abs(this.position.x-a),d=Math.abs(this.position.y-b),e=this.layout.dragItemCount&&!this.isPlacing&&!this.isTransitioning&&1>c&&1>d;return e?void this.goTo(a,b):void h.apply(this,arguments)},f.enablePlacing=function(){this.removeTransitionStyles(),this.isTransitioning&&d&&(this.element.style[d]="none"),this.isTransitioning=!1,this.getSize(),this.layout._setRectSize(this.element,this.rect),this.isPlacing=!0},f.disablePlacing=function(){this.isPlacing=!1},f.removeElem=function(){this.element.parentNode.removeChild(this.element),this.layout.packer.addSpace(this.rect),this.emitEvent("remove",[this])},f.showDropPlaceholder=function(){var a=this.dropPlaceholder;a||(a=this.dropPlaceholder=document.createElement("div"),a.className="packery-drop-placeholder",a.style.position="absolute"),a.style.width=this.size.width+"px",a.style.height=this.size.height+"px",this.positionDropPlaceholder(),this.layout.element.appendChild(a)},f.positionDropPlaceholder=function(){this.dropPlaceholder.style[d]="translate("+this.rect.x+"px, "+this.rect.y+"px)"},f.hideDropPlaceholder=function(){this.layout.element.removeChild(this.dropPlaceholder)},e}),function(a,b){"function"==typeof define&&define.amd?define("packery/js/packery",["get-size/get-size","outlayer/outlayer","./rect","./packer","./item"],b):"object"==typeof module&&module.exports?module.exports=b(require("get-size"),require("outlayer"),require("./rect"),require("./packer"),require("./item")):a.Packery=b(a.getSize,a.Outlayer,a.Packery.Rect,a.Packery.Packer,a.Packery.Item)}(window,function(a,b,c,d,e){function f(a,b){return a.position.y-b.position.y||a.position.x-b.position.x}function g(a,b){return a.position.x-b.position.x||a.position.y-b.position.y}function h(a,b){var c=b.x-a.x,d=b.y-a.y;return Math.sqrt(c*c+d*d)}c.prototype.canFit=function(a){return this.width>=a.width-1&&this.height>=a.height-1};var i=b.create("packery");i.Item=e;var j=i.prototype;j._create=function(){b.prototype._create.call(this),this.packer=new d,this.shiftPacker=new d,this.isEnabled=!0,this.dragItemCount=0;var a=this;this.handleDraggabilly={dragStart:function(){a.itemDragStart(this.element)},dragMove:function(){a.itemDragMove(this.element,this.position.x,this.position.y)},dragEnd:function(){a.itemDragEnd(this.element)}},this.handleUIDraggable={start:function(b,c){c&&a.itemDragStart(b.currentTarget)},drag:function(b,c){c&&a.itemDragMove(b.currentTarget,c.position.left,c.position.top)},stop:function(b,c){c&&a.itemDragEnd(b.currentTarget)}}},j._resetLayout=function(){this.getSize(),this._getMeasurements();var a,b,c;this._getOption("horizontal")?(a=1/0,b=this.size.innerHeight+this.gutter,c="rightwardTopToBottom"):(a=this.size.innerWidth+this.gutter,b=1/0,c="downwardLeftToRight"),this.packer.width=this.shiftPacker.width=a,this.packer.height=this.shiftPacker.height=b,this.packer.sortDirection=this.shiftPacker.sortDirection=c,this.packer.reset(),this.maxY=0,this.maxX=0},j._getMeasurements=function(){this._getMeasurement("columnWidth","width"),this._getMeasurement("rowHeight","height"),this._getMeasurement("gutter","width")},j._getItemLayoutPosition=function(a){if(this._setRectSize(a.element,a.rect),this.isShifting||this.dragItemCount>0){var b=this._getPackMethod();this.packer[b](a.rect)}else this.packer.pack(a.rect);return this._setMaxXY(a.rect),a.rect},j.shiftLayout=function(){this.isShifting=!0,this.layout(),delete this.isShifting},j._getPackMethod=function(){return this._getOption("horizontal")?"rowPack":"columnPack"},j._setMaxXY=function(a){this.maxX=Math.max(a.x+a.width,this.maxX),this.maxY=Math.max(a.y+a.height,this.maxY)},j._setRectSize=function(b,c){var d=a(b),e=d.outerWidth,f=d.outerHeight;(e||f)&&(e=this._applyGridGutter(e,this.columnWidth),f=this._applyGridGutter(f,this.rowHeight)),c.width=Math.min(e,this.packer.width),c.height=Math.min(f,this.packer.height)},j._applyGridGutter=function(a,b){if(!b)return a+this.gutter;b+=this.gutter;var c=a%b,d=c&&1>c?"round":"ceil";return a=Math[d](a/b)*b},j._getContainerSize=function(){return this._getOption("horizontal")?{width:this.maxX-this.gutter}:{height:this.maxY-this.gutter}},j._manageStamp=function(a){var b,d=this.getItem(a);if(d&&d.isPlacing)b=d.rect;else{var e=this._getElementOffset(a);b=new c({x:this._getOption("originLeft")?e.left:e.right,y:this._getOption("originTop")?e.top:e.bottom})}this._setRectSize(a,b),this.packer.placed(b),this._setMaxXY(b)},j.sortItemsByPosition=function(){var a=this._getOption("horizontal")?g:f;this.items.sort(a)},j.fit=function(a,b,c){var d=this.getItem(a);d&&(this.stamp(d.element),d.enablePlacing(),this.updateShiftTargets(d),b=void 0===b?d.rect.x:b,c=void 0===c?d.rect.y:c,this.shift(d,b,c),this._bindFitEvents(d),d.moveTo(d.rect.x,d.rect.y),this.shiftLayout(),this.unstamp(d.element),this.sortItemsByPosition(),d.disablePlacing())},j._bindFitEvents=function(a){function b(){d++,2==d&&c.dispatchEvent("fitComplete",null,[a])}var c=this,d=0;a.once("layout",b),this.once("layoutComplete",b)},j.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&(this.options.shiftPercentResize?this.resizeShiftPercentLayout():this.layout())},j.needsResizeLayout=function(){var b=a(this.element),c=this._getOption("horizontal")?"innerHeight":"innerWidth";return b[c]!=this.size[c]},j.resizeShiftPercentLayout=function(){var b=this._getItemsForLayout(this.items),c=this._getOption("horizontal"),d=c?"y":"x",e=c?"height":"width",f=c?"rowHeight":"columnWidth",g=c?"innerHeight":"innerWidth",h=this[f];if(h=h&&h+this.gutter){this._getMeasurements();var i=this[f]+this.gutter;b.forEach(function(a){var b=Math.round(a.rect[d]/h);a.rect[d]=b*i})}else{var j=a(this.element)[g]+this.gutter,k=this.packer[e];b.forEach(function(a){a.rect[d]=a.rect[d]/k*j})}this.shiftLayout()},j.itemDragStart=function(a){if(this.isEnabled){this.stamp(a);var b=this.getItem(a);b&&(b.enablePlacing(),b.showDropPlaceholder(),this.dragItemCount++,this.updateShiftTargets(b))}},j.updateShiftTargets=function(a){this.shiftPacker.reset(),this._getBoundingRect();var b=this._getOption("originLeft"),d=this._getOption("originTop");this.stamps.forEach(function(a){var e=this.getItem(a);if(!e||!e.isPlacing){var f=this._getElementOffset(a),g=new c({x:b?f.left:f.right,y:d?f.top:f.bottom});this._setRectSize(a,g),this.shiftPacker.placed(g)}},this);var e=this._getOption("horizontal"),f=e?"rowHeight":"columnWidth",g=e?"height":"width";this.shiftTargetKeys=[],this.shiftTargets=[];var h,i=this[f];if(i=i&&i+this.gutter){var j=Math.ceil(a.rect[g]/i),k=Math.floor((this.shiftPacker[g]+this.gutter)/i);h=(k-j)*i;for(var l=0;k>l;l++)this._addShiftTarget(l*i,0,h)}else h=this.shiftPacker[g]+this.gutter-a.rect[g],this._addShiftTarget(0,0,h);var m=this._getItemsForLayout(this.items),n=this._getPackMethod();m.forEach(function(a){var b=a.rect;this._setRectSize(a.element,b),this.shiftPacker[n](b),this._addShiftTarget(b.x,b.y,h);var c=e?b.x+b.width:b.x,d=e?b.y:b.y+b.height;if(this._addShiftTarget(c,d,h),i)for(var f=Math.round(b[g]/i),j=1;f>j;j++){var k=e?c:b.x+i*j,l=e?b.y+i*j:d;this._addShiftTarget(k,l,h)}},this)},j._addShiftTarget=function(a,b,c){var d=this._getOption("horizontal")?b:a;if(!(0!==d&&d>c)){var e=a+","+b,f=-1!=this.shiftTargetKeys.indexOf(e);f||(this.shiftTargetKeys.push(e),this.shiftTargets.push({x:a,y:b}))}},j.shift=function(a,b,c){var d,e=1/0,f={x:b,y:c};this.shiftTargets.forEach(function(a){var b=h(a,f);e>b&&(d=a,e=b)}),a.rect.x=d.x,a.rect.y=d.y};var k=120;j.itemDragMove=function(a,b,c){function d(){f.shift(e,b,c),e.positionDropPlaceholder(),f.layout()}var e=this.isEnabled&&this.getItem(a);if(e){b-=this.size.paddingLeft,c-=this.size.paddingTop;var f=this,g=new Date;this._itemDragTime&&g-this._itemDragTime<k?(clearTimeout(this.dragTimeout),this.dragTimeout=setTimeout(d,k)):(d(),this._itemDragTime=g)}},j.itemDragEnd=function(a){function b(){d++,2==d&&(c.element.classList.remove("is-positioning-post-drag"),c.hideDropPlaceholder(),e.dispatchEvent("dragItemPositioned",null,[c]))}var c=this.isEnabled&&this.getItem(a);if(c){clearTimeout(this.dragTimeout),c.element.classList.add("is-positioning-post-drag");var d=0,e=this;c.once("layout",b),this.once("layoutComplete",b),c.moveTo(c.rect.x,c.rect.y),this.layout(),this.dragItemCount=Math.max(0,this.dragItemCount-1),this.sortItemsByPosition(),c.disablePlacing(),this.unstamp(c.element)}},j.bindDraggabillyEvents=function(a){this._bindDraggabillyEvents(a,"on")},j.unbindDraggabillyEvents=function(a){this._bindDraggabillyEvents(a,"off")},j._bindDraggabillyEvents=function(a,b){var c=this.handleDraggabilly;a[b]("dragStart",c.dragStart),a[b]("dragMove",c.dragMove),a[b]("dragEnd",c.dragEnd)},j.bindUIDraggableEvents=function(a){this._bindUIDraggableEvents(a,"on")},j.unbindUIDraggableEvents=function(a){this._bindUIDraggableEvents(a,"off")},j._bindUIDraggableEvents=function(a,b){var c=this.handleUIDraggable;a[b]("dragstart",c.start)[b]("drag",c.drag)[b]("dragstop",c.stop)};var l=j.destroy;return j.destroy=function(){l.apply(this,arguments),this.isEnabled=!1},i.Rect=c,i.Packer=d,i}),function(a,b){"function"==typeof define&&define.amd?define(["isotope-layout/js/layout-mode","packery/js/packery"],b):"object"==typeof module&&module.exports?module.exports=b(require("isotope-layout/js/layout-mode"),require("packery")):b(a.Isotope.LayoutMode,a.Packery)}(window,function(a,b){var c=a.create("packery"),d=c.prototype,e={_getElementOffset:!0,_getMeasurement:!0};for(var f in b.prototype)e[f]||(d[f]=b.prototype[f]);var g=d._resetLayout;d._resetLayout=function(){this.packer=this.packer||new b.Packer,this.shiftPacker=this.shiftPacker||new b.Packer,g.apply(this,arguments)};var h=d._getItemLayoutPosition;d._getItemLayoutPosition=function(a){return a.rect=a.rect||new b.Rect,h.call(this,a)};var i=d.needsResizeLayout;d.needsResizeLayout=function(){return this._getOption("horizontal")?this.needsVerticalResizeLayout():i.call(this)};var j=d._getOption;return d._getOption=function(a){return"horizontal"==a?void 0!==this.options.isHorizontal?this.options.isHorizontal:this.options.horizontal:j.apply(this.isotope,arguments)},c});