import { throttle, debounce } from 'throttle-debounce' /** * Tiny Masonry * * @author Björn Hase * @license http://opensource.org/licenses/MIT The MIT License * @link https://gitea.node001.net/tiny-components/masonry * */ class Masonry { /** * * */ constructor() { this.height = 0 // getting elements this.elements = document.querySelectorAll('.tiny-masonry__item-inner') this.container = document.querySelector('.tiny-masonry') // getting gap for calculate from grid this.gap = parseInt(getComputedStyle(this.container, 'gap').getPropertyValue('grid-gap').split(' ')[0]) // adding loaded event this.elements.forEach((element) => { const img = element.querySelector('img') if (img.completed) { this.calculate() } else { img.addEventListener('load', () => { this.calculate() }) } }) window.addEventListener('resize', throttle(300, () => { this.calculate() }), false) window.addEventListener('scroll', throttle(300, () => { this.calculate(true) }), false) } /** * * */ calculate(onlyVisible = false) { // getting number of columns if (!onlyVisible) { this.columns = Math.ceil(this.container.offsetWidth / this.elements[0].parentElement.offsetWidth) - 1 if (this.columns === 0) { this.columns = 1 } } this.height = [] for (let i = 0; i < this.elements.length; i++) { let marginTop = 0 // getting row let row = Math.round(i / this.columns) + 1 // reset margin-top for the first columns if (i < this.columns) { this.elements[i].parentElement.dataset.offsetMarginTop = 0 } // check for parent element and getting marginTop if (this.elements[i - this.columns] && !onlyVisible) { if (this.elements[i - this.columns].parentElement.dataset.offsetMarginTop) { marginTop += parseInt(this.elements[i - this.columns].parentElement.dataset.offsetMarginTop) } marginTop += this.elements[i - this.columns].offsetHeight } else { marginTop = this.elements[i].parentElement.dataset.offsetMarginTop } if (!onlyVisible) { this.elements[i].parentElement.dataset.offsetMarginTop = marginTop } if (window.pageYOffset <= (marginTop + this.elements[i].offsetHeight + (this.gap * row)) && (window.pageYOffset + window.innerHeight + (this.gap * row)) >= marginTop) { this.elements[i].parentElement.style.marginTop = marginTop + 'px' this.elements[i].parentElement.style.visibility = 'visible' } else { this.elements[i].parentElement.style.visibility = 'hidden' } // add complete height for element this.height.push(parseInt(marginTop) + parseInt(this.elements[i].offsetHeight) + (this.gap * row)) } // getting heighest height this.height = Math.max(...this.height) if (this.height > 0) { this.container.style.height = this.height + 'px' } } } export default Masonry