/*!
--------------------------------
Waterfall.js
--------------------------------
+ https://github.com/raphamorim/waterfall
+ version 1.1.0
+ Copyright 2016 Raphael Amorim & Israel Teixeira
+ Licensed under the MIT license
+ Documentation: https://github.com/raphamorim/waterfall
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define('waterfall', function () {
return factory
})
} else if (typeof module === 'object' && module.exports) {
module.exports = factory
} else {
root.waterfall = factory
}
}(this, function waterfall (container) {
if (typeof (container) === 'string') {
container = document.querySelector(container)
}
function style (el) {
return window.getComputedStyle(el)
}
function margin (name, el) {
return parseFloat(style(el)['margin' + name]) || 0
}
function px (n) { return parseFloat(n) + 'px' }
function y (el) { return parseFloat(el.style.top) }
function x (el) { return parseFloat(el.style.left) }
function width (el) { return parseFloat(style(el).width) }
function height (el) { return parseFloat(style(el).height) }
function bottom (el) { return y(el) + height(el) + margin('Bottom', el) }
function right (el) { return x(el) + width(el) + margin('Right', el) }
function sort (l) {
l = l.sort(function (a, b) {
var bottomDiff = bottom(b) - bottom(a)
return bottomDiff || x(b) - x(a)
})
}
function Boundary (firstRow) {
var els = firstRow
sort(els)
this.add = function (el) {
els.push(el)
sort(els)
els.pop()
}
this.min = function () { return els[els.length - 1] }
this.max = function () { return els[0] }
}
function placeEl (el, top, left) {
el.style.position = 'absolute'
el.style.top = px(top)
el.style.left = px(left)
}
function placeFirstElement (el) {
placeEl(el, 0, margin('Left', el))
}
function placeAtTheFirstLine (prev, el) {
placeEl(el, prev.style.top, right(prev) + margin('Left', el))
}
function placeAtTheSmallestColumn (minEl, el) {
placeEl(el, bottom(minEl) + margin('Top', el), x(minEl))
}
function adjustContainer (container, maxEl) {
container.style.position = 'relative'
container.style.height = px(bottom(maxEl) + margin('Bottom', maxEl))
}
function thereIsSpace (els, i) {
return right(els[i - 1]) + width(els[i]) <= width(container)
}
var els = container.children
if (els.length) {
placeFirstElement(els[0])
}
for (var i = 1; i < els.length && thereIsSpace(els, i); i++) {
placeAtTheFirstLine(els[i - 1], els[i])
}
var firstRow = [].slice.call(els, 0, i)
var boundary = new Boundary(firstRow)
for (; i < els.length; i++) {
placeAtTheSmallestColumn(boundary.min(), els[i])
boundary.add(els[i])
}
adjustContainer(container, boundary.max())
}))