Last active
October 4, 2016 15:28
-
-
Save kotarok/f6628beb91168a72fd02 to your computer and use it in GitHub Desktop.
Watch if the given element is in viewport and fires 'inview' and 'outview' event respectively.
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
var watchInview = function(el) { | |
// Get most closest element which has scrollbar. | |
var scrollContainer = getAncestors(el).find(function(el) { | |
return el.scrollHeight > el.offsetHeight || el.scrollWidth > el.offsetWidth; | |
}); | |
el.scrollContainer = | |
(scrollContainer instanceof HTMLBodyElement)? window: scrollContainer; | |
el.scrollListener_ = function() { | |
var reveal = getReveal(el, el.scrollContainer); | |
var isInview = (reveal.x && reveal.y); | |
if (isInview && !el.wasInview) { | |
el.dispatchEvent(new Event('inview')); | |
el.wasInview = true; | |
} else if (!isInview && el.wasInview) { | |
el.dispatchEvent(new Event('outview')); | |
el.wasInview = false; | |
} | |
}; | |
el.scrollContainer.addEventListener('scroll', el.scrollListener_); | |
if (el !== window) { // To initialise elements already in revealed. | |
el.scrollContainer.scrollTop = 1; | |
el.scrollContainer.scrollTop = 0; | |
} | |
}; | |
var unwatchInview = function(el) { | |
el.scrollContainer.removeEventListener('scroll', el.scrollListener_); | |
}; | |
var getAncestors = function(el) { | |
var els = []; | |
while ((el = getParent(el))) els.push(el); | |
return els; | |
}; | |
var getParent = function(el) { | |
var pel = el.parentNode; | |
return (pel instanceof HTMLElement)? pel: undefined; | |
}; | |
var getReveal = function(el, container) { | |
var cRect = (container === window || undefined)? { | |
left: 0, width: window.innerWidth, | |
top: 0, height: window.innerHeight, | |
}: container.getBoundingClientRect(); | |
var eRect = el.getBoundingClientRect(); | |
/** | |
* Calculate reveal ratio of element to container by given params | |
* @private | |
* @return {Number} Ratio of revealed ration in between 0 and 1. | |
*/ | |
var calcReveal_ = function(start, end, axis, result) { | |
revStart = (cRect[axis] + cRect[start] - eRect[start]) / eRect[axis]; | |
revEnd = (eRect[end] - cRect[start]) / eRect[axis]; | |
result = Math.min(revStart, revEnd); | |
return (result > 1)? 1: (result < 0)? 0: result; | |
}; | |
return { | |
x: calcReveal_('left', 'right', 'width'), | |
y: calcReveal_('top', 'bottom', 'height') | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment