isotope-masonry-horizontal
Version:
masonryHorizontal layout mode for Isotope
147 lines (124 loc) • 4.31 kB
JavaScript
/*!
* masonryHorizontal layout mode for Isotope
* v2.0.1
* https://isotope.metafizzy.co/layout-modes/masonryhorizontal.html
*/
/*jshint browser: true, strict: true, undef: true, unused: true */
( function( window, factory ) {
'use strict';
// universal module definition
if ( typeof define === 'function' && define.amd ) {
// AMD
define( [
'get-size/get-size',
'isotope-layout/js/layout-mode'
],
factory );
} else if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory(
require('get-size'),
require('isotope-layout/js/layout-mode')
);
} else {
// browser global
factory(
window.getSize,
window.Isotope.LayoutMode
);
}
}( window, function factory( getSize, LayoutMode ) {
'use strict';
// -------------------------- definition -------------------------- //
// create an Outlayer layout class
var MasonryHorizontal = LayoutMode.create('masonryHorizontal');
var proto = MasonryHorizontal.prototype;
proto._resetLayout = function() {
this.getRowHeight();
this._getMeasurement( 'gutter', 'outerHeight' );
this.rowHeight += this.gutter;
// measure rows
this.rows = Math.floor( ( this.isotope.size.innerHeight + this.gutter ) / this.rowHeight );
this.rows = Math.max( this.rows, 1 );
// reset row Xs
var i = this.rows;
this.rowXs = [];
while (i--) {
this.rowXs.push( 0 );
}
this.maxX = 0;
};
proto._getItemLayoutPosition = function( item ) {
item.getSize();
// how many rows does this brick span
var remainder = item.size.outerHeight % this.rowHeight;
var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
// round if off by 1 pixel, otherwise use ceil
var rowSpan = Math[ mathMethod ]( item.size.outerHeight / this.rowHeight );
rowSpan = Math.min( rowSpan, this.rows );
var rowGroup = this._getRowGroup( rowSpan );
// get the minimum X value from the rows
var minimumX = Math.min.apply( Math, rowGroup );
var shortRowIndex = rowGroup.indexOf( minimumX );
// position the brick
var position = {
x: minimumX,
y: this.rowHeight * shortRowIndex
};
// apply setHeight to necessary rows
var setWidth = minimumX + item.size.outerWidth;
var setSpan = this.rows + 1 - rowGroup.length;
for ( var i = 0; i < setSpan; i++ ) {
this.rowXs[ shortRowIndex + i ] = setWidth;
}
return position;
};
/**
* @param {Number} rowSpan - number of rows the element spans
* @returns {Array} rowGroup
*/
proto._getRowGroup = function( rowSpan ) {
if ( rowSpan < 2 ) {
// if brick spans only one row, use all the row Xs
return this.rowXs;
}
var rowGroup = [];
// how many different places could this brick fit horizontally
var groupCount = this.rows + 1 - rowSpan;
// for each group potential horizontal position
for ( var i = 0; i < groupCount; i++ ) {
// make an array of rowX values for that one group
var groupRowXs = this.rowXs.slice( i, i + rowSpan );
// and get the max value of the array
rowGroup[i] = Math.max.apply( Math, groupRowXs );
}
return rowGroup;
};
proto._manageStamp = function( stamp ) {
var stampSize = getSize( stamp );
var offset = this.isotope._getElementOffset( stamp );
// get the rows that this stamp affects
var firstY = this._getOption('originTop') ? offset.top : offset.bottom;
var lastY = firstY + stampSize.outerHeight;
var firstRow = Math.floor( firstY / this.rowHeight );
firstRow = Math.max( 0, firstRow );
var lastRow = Math.floor( lastY / this.rowHeight );
lastRow = Math.min( this.rows - 1, lastRow );
// set rowXs to outside edge of the stamp
var stampMaxX = ( this._getOption('originLeft') ? offset.left : offset.right ) +
stampSize.outerWidth;
for ( var i = firstRow; i <= lastRow; i++ ) {
this.rowXs[i] = Math.max( stampMaxX, this.rowXs[i] );
}
};
proto._getContainerSize = function() {
this.maxX = Math.max.apply( Math, this.rowXs );
return {
width: this.maxX
};
};
proto.needsResizeLayout = function() {
return this.needsVerticalResizeLayout();
};
return MasonryHorizontal;
}));