UNPKG

on-load

Version:

On load/unload events for DOM elements using a MutationObserver

104 lines (93 loc) 2.74 kB
/* global MutationObserver */ const document = require('global/document') const window = require('global/window') const watch = Object.create(null) const KEY_ID = 'onloadid' + Math.random().toString(36).slice(2) const KEY_ATTR = 'data-' + KEY_ID let INDEX = 0 if (window && window.MutationObserver) { const observer = new MutationObserver(function (mutations) { if (!isHashValid(watch)) return let i = mutations.length while (i--) { if (mutations[i].attributeName === KEY_ATTR) { eachAttr(mutations[i], turnon, turnoff) continue } eachMutation(mutations[i].removedNodes, function (index, el) { if (!document.documentElement.contains(el)) turnoff(index, el) }) eachMutation(mutations[i].addedNodes, function (index, el) { if (document.documentElement.contains(el)) turnon(index, el) }) } }) observer.observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeOldValue: true, attributeFilter: [KEY_ATTR] }) } module.exports = function onload (el, on, off, caller) { on = on || function () {} off = off || function () {} el.setAttribute(KEY_ATTR, 'o' + INDEX) watch['o' + INDEX] = [on, off, 0, caller || onload.caller] INDEX += 1 return el } module.exports.KEY_ATTR = KEY_ATTR module.exports.KEY_ID = KEY_ID function turnon (index, el) { if (watch[index][0] && watch[index][2] === 0) { watch[index][0](el) watch[index][2] = 1 } } function turnoff (index, el) { if (watch[index][1] && watch[index][2] === 1) { watch[index][1](el) watch[index][2] = 0 } } function eachAttr (mutation, on, off) { const newValue = mutation.target.getAttribute(KEY_ATTR) if (sameOrigin(mutation.oldValue, newValue)) { watch[newValue][2] = watch[mutation.oldValue][2] return } if (watch[mutation.oldValue]) { off(mutation.oldValue, mutation.target) } if (watch[newValue]) { on(newValue, mutation.target) } } function sameOrigin (oldValue, newValue) { if (!oldValue || !newValue) return false return watch[oldValue][3] === watch[newValue][3] } function eachMutation (nodes, fn) { const keys = Object.keys(watch) for (let i = 0; i < nodes.length; i++) { if (nodes[i] && nodes[i].getAttribute && nodes[i].getAttribute(KEY_ATTR)) { const onloadid = nodes[i].getAttribute(KEY_ATTR) keys.forEach(function (k) { if (onloadid === k) { fn(k, nodes[i]) } }) } if (nodes[i] && nodes[i].childNodes.length > 0) { eachMutation(nodes[i].childNodes, fn) } } } function isHashValid (hash) { /* eslint-disable no-unreachable-loop */ for (const k in hash) { return k } }