Skip to content

Commit 99291b1

Browse files
committed
Create tickers and events utils
1 parent c8d4e7c commit 99291b1

File tree

5 files changed

+271
-3711
lines changed

5 files changed

+271
-3711
lines changed

assets/scripts/utils/debounce.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

assets/scripts/utils/events.js

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
import { debounce } from './tickers'
2+
3+
CUSTOM_EVENT_LISTENERS = []
4+
5+
/**
6+
* Check if element is Window
7+
* @param {DOMElement} $el - Element to check
8+
* @return {boolean} True if window
9+
*/
10+
11+
const isWindow = $el => $el === window
12+
13+
14+
/**
15+
* Check if element is a DOM element
16+
* @param {DOMElement} $el - Element to check
17+
* @return {boolean} True if dom element
18+
*/
19+
20+
const isDomElement = $el => ($el instanceof Element || $el instanceof HTMLDocument || $el instanceof HTMLDocument)
21+
22+
23+
/**
24+
* Check if element is Window or DOM element
25+
* @param {Element} $el - Element to check
26+
* @return {boolean} True if window or DOM element
27+
*/
28+
29+
const isValidElement = $el => (isWindow($el) || isDomElement($el))
30+
31+
32+
/**
33+
* Check if element already has the event attached
34+
* @param {Element} $el - Element where the event is attached
35+
* @param {String} event - The event name
36+
* @return {Boolean} True if the event is already attached to the element
37+
*/
38+
39+
const customEventIsDefined = ($el, event) => CUSTOM_EVENT_LISTENERS.findIndex(e => e.$el === $el && e.event === event) > -1
40+
41+
42+
/**
43+
* Add custom event to event storage
44+
* @param {Element} $el - Element where the event is attached
45+
* @param {String} event - The event name
46+
* @return {void}
47+
*/
48+
49+
const addCustomEvent = ($el, event) => {
50+
if(!customEventIsDefined($el, event)) {
51+
CUSTOM_EVENT_LISTENERS.push({
52+
$el,
53+
event
54+
})
55+
}
56+
}
57+
58+
59+
/**
60+
* Create a sarting event for the event triggered
61+
* @param {Element} EventTarget - Element to bind the event to
62+
* @param {object} event - The triggered event's name
63+
* @return {void}
64+
*/
65+
66+
const addStartEvent = (EventTarget, event, delay = 200) => {
67+
68+
const eventName = `${event}Start`
69+
70+
// Check element
71+
if(!isValidElement(EventTarget)) {
72+
console.warn(`[addStartEvent:${eventName}]: Wrong parameter '${el}'. The parameter must be document, window or a DOM element`)
73+
return
74+
}
75+
76+
// Check if event already exists
77+
if(customEventIsDefined(EventTarget, eventName)) {
78+
console.log(`[addStartEvent:${eventName}]: Already exists for '${el}' element`)
79+
return
80+
}
81+
82+
// Register element and event
83+
addCustomEvent(EventTarget, eventName)
84+
85+
// Create event
86+
const startEvent = new CustomEvent(eventName)
87+
EventTarget.addEventListener(event, debounce(() => {
88+
EventTarget.dispatchEvent(startEvent)
89+
}, delay, true))
90+
}
91+
92+
/**
93+
* Create an ending event for the event triggered
94+
* @param {Element} EventTarget - Element to bind the event to
95+
* @param {object} event - The triggered event's name
96+
* @return {void}
97+
*/
98+
99+
const addEndEvent = (EventTarget, event, delay = 200) => {
100+
101+
const eventName = `${event}End`
102+
103+
// Check element
104+
if(!isValidElement(EventTarget)) {
105+
console.warn(`[addEndEvent:${eventName}]: Wrong parameter '${el}'. The parameter must be document, window or a DOM element`)
106+
return
107+
}
108+
109+
// Check if event already exists
110+
if(customEventIsDefined(EventTarget, eventName)) {
111+
console.log(`[addEndEvent:${eventName}]: Already exists for '${el}' element`)
112+
return
113+
}
114+
115+
// Register element and event
116+
addCustomEvent(EventTarget, eventName)
117+
118+
// Create event
119+
const endEvent = new CustomEvent(eventName)
120+
EventTarget.addEventListener(event, debounce(() => {
121+
EventTarget.dispatchEvent(endEvent)
122+
}, delay))
123+
}
124+
125+
126+
/**
127+
* Add scrollUp event to element (window by default)
128+
* @param {Element} EventTarget - Element to bind the event to
129+
* @return {void}
130+
*/
131+
132+
const addScrollUpEvent = (EventTarget = window) => {
133+
134+
// Check element
135+
if(!isValidElement(EventTarget)) {
136+
console.warn(`[addScrollUpEvent]: Wrong parameter '${el}'. The parameter must be window or a DOM element`)
137+
return
138+
}
139+
140+
let scrollTop = EventTarget.scrollTop
141+
let previousScrollTop = scrollTop
142+
let direction = 0
143+
const scrollUp = new CustomEvent('scrollUp')
144+
const scrollProperty = isWindow(EventTarget) ? 'scrollY' : 'scrollTop'
145+
146+
EventTarget.addEventListener('scroll', e => {
147+
scrollTop = EventTarget[scrollProperty]
148+
149+
// Scroll up
150+
if(scrollTop < previousScrollTop && direction > -1) {
151+
EventTarget.dispatchEvent(scrollUp)
152+
direction = -1
153+
154+
// Scroll down
155+
} else if(scrollTop > previousScrollTop && direction < 1) {
156+
direction = 1
157+
}
158+
159+
previousScrollTop = scrollTop
160+
})
161+
}
162+
163+
164+
/**
165+
* Add scrollDown event to element (window by default)
166+
* @param {Element} EventTarget - Element to bind the event to
167+
* @return {void}
168+
*/
169+
170+
const addScrollDownEvent = (EventTarget = window) => {
171+
172+
// Check element
173+
if(!isValidElement(EventTarget)) {
174+
console.warn(`[addScrollDownEvent]: Wrong parameter '${el}'. The parameter must be window or a DOM element`)
175+
return
176+
}
177+
178+
let scrollTop = EventTarget.scrollTop
179+
let previousScrollTop = scrollTop
180+
let direction = 0
181+
const scrollDown = new CustomEvent('scrollDown')
182+
const scrollProperty = isWindow(EventTarget) ? 'scrollY' : 'scrollTop'
183+
184+
EventTarget.addEventListener('scroll', e => {
185+
scrollTop = EventTarget[scrollProperty]
186+
187+
// Scroll up
188+
if(scrollTop < previousScrollTop && direction > -1) {
189+
direction = -1
190+
191+
// Scroll down
192+
} else if(scrollTop > previousScrollTop && direction < 1) {
193+
EventTarget.dispatchEvent(scrollDown)
194+
direction = 1
195+
}
196+
197+
previousScrollTop = scrollTop
198+
})
199+
}
200+
201+
export {
202+
addStartEvent,
203+
addEndEvent,
204+
addScrollUpEvent,
205+
addScrollDownEvent,
206+
}

