Skip to content

Instantly share code, notes, and snippets.

@w33zy
Forked from dimsemenov/mini-masonry-grid.js
Created January 8, 2018 02:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save w33zy/47103265d4a4dddcbf18ba91438680c4 to your computer and use it in GitHub Desktop.
Save w33zy/47103265d4a4dddcbf18ba91438680c4 to your computer and use it in GitHub Desktop.
(function(window) {
'use strict';
var toggleEvent = function(el, name, fn, unbind) {
var methodName = (unbind ? 'remove' : 'add') + 'EventListener';
el[methodName](name, fn, false);
};
window.MicroMasonryGrid = function(gallery, newOpts) {
var self = this,
thumbElements = gallery.childNodes,
figureEl,
columnHeights,
columnItems,
gridWidth,
columnWidth,
i,
windowHeight,
galleryRect,
galleryInitialYOffset,
numColumns,
localPageYOffset;
var opts = self.opts = {
cols: function(){return 3},
gap: 10,
src: 'data-m-src',
getHeight: function(el, columnWidth) {
return Math.round( columnWidth / Number(el.getAttribute('data-ratio')) );
},
addImage: function(el) {
var img = new Image();
// "this" is options object
var srcSet = el.getAttribute('data-m-srcset');
if(srcSet) {
img.setAttribute('srcset',srcSet);
}
img.src = el.getAttribute(this.src);
el.children[0].insertBefore(img, el.children[0].firstChild);
//el.children[0].appendChild(img);
}
};
for (var n in newOpts) {
opts[n] = newOpts[n];
}
var itemsToPaint = {},
totalHeight;
var calc = function() {
localPageYOffset = window.pageYOffset;
// create empty arrays for columns
columnHeights = [];
columnItems = [];
galleryRect = gallery.getBoundingClientRect();
galleryInitialYOffset = galleryRect.top + localPageYOffset;
windowHeight = window.innerHeight;
gridWidth = galleryRect.right - galleryRect.left;
i = numColumns = opts.cols(gridWidth);
while(i--) {
columnHeights.push(0);
columnItems.push([]);
}
columnWidth = ( gridWidth - opts.gap * (numColumns-1) ) / numColumns;
columnWidth = Math.round(columnWidth * 100) / 100; // leave two decimal points
for(i = 0; i < thumbElements.length; i++) {
figureEl = thumbElements[i];
if(figureEl.nodeType !== 1) {
continue;
}
// Find the key of the smallest column.
var smallestColumnIndex = 0,
tempVal = columnHeights[0];
for(var q = 1; q < numColumns; q++) {
if(columnHeights[q] < tempVal) {
smallestColumnIndex = q;
tempVal = columnHeights[q];
}
}
var itemHeight = opts.getHeight(figureEl, columnWidth);
var itemYPosition = columnHeights[smallestColumnIndex];
var itemData;
itemsToPaint[i] = {
width: columnWidth + 'px',
height: itemHeight + 'px',
top: itemYPosition + 'px',
left: columnWidth * smallestColumnIndex + (smallestColumnIndex * opts.gap) + 'px'
};
if(opts.src && figureEl.getAttribute(opts.src)) {
itemData = {
el:figureEl,
h:itemHeight + opts.gap,
tH: itemYPosition
};
}
columnItems[smallestColumnIndex].push(itemData);
columnHeights[smallestColumnIndex] += itemHeight + opts.gap;
}
};
var paint = function() {
for(i = 0; i < thumbElements.length; i++) {
if(itemsToPaint[i]) {
var elStyle = thumbElements[i].style;
elStyle.width = itemsToPaint[i].width;
elStyle.height = itemsToPaint[i].height;
elStyle.top = itemsToPaint[i].top;
elStyle.left = itemsToPaint[i].left;
}
}
gallery.style.height = Math.max.apply(0, columnHeights) + 'px';
//self.lazyLoad();
};
self.lazyLoad = function() {
if(!opts.src) {
return;
}
var pageOffset = localPageYOffset - galleryInitialYOffset,
col,
item;
for(var c = 0; c < numColumns; c++) {
col = columnItems[c];
for(i = 0; i < col.length; i++) {
item = col[i];
if(!item) {
continue;
}
var extraGap = 50;
var tempGap = 0; // TEMP
if(
pageOffset+windowHeight+extraGap-tempGap >= item.tH &&
pageOffset-extraGap+tempGap <= (item.tH + item.h)
) {
opts.addImage(item.el);
item.el.removeAttribute(opts.src);
col[i] = null;
}
}
}
};
// Throttle scroll (fire once per 100ms)
var throttleTimer,
onPageScroll = function() {
if(!throttleTimer) {
localPageYOffset = window.pageYOffset;
self.lazyLoad();
throttleTimer = setTimeout(function() {
localPageYOffset = window.pageYOffset;
self.lazyLoad();
throttleTimer = 0;
}, 100);
}
};
/**
* Adds/removes scroll event, resize event, and their debouce/throttle timers.
* @param {boolean} remove Set to true to remove.
*/
self.toggleEvents = function(remove) {
toggleEvent(window, 'scroll', onPageScroll, remove);
toggleEvent(window, 'magnificCalc', calc, remove);
toggleEvent(window, 'magnificPaint', paint, remove);
//toggleEvent(window, 'resize', onPageResize, remove);
if(remove) {
clearTimeout(debounceTimer);
clearTimeout(throttleTimer);
}
};
//self.build();
self.toggleEvents();
};
})(window);
var init = function() {
// loop through all gallery elements and bind events
var galleryElements = document.querySelectorAll('.micro-masonry-grid');
for(var i = 0, l = galleryElements.length; i < l; i++) {
window.masonryTest = new MicroMasonryGrid(galleryElements[i], {
cols:function(w) {
return Math.round(w/210);
}
});
}
};
init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment