Created
February 18, 2016 07:51
-
-
Save dimsemenov/8780be09cb5f61213976 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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