const Events = (() => {
const cache = new Map
const observer = new MutationObserver(function(mutations) {
for (let mutation of mutations) {
if (mutation.type === 'childList') {
if (mutation.removedNodes.length) {
console.log('element removed from the dom, removing all events for the element')
mutation.removedNodes.forEach(x => Events.remove(x))
}
}
}
})
// watch the dom for the element being deleted
observer.observe(document.body, { childList: true })
return {
add(el, type, fn, capture = false) {
let cached = cache.get(el)
if (!cached) {
cached = {}
cache.set(el, cached)
}
if (!cached[type]) {
cached[type] = new Set
}
cached[type].add(fn)
el.addEventListener(type, fn, capture)
},
remove(el, type, fn) {
const cached = cache.get(el)
if (!cached) {
return false
}
// remove all events for an event type
if (type && !fn) {
cached[type].forEach(fn => {
el.removeEventListener(type, fn)
})
cached[type] = new Set
}
// remove a specific event
else if (type && fn) {
el.removeEventListener(type, fn)
// remove the event from the cache
cached[type].delete(fn)
}
// remove all events for the element
else {
for (key in cached) {
cached[key].forEach(fn => {
el.removeEventListener(key, fn)
})
}
cache.delete(el)
}
},
show(el, type) {
const cached = cache.get(el)
if (!cached) {
return false
}
if (type) {
return cached[type]
}
return cached
}
}
})()
function onRightClick() {}
Events.add(document, 'contextmenu', onRightClick)
Events.remove(document, 'contextmenu', onRightClick) // remove a specific event callback
Events.remove(document, 'contextmenu') // remove specific event types from an element
Events.remove(document) // remove all events from an element
const testElement = document.querySelector('#test_element')
Events.add(testElement, 'click', function deleteSelf(e) {
this.parentNode.removeChild(this)
})
<div id="test_element">
when you <strong>click me</strong> I will be deleted from the DOM which will fire the MutationObserver to remove all my events
</div>