Sometimes we are testing a page element or component that, when the page has loaded, lies outside of the viewport. This has the simple consequence that you should not count this page load as a visitor to your test. Only when the element you are testing scrolls into view, the visitor can be added to your test. To accomplish this, we needed some code that keeps track of the elements position on the page with regard to the page’s dimensions.
This one still relies on jQuery, I’ll upload a JS only version soon.
var notifyEnterViewport = function(o) { var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame, l = $(window).height(), r = $(window), t = r.scrollTop(), enter = function(e) { e.addClass("MM_inside_viewport"), e.hasClass("MM_outside_viewport") && e.removeClass("MM_outside_viewport") }, exit = function(e) { e.addClass("MM_outside_viewport"), e.hasClass("MM_inside_viewport") && e.removeClass("MM_inside_viewport") }, loop = function() { var e = r.scrollTop(); t !== e && (t = e, o.length && $.each(o, function(e) { var o = $(this), raf = o.height(), t = o.offset().top, loop = t - r.scrollTop(), n = t - r.scrollTop() + raf; 0 <= loop && n <= l && !o.hasClass("MM_inside_viewport") && (console.log("test: element " + (e + 1) + " scrolled into view"), enter(o)), (n < 0 || l < loop) && !o.hasClass("MM_outside_viewport") && (console.log("test: element " + (e + 1) + " scrolled out of view"), exit(o)) })), raf(loop) }; raf && loop(); } elementsToCheck = $("div#checkThisElement"); notifyEnterViewport(elementsToCheck);
- UPDATE!
var notifyEnterViewport = function(el) {
var w = window,
raf = w.requestAnimationFrame,
vpHeight = w.innerHeight,
lastPgYO = w.pageYOffset,
scroll = function() {
var height = el.offsetHeight,
elOffset = offSet(el),
top = elOffset.top,
pTop = top - w.pageYOffset,
pBottom = pTop + height;
if (pTop >= 0 && pBottom <= vpHeight && !el.classList.contains('mm_enter')) {
enter(el);
}
if ((pBottom < 0 || pTop > vpHeight) && !el.classList.contains('mm_exit')) {
exit(el);
}
},
offSet = function(el) {
var rect = el.getBoundingClientRect(),
pgxo = w.pageXOffset,
pgyo = w.pageYOffset;
return {
top: rect.top + pgyo,
left: rect.left + pgxo
};
},
enter = function(el) {
//console.log("enter: ", el);
el.classList.add('mm_enter');
el.classList.remove('mm_exit');
},
exit = function(el) {
//console.log("exit: ", el);
el.classList.add('mm_exit');
el.classList.remove('mm_enter');
},
loop = function() {
var PgYO = w.pageYOffset;
if (lastPgYO === PgYO) {
raf(loop);
return;
} else {
lastPgYO = PgYO;
scroll();
raf(loop);
}
};
if (raf) loop();
};
// call:
notifyEnterViewport(document.querySelector('ul#sub_nav > li.active:not(.first)'));