/**
Keeps track of the furthest point on page that user has scrolled to
@memberof module:Viki
**/
class ScrollTracker {
/**
@constructor
**/
constructor() {
this.storage = [];
this.lastPos = Infinity;
this.startPos = window.scrollY;
this.direction = 1;
this.thresh = 0;
this.scrollTrackHandler = this.scrollTrackHandler.bind(this);
this.waiting = true;
}
/**
Start tracking
**/
init() {
this.startPos = window.scrollY;
this.store(this.startPos);
window.addEventListener('scroll', this.scrollTrackHandler);
}
scrollTrackHandler() {
if (this.waiting) {
window.requestAnimationFrame(() => {
const currPos = window.scrollY;
// Save coordinate if direction changes
if (this.lastPos !== Infinity && (currPos - this.lastPos) * this.direction < this.thresh) {
this.store(currPos);
this.startPos = currPos;
this.direction *= -1;
}
this.lastPos = currPos;
this.waiting = true;
});
}
this.waiting = false;
}
/**
Save scroll y coordinate
@param {Number} y y-coordinate to store
**/
store(y) {
this.storage.push(y);
}
/**
Percentage of document that appears on user's viewport
@returns {Number}
**/
percentageSeen() {
this.store(window.scrollY);
const furthestScrolled = Math.max.apply(null, this.storage) || 0;
const viewportHeight = (window.innerHeight || document.documentElement.clientHeight);
const furthestViewport = furthestScrolled + viewportHeight;
const docRect = document.documentElement.getBoundingClientRect();
const docHeight = docRect.height;
const res = Math.ceil((furthestViewport / docHeight) * 100);
return res;
}
/**
Percentage of document that appears on user's viewport rounded to given granularity
@param {Number} [granularity=10] - granularity of rounding
@returns {Number}
**/
percentageSeenRounded(granularity = 10) {
const seen = this.percentageSeen();
const res = Math.round(seen / granularity) * granularity;
return res;
}
}
module.exports = ScrollTracker;