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 changed files with 48 additions and 12 deletions
|
@ -1,18 +1,54 @@
|
|||
export default function clickOutside(element, callbackFunction) {
|
||||
function onClick(event) {
|
||||
if (!element.contains(event.target)) {
|
||||
callbackFunction?.(event)
|
||||
const ignoredClasses = [".flatpickr-calendar"]
|
||||
let clickHandlers = []
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
return {
|
||||
update(newCallbackFunction) {
|
||||
callbackFunction = newCallbackFunction
|
||||
},
|
||||
destroy() {
|
||||
document.body.removeEventListener("click", onClick, 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 {
|
||||
update: newCallback => updateHandler(id, element, newCallback),
|
||||
destroy: () => removeHandler(id),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue