minigrid
Version:
Minimal 2kb zero dependency cascading grid layout
123 lines (97 loc) • 3.21 kB
JavaScript
/* @license Minigrid v3.1.1 – minimal cascading grid layout http://alves.im/minigrid */
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.Minigrid = factory();
}
}(this, function(exports){
'use strict';
function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
}
var Minigrid = function(props) {
var containerEle = props.container instanceof Node ? (
props.container
) : (
document.querySelector(props.container)
);
var itemsNodeList = props.item instanceof NodeList ?
props.item : containerEle.querySelectorAll(props.item);
this.props = extend(props, {
container: containerEle,
nodeList: itemsNodeList
});
}
Minigrid.prototype.mount = function() {
if (!this.props.container) {
return false;
}
if (!this.props.nodeList || this.props.nodeList.length === 0) {
return false;
}
var gutter = (
typeof this.props.gutter === 'number' &&
isFinite(this.props.gutter) &&
Math.floor(this.props.gutter) === this.props.gutter
) ? this.props.gutter : 0;
var done = this.props.done;
var containerEle = this.props.container;
var itemsNodeList = this.props.nodeList;
containerEle.style.width = '';
var forEach = Array.prototype.forEach;
var containerWidth = containerEle.getBoundingClientRect().width;
var firstChildWidth = itemsNodeList[0].getBoundingClientRect().width + gutter;
var cols = Math.max(Math.floor((containerWidth - gutter) / firstChildWidth), 1);
var count = 0;
containerWidth = (firstChildWidth * cols + gutter) + 'px';
containerEle.style.width = containerWidth;
containerEle.style.position = 'relative';
var itemsGutter = [];
var itemsPosX = [];
for ( var g = 0 ; g < cols ; ++g ) {
itemsPosX.push(g * firstChildWidth + gutter);
itemsGutter.push(gutter);
}
// RTL support
if (this.props.rtl) {
itemsPosX.reverse();
}
forEach.call(itemsNodeList, function (item) {
var itemIndex = itemsGutter
.slice(0)
.sort(function (a, b) {
return a - b;
})
.shift();
itemIndex = itemsGutter.indexOf(itemIndex);
var posX = parseInt(itemsPosX[itemIndex]);
var posY = parseInt(itemsGutter[itemIndex]);
item.style.position = 'absolute';
item.style.webkitBackfaceVisibility = item.style.backfaceVisibility = 'hidden';
item.style.transformStyle = 'preserve-3d';
item.style.transform = 'translate3D(' + posX + 'px,' + posY + 'px, 0)';
itemsGutter[itemIndex] += item.getBoundingClientRect().height + gutter;
count = count + 1;
});
containerEle.style.display = '';
var containerHeight = itemsGutter
.slice(0)
.sort(function (a, b) {
return a - b;
})
.pop();
containerEle.style.height = containerHeight + 'px';
if (typeof done === 'function') {
done(itemsNodeList);
}
}
return Minigrid;
}));