import throttle from 'lodash/throttle';
import customEvent from '../utils/customEvent';
import supportsPassiveEvent from '../utils/supportsPassiveEvent';
/**
* ScrollHandler
*
* Monitor scroll event and apply custom css to indicate
* if the user is scrolling up or down a page.
*
* @module ScrollHandler
*/
const ScrollHandler = {
selectors: {
scrollListener: '[data-scrollListener]',
container: '.l-container',
},
states: {
up: 'is-scrolling-up',
down: 'is-scrolling-down',
},
thresholds: {
top: 0,
scroll: 100,
},
currentScrollY: 0,
currentDirection: '',
$container: false,
init() {
if ( document.querySelectorAll( this.selectors.scrollListener ).length > 0 ) {
this.$container = document.querySelector( this.selectors.container );
// If browser supports passive event, add passive option.
// This is done so handling of the scroll event does not block the scrolling itself
window.addEventListener( 'scroll', throttle( () => {
this.handleScroll();
}, 200 ), supportsPassiveEvent ? { passive: true } : false );
}
},
/**
* Handles page scrolling
*
* @method handleScroll
*/
handleScroll() {
// Determine scroll direction.
let direction = '';
let distance = window.pageYOffset - this.currentScrollY;
if ( distance > 0 ) {
// scrolling down
direction = 'down';
} else if ( distance < 0 ) {
// scrolling up
direction = 'up';
}
distance = Math.abs( distance );
// When the scroll position does not exceed the top threshold
// consider user has scrolled to the top.
if ( window.pageYOffset <= this.thresholds.top ) {
// Remove scroll direction css classes.
this.$container.classList.remove( this.states.up );
this.$container.classList.remove( this.states.down );
// Reset the current scroll direction.
this.currentDirection = '';
// Dispatch event to flag scroll to top.
customEvent.fire( window, customEvent.SCROLLED_TO_TOP, {});
return;
}
// Remember scroll position.
this.currentScrollY = window.pageYOffset;
// Fire event whenever the scroll distance is beyond the threshold.
if ( distance >= this.thresholds.scroll ) {
customEvent.fire( window, customEvent.SCROLLED, {
direction,
distance,
});
}
// Scroll direction changed.
if ( direction !== this.currentDirection ) {
// Add / remove css class based on scroll direction.
this.$container.classList.remove( this.states[this.currentDirection]);
this.$container.classList.add( this.states[direction]);
// Remember the current scroll direction.
this.currentDirection = direction;
// Dispatch event to flag change of scroll direction.
customEvent.fire( window, customEvent.SCROLL_DIRECTION_CHANGED, {
direction,
distance,
});
}
},
};
export default ScrollHandler;