UNPKG

choo-shortcache

Version:

choo nanocomponent cache shortcut

103 lines (93 loc) 2.72 kB
/* global MutationObserver */ var document = require('global/document') var window = require('global/window') var assert = require('assert') var watch = Object.create(null) var KEY_ID = 'onloadid' + (new Date() % 9e6).toString(36) var KEY_ATTR = 'data-' + KEY_ID var INDEX = 0 if (window && window.MutationObserver) { var observer = new MutationObserver(function (mutations) { if (Object.keys(watch).length < 1) return for (var i = 0; i < mutations.length; i++) { if (mutations[i].attributeName === KEY_ATTR) { eachAttr(mutations[i], turnon, turnoff) continue } eachMutation(mutations[i].removedNodes, turnoff) eachMutation(mutations[i].addedNodes, turnon) } }) if (document.body) { beginObserve(observer) } else { document.addEventListener('DOMContentLoaded', function (event) { beginObserve(observer) }) } } function beginObserve (observer) { observer.observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeOldValue: true, attributeFilter: [KEY_ATTR] }) } module.exports = function onload (el, on, off, caller) { assert(document.body, 'on-load: will not work prior to DOMContentLoaded') 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) { var newValue = mutation.target.getAttribute(KEY_ATTR) if (sameOrigin(mutation.oldValue, newValue)) { watch[newValue] = watch[mutation.oldValue] 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) { var keys = Object.keys(watch) for (var i = 0; i < nodes.length; i++) { if (nodes[i] && nodes[i].getAttribute && nodes[i].getAttribute(KEY_ATTR)) { var onloadid = nodes[i].getAttribute(KEY_ATTR) keys.forEach(function (k) { if (onloadid === k) { fn(k, nodes[i]) } }) } if (nodes[i].childNodes.length > 0) { eachMutation(nodes[i].childNodes, fn) } } }