assets/scripts/utils/tickers.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Debounce function: fire the callback before/after the action has finished for the defined amount of time
3+
* @param {function} callback - callback function
4+
* @param {number} delay - waiting time in milisecond
5+
* @param {boolean} immediate - triggers before or after delay
6+
* @return {function} callback
7+
*/
8+
9+
const debounce = (callback, delay, immediate = false) => {
10+
let timeout = null
11+
12+
return (...args) => {
13+
clearTimeout(timeout)
14+
15+
const later = () => {
16+
timeout = null
17+
if (!immediate) {
18+
callback(...args)
19+
}
20+
}
21+
22+
if (immediate && !timeout) {
23+
callback(...args)
24+
}
25+
26+
timeout = setTimeout(later, delay)
27+
}
28+
}
29+
30+
31+
/**
32+
* Throttle function: fire the callback while the action is being performed for the defined iteration time
33+
* @param {function} callback - callback function
34+
* @param {number} delay - waiting time in milisecond
35+
* @return {function} callback
36+
*/
37+
38+
const throttle = (callback, delay) => {
39+
let timeout = false
40+
41+
return (...args) => {
42+
if (!timeout) {
43+
timeout = true
44+
45+
callback(...args)
46+
47+
setTimeout(() => {
48+
timeout = false
49+
}, delay)
50+
}
51+
}
52+
}
53+
54+
55+
export {
56+
debounce,
57+
throttle
58+
}

0 commit comments

Comments
 (0)