1
0
mirror of https://github.com/locomotivemtl/locomotive-boilerplate.git synced 2026-01-15 00:55:08 +08:00
Files
locomotive-boilerplate/assets/scripts/utils/events.js
2022-05-26 13:32:52 +02:00

231 lines
5.8 KiB
JavaScript

import { debounce } from './tickers'
CUSTOM_EVENT_LISTENERS = []
/**
* Check if element is Window
* @param {DOMElement} $el - Element to check
* @return {boolean} True if window
*/
const isWindow = $el => $el === window
/**
* Check if element is a DOM element
* @param {DOMElement} $el - Element to check
* @return {boolean} True if dom element
*/
const isDomElement = $el => ($el instanceof Element || $el instanceof HTMLDocument || $el instanceof HTMLDocument)
/**
* Check if element is Window or DOM element
* @param {Element} $el - Element to check
* @return {boolean} True if window or DOM element
*/
const isValidElement = $el => (isWindow($el) || isDomElement($el))
/**
* Check if element already has the event attached
* @param {Element} $el - Element where the event is attached
* @param {String} event - The event name
* @return {Boolean} True if the event is already attached to the element
*/
const getCustomEventIndex = ($el, event) => CUSTOM_EVENT_LISTENERS.findIndex(e => e.$el === $el && e.event === event)
/**
* Check if element already has the event attached
* @param {Element} $el - Element where the event is attached
* @param {String} event - The event name
* @return {Boolean} True if the event is already attached to the element
*/
const customEventIsDefined = ($el, event) => getCustomEventIndex($el, event) > -1
/**
* Add custom event to event storage
* @param {Element} $el - Element where the event is attached
* @param {String} event - The event name
* @return {void}
*/
const addCustomEvent = ($el, event) => {
if(!customEventIsDefined($el, event)) {
CUSTOM_EVENT_LISTENERS.push({
$el,
event
})
}
}
/**
* Remove custom event to event storage
* @param {Element} $el - Element where the event is attached
* @param {String} event - The event name
* @return {void}
*/
const removeCustomEvent = ($el, event) => {
const customEventIndex = getCustomEventIndex($el, event)
if(customEventIndex > -1) {
CUSTOM_EVENT_LISTENERS.splice(customEventIndex, 1)
}
}
/**
* Create a sarting event for the event triggered
* @param {Element} $el - Element to bind the event to
* @param {object} event - The triggered event's name
* @return {void}
*/
const addStartEvent = ($el, event, delay = 200) => {
// Check element
if(!isValidElement($el)) {
console.warn(`[addStartEvent:${event}]: Wrong parameter '${el}'. The parameter must be document, window or a DOM element`)
return
}
const eventName = `${event}Start`
// Check if event already exists
if(customEventIsDefined($el, eventName)) {
return
}
// Register element and event
addCustomEvent($el, eventName)
// Create event
const startEvent = new CustomEvent(eventName)
$el.addEventListener(event, debounce(() => {
$el.dispatchEvent(startEvent)
}, delay, true))
}
/**
* Create an ending event for the event triggered
* @param {Element} $el - Element to bind the event to
* @param {object} event - The triggered event's name
* @return {void}
*/
const addEndEvent = ($el, event, delay = 200) => {
// Check element
if(!isValidElement($el)) {
console.warn(`[addEndEvent:${event}]: Wrong parameter '${el}'. The parameter must be document, window or a DOM element`)
return
}
const eventName = `${event}End`
// Check if event already exists
if(customEventIsDefined($el, eventName)) {
return
}
// Register element and event
addCustomEvent($el, eventName)
// Create event
const endEvent = new CustomEvent(eventName)
$el.addEventListener(event, debounce(() => {
$el.dispatchEvent(endEvent)
}, delay))
}
/**
* Add scrollUp event to element (window by default)
* @param {Element} $el - Element to bind the event to
* @return {void}
*/
const addScrollUpEvent = ($el = window) => {
// Check element
if(!isValidElement($el)) {
console.warn(`[addScrollUpEvent]: Wrong parameter '${el}'. The parameter must be window or a DOM element`)
return
}
let scrollTop = $el.scrollTop
let previousScrollTop = scrollTop
let direction = 0
const scrollUp = new CustomEvent('scrollUp')
const scrollProperty = isWindow($el) ? 'scrollY' : 'scrollTop'
$el.addEventListener('scroll', e => {
scrollTop = $el[scrollProperty]
// Scroll up
if(scrollTop < previousScrollTop && direction > -1) {
$el.dispatchEvent(scrollUp)
direction = -1
// Scroll down
} else if(scrollTop > previousScrollTop && direction < 1) {
direction = 1
}
previousScrollTop = scrollTop
})
}
/**
* Add scrollDown event to element (window by default)
* @param {Element} $el - Element to bind the event to
* @return {void}
*/
const addScrollDownEvent = ($el = window) => {
// Check element
if(!isValidElement($el)) {
console.warn(`[addScrollDownEvent]: Wrong parameter '${el}'. The parameter must be window or a DOM element`)
return
}
let scrollTop = $el.scrollTop
let previousScrollTop = scrollTop
let direction = 0
const scrollDown = new CustomEvent('scrollDown')
const scrollProperty = isWindow($el) ? 'scrollY' : 'scrollTop'
$el.addEventListener('scroll', e => {
scrollTop = $el[scrollProperty]
// Scroll up
if(scrollTop < previousScrollTop && direction > -1) {
direction = -1
// Scroll down
} else if(scrollTop > previousScrollTop && direction < 1) {
$el.dispatchEvent(scrollDown)
direction = 1
}
previousScrollTop = scrollTop
})
}
export {
addStartEvent,
addEndEvent,
addScrollUpEvent,
addScrollDownEvent,
removeCustomEvent
}