Refactor clickoutside util to use a single event listener rather than many, and add support for ignoring certain classes
This commit is contained in:
parent
abedb5d9eb
commit
92b7b04e14
|
@ -1,18 +1,54 @@
|
||||||
export default function clickOutside(element, callbackFunction) {
|
const ignoredClasses = [".flatpickr-calendar"]
|
||||||
function onClick(event) {
|
let clickHandlers = []
|
||||||
if (!element.contains(event.target)) {
|
|
||||||
callbackFunction?.(event)
|
/**
|
||||||
|
* Handle a body click event
|
||||||
|
*/
|
||||||
|
const handleClick = event => {
|
||||||
|
// Ignore click if needed
|
||||||
|
for (let className of ignoredClasses) {
|
||||||
|
if (event.target.closest(className)) {
|
||||||
|
console.log("ignore")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.addEventListener("click", onClick, true)
|
// Process handlers
|
||||||
|
clickHandlers.forEach(handler => {
|
||||||
|
if (!handler.element.contains(event.target)) {
|
||||||
|
handler.callback?.(event)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
document.documentElement.addEventListener("click", handleClick, true)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds or updates a click handler
|
||||||
|
*/
|
||||||
|
const updateHandler = (id, element, callback) => {
|
||||||
|
let existingHandler = clickHandlers.find(x => x.id === id)
|
||||||
|
if (!existingHandler) {
|
||||||
|
clickHandlers.push({ id, element, callback })
|
||||||
|
} else {
|
||||||
|
existingHandler.callback = callback
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a click handler
|
||||||
|
*/
|
||||||
|
const removeHandler = id => {
|
||||||
|
clickHandlers = clickHandlers.filter(x => x.id !== id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Svelte action to apply a click outside handler for a certain element
|
||||||
|
*/
|
||||||
|
export default (element, callback) => {
|
||||||
|
const id = Math.random()
|
||||||
|
updateHandler(id, element, callback)
|
||||||
return {
|
return {
|
||||||
update(newCallbackFunction) {
|
update: newCallback => updateHandler(id, element, newCallback),
|
||||||
callbackFunction = newCallbackFunction
|
destroy: () => removeHandler(id),
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
document.body.removeEventListener("click", onClick, true)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue