photo-grid
Version:
A fully responsive, lightweight and fast image grid plugin with no dependencies
93 lines (79 loc) • 2.35 kB
JavaScript
/* @flow */
const defaultGridBasis = 200
const findGrids = () => effectAll(buildGrid)(document.querySelectorAll('.photo-grid'))
const effectAll = (func: (a: any) => void) => iterable => { for (const x of iterable) func(x) }
const imageLoaded = (elm, image, gridBasis) => {
// We'll be using the ratio to shrink each image
const ratio = image.width / image.height
if (elm instanceof HTMLElement) {
// This is the basis for our object.
elm.style.flexBasis = gridBasis * ratio + 'px'
// We'll then let each element grow dependent on it's width/height ratio.
elm.style.flexGrow = ratio.toString()
// We're ready to show the photo to the public.
elm.classList.add('photo-grid-loaded')
}
}
const imageRatio = (gridBasis: number) => (elm: HTMLElement) => {
const image = elm.querySelector(':scope img')
if(image instanceof HTMLImageElement) {
if (image && image.complete) {
imageLoaded(elm, image, gridBasis)
} else {
image.onload = () => imageLoaded(elm, image, gridBasis)
}
}
}
const buildGrid = (grid: HTMLElement) => {
const gridBasis = parseInt(grid.dataset.gridBasis || defaultGridBasis, 10)
effectAll(imageRatio(gridBasis))(grid.children)
// The fake elements are used to make the last few images get decent sized.
appendFakeElement(grid, gridBasis)
}
const appendFakeElement = (grid, gridBasis) => {
const li = document.createElement('li')
li.classList.add('photo-grid-fake')
li.style.flexBasis = gridBasis * (4 / 3) + 'px'
li.style.flexGrow = (4 / 3).toString()
effectAll(() => {grid.appendChild(li.cloneNode(true))})(Array(10))
}
const addCss = () => {
const css = `
.photo-grid {
display: flex;
flex-wrap: wrap;
padding: 0;
list-style:none;
}
.photo-grid img {
width: 100%;
}
.photo-grid > li {
position: relative;
margin: 2px;
line-height: 0;
cursor: pointer;
display: none;
}
.photo-grid > .photo-grid-fake {
margin: 0 2px;
display: initial;
}
.photo-grid > .photo-grid-loaded {
display: initial;
}
`
const sheet = Object.assign(document.createElement('style'), {innerHTML: css})
if(document.head) {
document.head.appendChild(sheet)
}
}
// Add the css needed. This could potentially be broken out to a css file
addCss()
document.addEventListener(
'DOMContentLoaded',
() => {
findGrids()
},
false
)