Current File : /pages/54/47/d0016649/home/htdocs/cd24/wp-content/themes/en-vision/lib/js/jquery-isotope.js
/**
 * 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( 'CloudFwisotope', {
	  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;

  }));