Blame | Last modification | View Log | RSS feed
/*!* Masonry PACKAGED v4.2.2* Cascading grid layout library* https://masonry.desandro.com* MIT License* by David DeSandro*//*** 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 ) {// AMDdefine( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {return factory( window, jQuery );});} else if ( typeof module == 'object' && module.exports ) {// CommonJSmodule.exports = factory(window,require('jquery'));} else {// browser globalwindow.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 chainingvar 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 setterPluginClass.prototype.option = function( opts ) {// bail out if not an objectif ( !$.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 1var 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 instancevar 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 valuevar value = method.apply( instance, args );// set return value if value is returned, use only first valuereturnValue = 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 & initinstance.option( options );instance._init();} else {// initialize new instanceinstance = new PluginClass( elem, options );$.data( elem, namespace, instance );}});}updateJQuery( $ );}// ----- updateJQuery ----- //// set $.bridget for v1 backwards compatibilityfunction 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 - RequireJSdefine( 'ev-emitter/ev-emitter',factory );} else if ( typeof module == 'object' && module.exports ) {// CommonJS - Browserify, Webpackmodule.exports = factory();} else {// Browser globalsglobal.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 hashvar events = this._events = this._events || {};// set listeners arrayvar listeners = events[ eventName ] = events[ eventName ] || [];// only add onceif ( listeners.indexOf( listener ) == -1 ) {listeners.push( listener );}return this;};proto.once = function( eventName, listener ) {if ( !eventName || !listener ) {return;}// add eventthis.on( eventName, listener );// set once flag// set onceEvents hashvar onceEvents = this._onceEvents = this._onceEvents || {};// set onceListeners objectvar onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};// set flagonceListeners[ 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 listenerlisteners = listeners.slice(0);args = args || [];// once stuffvar 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 recursionthis.off( eventName, listener );// unset once flagdelete onceListeners[ listener ];}// trigger listenerlistener.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 ) {// AMDdefine( 'get-size/get-size',factory );} else if ( typeof module == 'object' && module.exports ) {// CommonJSmodule.exports = factory();} else {// browser globalwindow.getSize = factory();}})( window, function factory() {'use strict';// -------------------------- helpers -------------------------- //// get a number from a string, not a percentagefunction getStyleSize( value ) {var num = parseFloat( value );// not a percent like '100%', and a numbervar 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 onceif ( 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#928isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;getSize.isBoxSizeOuter = isBoxSizeOuter;body.removeChild( div );}// -------------------------- getSize -------------------------- //function getSize( elem ) {setup();// use querySeletor if elem is stringif ( typeof elem == 'string' ) {elem = document.querySelector( elem );}// do not proceed on non-objectsif ( !elem || typeof elem != 'object' || !elem.nodeType ) {return;}var style = getStyle( elem );// if hidden, everything is 0if ( 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 measurementsfor ( var i=0; i < measurementsLength; i++ ) {var measurement = measurements[i];var value = style[ measurement ];var num = parseFloat( value );// any 'auto', 'medium' value will be 0size[ 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 stylevar 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 definitionif ( typeof define == 'function' && define.amd ) {// AMDdefine( 'desandro-matches-selector/matches-selector',factory );} else if ( typeof module == 'object' && module.exports ) {// CommonJSmodule.exports = factory();} else {// browser globalwindow.matchesSelector = factory();}}( window, function factory() {'use strict';var matchesMethod = ( function() {var ElemProto = window.Element.prototype;// check for the standard method name firstif ( ElemProto.matches ) {return 'matches';}// check un-prefixedif ( ElemProto.matchesSelector ) {return 'matchesSelector';}// check vendor prefixesvar 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 ) {// AMDdefine( 'fizzy-ui-utils/utils',['desandro-matches-selector/matches-selector'], function( matchesSelector ) {return factory( window, matchesSelector );});} else if ( typeof module == 'object' && module.exports ) {// CommonJSmodule.exports = factory(window,require('desandro-matches-selector'));} else {// browser globalwindow.fizzyUIUtils = factory(window,window.matchesSelector);}}( window, function factory( window, matchesSelector ) {var utils = {};// ----- extend ----- //// extends objectsutils.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 arrayutils.makeArray = function( obj ) {if ( Array.isArray( obj ) ) {// use object if already an arrayreturn obj;}// return empty array if undefined or null. #6if ( obj === null || obj === undefined ) {return [];}var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';if ( isArrayLike ) {// convert nodeList to arrayreturn arraySlice.call( obj );}// array of single indexreturn [ 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 stringutils.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 elemselems = utils.makeArray( elems );var ffElems = [];elems.forEach( function( elem ) {// check that elem is an actual elementif ( !( elem instanceof HTMLElement ) ) {return;}// add elem if no selectorif ( !selector ) {ffElems.push( elem );return;}// filter & find items if we have a selector// filterif ( matchesSelector( elem, selector ) ) {ffElems.push( elem );}// find childrenvar childElems = elem.querySelectorAll( selector );// concat childElems to filterFound arrayfor ( var i=0; i < childElems.length; i++ ) {ffElems.push( childElems[i] );}});return ffElems;};// ----- debounceMethod ----- //utils.debounceMethod = function( _class, methodName, threshold ) {threshold = threshold || 100;// original methodvar 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#441setTimeout( 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 initializeif ( console ) {console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +': ' + error );}return;}// initializevar 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 - RequireJSdefine( 'outlayer/item',['ev-emitter/ev-emitter','get-size/get-size'],factory);} else if ( typeof module == 'object' && module.exports ) {// CommonJS - Browserify, Webpackmodule.exports = factory(require('ev-emitter'),require('get-size'));} else {// browser globalwindow.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 prefixvar 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 Packerythis.layout = layout;this.position = {x: 0,y: 0};this._create();}// inherit EvEmittervar proto = Item.prototype = Object.create( EvEmitter.prototype );proto.constructor = Item;proto._create = function() {// transition objectsthis._transn = {ingProperties: {},clean: {},onEnd: {}};this.css({position: 'absolute'});};// trigger specified handler for event typeproto.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 availablevar supportedProp = vendorProperties[ prop ] || prop;elemStyle[ supportedProp ] = style[ prop ];}};// measure position, and sets itproto.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 pixelsvar 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 valuesx = isNaN( x ) ? 0 : x;y = isNaN( y ) ? 0 : y;// remove padding from measurementx -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;this.position.x = x;this.position.y = y;};// set settled position, apply paddingproto.layoutPosition = function() {var layoutSize = this.layout.size;var style = {};var isOriginLeft = this.layout._getOption('originLeft');var isOriginTop = this.layout._getOption('originTop');// xvar 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 pixelsstyle[ xProperty ] = this.getXValue( x );// reset other propertystyle[ xResetProperty ] = '';// yvar 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 pixelsstyle[ yProperty ] = this.getYValue( y );// reset other propertystyle[ 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/leftvar curX = this.position.x;var curY = this.position.y;var didNotMove = x == this.position.x && y == this.position.y;// save end positionthis.setPosition( x, y );// if did not move and not transitioning, just go to layoutif ( 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 bottomvar 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 supportproto.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 callbackproto._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 durationif ( !parseFloat( this.layout.options.transitionDuration ) ) {this._nonTransition( args );return;}var _transition = this._transn;// keep track of onTransitionEnd callback by css propertyfor ( var prop in args.onTransitionEnd ) {_transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];}// keep track of properties that are transitioningfor ( prop in args.to ) {_transition.ingProperties[ prop ] = true;// keep track of properties to clean up when transition is doneif ( args.isCleaning ) {_transition.clean[ prop ] = true;}}// set from stylesif ( args.from ) {this.css( args.from );// force redraw. http://blog.alexmaccaw.com/css-transitionsvar h = this.element.offsetHeight;// hack for JSHint to hush about unused varh = null;}// enable transitionthis.enableTransition( args.to );// set styles that are transitioningthis.css( args.to );this.isTransitioning = true;};// dash before all cap letters, including first for// WebkitTransform => -webkit-transformfunction 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 jumpif ( 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 staggervar duration = this.layout.options.transitionDuration;duration = typeof duration == 'number' ? duration + 'ms' : duration;// enable transition stylesthis.css({transitionProperty: transitionProps,transitionDuration: duration,transitionDelay: this.staggerDelay || 0});// listen for transition end eventthis.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 easiervar dashedVendorProperties = {'-webkit-transform': 'transform'};proto.ontransitionend = function( event ) {// disregard bubbled events from childrenif ( event.target !== this.element ) {return;}var _transition = this._transn;// get property name of transitioned property, convert to prefix-freevar propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;// remove property that has completed transitioningdelete _transition.ingProperties[ propertyName ];// check if any properties are still transitioningif ( isEmptyObj( _transition.ingProperties ) ) {// all properties have completed transitioningthis.disableTransition();}// clean styleif ( propertyName in _transition.clean ) {// clean up stylethis.element.style[ event.propertyName ] = '';delete _transition.clean[ propertyName ];}// trigger onTransitionEnd callbackif ( 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 stylesvar cleanStyle = {};for ( var prop in style ) {cleanStyle[ prop ] = '';}this.css( cleanStyle );};var cleanTransitionStyle = {transitionProperty: '',transitionDuration: '',transitionDelay: ''};proto.removeTransitionStyles = function() {// remove transitionthis.css( cleanTransitionStyle );};// ----- stagger ----- //proto.stagger = function( delay ) {delay = isNaN( delay ) ? 0 : delay;this.staggerDelay = delay + 'ms';};// ----- show/hide/remove ----- //// remove element from DOMproto.removeElem = function() {this.element.parentNode.removeChild( this.element );// remove display: nonethis.css({ display: '' });this.emitEvent( 'remove', [ this ] );};proto.remove = function() {// just remove element if no transition support or no transitionif ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {this.removeElem();return;}// start transitionthis.once( 'transitionEnd', function() {this.removeElem();});this.hide();};proto.reveal = function() {delete this.isHidden;// remove display: nonethis.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 hiddenif ( !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 opacityif ( optionStyle.opacity ) {return 'opacity';}// get first propertyfor ( var prop in optionStyle ) {return prop;}};proto.hide = function() {// set flagthis.isHidden = true;// remove display: nonethis.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 hiddenisCleaning: true,onTransitionEnd: onTransitionEnd});};proto.onHideTransitionEnd = function() {// check if still hidden// during transition, item may have been un-hiddenif ( 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 - RequireJSdefine( '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, Webpackmodule.exports = factory(window,require('ev-emitter'),require('get-size'),require('fizzy-ui-utils'),require('./item'));} else {// browser globalwindow.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 identifiersvar GUID = 0;// internal store of all Outlayer intancesvar 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 jQueryif ( jQuery ) {this.$element = jQuery( this.element );}// optionsthis.options = utils.extend( {}, this.constructor.defaults );this.option( options );// add id for Outlayer.getFromElementvar id = ++GUID;this.element.outlayerGUID = id; // expandoinstances[ id ] = this; // associate via id// kick it offthis._create();var isInitLayout = this._getOption('initLayout');if ( isInitLayout ) {this.layout();}}// settings are for internal use onlyOutlayer.namespace = 'outlayer';Outlayer.Item = Item;// default optionsOutlayer.defaults = {containerStyle: {position: 'relative'},initLayout: true,originLeft: true,originTop: true,resize: true,resizeContainer: true,// item optionstransitionDuration: '0.4s',hiddenStyle: {opacity: 0,transform: 'scale(0.001)'},visibleStyle: {opacity: 1,transform: 'scale(1)'}};var proto = Outlayer.prototype;// inherit EvEmitterutils.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: oldNameinitLayout: 'isInitLayout',horizontal: 'isHorizontal',layoutInstant: 'isLayoutInstant',originLeft: 'isOriginLeft',originTop: 'isOriginTop',resize: 'isResizeBound',resizeContainer: 'isResizingContainer'};proto._create = function() {// get items from childrenthis.reloadItems();// elements that affect layout, but are not laid outthis.stamps = [];this.stamp( this.options.stamp );// set container styleutils.extend( this.element.style, this.options.containerStyle );// bind resize methodvar canBindResize = this._getOption('resize');if ( canBindResize ) {this.bindResize();}};// goes through all children again and gets bricks in proper orderproto.reloadItems = function() {// collection of item elementsthis.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 collectionvar 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 layoutvar layoutInstant = this._getOption('layoutInstant');var isInstant = layoutInstant !== undefined ?layoutInstant : !this._isLayoutInited;this.layoutItems( this.items, isInstant );// flag for initalizedthis._isLayoutInited = true;};// _init is alias for layoutproto._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 0this[ measurement ] = 0;} else {// use option as an elementif ( typeof option == 'string' ) {elem = this.element.querySelector( option );} else if ( option instanceof HTMLElement ) {elem = option;}// use size of element, if elementthis[ 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 arrayreturn;}var queue = [];items.forEach( function( item ) {// get x/y object from methodvar position = this._getItemLayoutPosition( item );// enqueueposition.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 numberproto.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 CSSitem.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 boxif ( 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 callbackitems.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 argumentsvar emitArgs = event ? [ event ].concat( args ) : args;this.emitEvent( type, emitArgs );if ( jQuery ) {// set this.$elementthis.$element = this.$element || jQuery( this.element );if ( event ) {// create jQuery eventvar $event = jQuery.Event( event );$event.type = type;this.$element.trigger( $event, args );} else {// just trigger with type if no event availablethis.$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 );// ignoreelems.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 elementsutils.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 stringif ( 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 / Topproto._getBoundingRect = function() {// get bounding rect for container elementvar 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 -> onresizeproto.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 #9if ( !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 bevar 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 collectionif ( 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 itemsthis.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 collectionvar previousItems = this.items.slice(0);this.items = items.concat( previousItems );// start new layoutthis._resetLayout();this._manageStamps();// layout new stuff without transitionthis.layoutItems( items, true );this.reveal( items );// layout previous itemsthis.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 matchesfor ( var i=0; i < this.items.length; i++ ) {var item = this.items[i];if ( item.element == elem ) {// return itemreturn 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 removeif ( !removeItems || !removeItems.length ) {return;}removeItems.forEach( function( item ) {item.remove();// remove item from collectionutils.removeFrom( this.items, item );}, this );};// ----- destroy ----- //// remove and disable Outlayer instanceproto.destroy = function() {// clean up dynamic stylesvar style = this.element.style;style.height = '';style.position = '';style.width = '';// destroy itemsthis.items.forEach( function( item ) {item.destroy();});this.unbindResize();var id = this.element.outlayerGUID;delete instances[ id ]; // remove reference to instance by iddelete this.element.outlayerGUID;// remove data for jQueryif ( 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 Outlayervar Layout = subclass( Outlayer );// apply new options and compatOptionsLayout.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 ItemLayout.Item = subclass( Item );// -------------------------- declarative -------------------------- //utils.htmlInit( Layout, namespace );// -------------------------- jQuery bridge -------------------------- //// make into jQuery pluginif ( 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 unitvar msUnits = {ms: 1,s: 1000};// munge time-like parameter into millisecond number// '0.4s' -> 40function 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 globalOutlayer.Item = Item;return Outlayer;}));/*!* Masonry v4.2.2* 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 ) {// AMDdefine( ['outlayer/outlayer','get-size/get-size'],factory );} else if ( typeof module == 'object' && module.exports ) {// CommonJSmodule.exports = factory(require('outlayer'),require('get-size'));} else {// browser globalwindow.Masonry = factory(window.Outlayer,window.getSize);}}( window, function factory( Outlayer, getSize ) {// -------------------------- masonryDefinition -------------------------- //// create an Outlayer layout classvar Masonry = Outlayer.create('masonry');// isFitWidth -> fitWidthMasonry.compatOptions.fitWidth = 'isFitWidth';var proto = Masonry.prototype;proto._resetLayout = function() {this.getSize();this._getMeasurement( 'columnWidth', 'outerWidth' );this._getMeasurement( 'gutter', 'outerWidth' );this.measureColumns();// reset column Ythis.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 itemif ( !this.columnWidth ) {var firstItem = this.items[0];var firstItemElem = firstItem && firstItem.element;// columnWidth fall back to item of first elementthis.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||// if first elem has no width, default to size of containerthis.containerWidth;}var columnWidth = this.columnWidth += this.gutter;// calculate columnsvar containerWidth = this.containerWidth + this.gutter;var cols = containerWidth / columnWidth;// fix rounding errors, typically with guttersvar excess = columnWidth - containerWidth % columnWidth;// if overshoot is less than a pixel, round up, otherwise floor itvar mathMethod = excess && excess < 1 ? 'round' : 'floor';cols = Math[ mathMethod ]( cols );this.cols = Math.max( cols, 1 );};proto.getContainerWidth = function() {// container is parent if fit widthvar 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 bevar size = getSize( container );this.containerWidth = size && size.innerWidth;};proto._getItemLayoutPosition = function( item ) {item.getSize();// how many columns does this brick spanvar remainder = item.size.outerWidth % this.columnWidth;var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';// round if off by 1 pixel, otherwise use ceilvar colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );colSpan = Math.min( colSpan, this.cols );// use horizontal or top column positionvar colPosMethod = this.options.horizontalOrder ?'_getHorizontalColPosition' : '_getTopColPosition';var colPosition = this[ colPosMethod ]( colSpan, item );// position the brickvar position = {x: this.columnWidth * colPosition.col,y: colPosition.y};// apply setHeight to necessary columnsvar 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 columnsvar 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 Ysreturn this.colYs;}var colGroup = [];// how many different places could this brick fit horizontallyvar groupCount = this.cols + 1 - colSpan;// for each group potential horizontal positionfor ( 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 groupvar groupColYs = this.colYs.slice( col, col + colSpan );// and get the max value of the arrayreturn Math.max.apply( Math, groupColYs );};// get column position based on horizontal index. #873proto._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 rowcol = isOver ? 0 : col;// don't let zero-size items take up spacevar 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 affectsvar 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 #425lastCol -= lastX % this.columnWidth ? 0 : 1;lastCol = Math.min( this.cols - 1, lastCol );// set colYs to bottom of the stampvar 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 columnsvar i = this.cols;while ( --i ) {if ( this.colYs[i] !== 0 ) {break;}unusedCols++;}// fit container to columns that have been usedreturn ( this.cols - unusedCols ) * this.columnWidth - this.gutter;};proto.needsResizeLayout = function() {var previousWidth = this.containerWidth;this.getContainerWidth();return previousWidth != this.containerWidth;};return Masonry;}));