UNPKG

avris-columnist

Version:

Simple and lightweight multi-column design

105 lines (82 loc) 2.87 kB
module.exports = class Columnist { constructor($container) { this.$container = $container; this.timer = null; this.columnCount = null; } layout() { const columns = this._countColumns(); // first row can get messed up if column count changes and they never get reset. let's just force it if (columns !== this.columnCount) { [...this.$container.children].forEach($col => { $col.style.marginTop = null; }); } this.columnCount = columns; let interventions = 0; const redraw = () => { let hasChanges = false; const margins = {}; let i = 0; [...this.$container.children].forEach($col => { const style = this._getStyle($col); if (!style) { return; } const extraHeight = parseInt(style.marginBottom.slice(0, -2), 10) + parseInt(style.paddingBottom.slice(0, -2), 10) + parseInt(style.borderBottomWidth.slice(0, -2), 10); margins[i] = Math.max(0, $col.offsetHeight - $col.children[0].offsetHeight - extraHeight); if (margins[i - columns] !== undefined) { const mT = `-${margins[i - columns]}px`.replace('-0px', '0px'); if ($col.style.marginTop !== mT) { $col.style.marginTop = mT; hasChanges = true; } } i++; }); interventions++; if (hasChanges && interventions < 100) { window.requestAnimationFrame(redraw); } } window.requestAnimationFrame(redraw); return this; } _countColumns() { const columnWidth = this._getColumnWidth(); return columnWidth ? Math.floor(this.$container.offsetWidth / columnWidth) : 1; } _getColumnWidth() { for (let $col of [...this.$container.children]) { if (this._getStyle($col)) { return $col.offsetWidth - 1; } } return null; } _getStyle($el) { const style = $el.currentStyle || window.getComputedStyle($el); if (style.display === 'none') { return null; } return style; } start(interval = 300) { this.timer = setInterval(() => this.layout(), interval); return this; } destroy() { if (this.timer) { clearInterval(this.timer); this.timer = null; } [...this.$container.children].forEach(($col, i) => { if (this._getStyle($col)) { $col.style.marginTop = null; } }); return this; } }