UNPKG

uconnect

Version:

An essential connected/disconnected DOM helper

113 lines (95 loc) 3.71 kB
self.uconnect = (function (exports) { 'use strict'; /** * @typedef {Object} Handler an object that handle events. * @property {(event: Event) => void} connected an optional method triggered when node is connected. * @property {(event: Event) => void} disconnected an optional method triggered when node is disconnected. */ /** * @typedef {Object} UConnect an utility to connect or disconnect nodes to observe. * @property {(node: Node, handler?: Handler) => void} connect a method to start observing a generic Node. * @property {(node: Node) => void} disconnect a method to stop observing a generic Node. * @property {() => void} kill a method to kill/disconnect the MutationObserver. */ /** * Attach a MutationObserver to a generic node and returns a UConnect instance. * @param {Node} root a DOM node to observe for mutations. * @param {string} parse the kind of nodes to parse: children, by default, or childNodes. * @param {Event} CE an Event/CustomEvent constructor (polyfilled in SSR). * @param {MutationObserver} MO a MutationObserver constructor (polyfilled in SSR). * @returns {UConnect} an utility to connect or disconnect nodes to observe. */ var observe = function observe(root, parse, CE, MO) { var observed = new WeakMap(); // these two should be WeakSet but IE11 happens var wmin = new WeakMap(); var wmout = new WeakMap(); var has = function has(node) { return observed.has(node); }; var disconnect = function disconnect(node) { if (has(node)) { listener(node, node.removeEventListener, observed.get(node)); observed["delete"](node); } }; var connect = function connect(node, handler) { disconnect(node); if (!(handler || (handler = {})).handleEvent) handler.handleEvent = handleEvent; listener(node, node.addEventListener, handler); observed.set(node, handler); }; var listener = function listener(node, method, handler) { method.call(node, 'disconnected', handler); method.call(node, 'connected', handler); }; var notifyObserved = function notifyObserved(nodes, type, wmin, wmout) { for (var length = nodes.length, i = 0; i < length; i++) { notifyTarget(nodes[i], type, wmin, wmout); } }; var notifyTarget = function notifyTarget(node, type, wmin, wmout) { if (has(node) && !wmin.has(node)) { wmout["delete"](node); wmin.set(node, 0); node.dispatchEvent(new (CE || CustomEvent)(type)); } notifyObserved(node[parse || 'children'] || [], type, wmin, wmout); }; var mo = new (MO || MutationObserver)(function (nodes) { for (var length = nodes.length, i = 0; i < length; i++) { var _nodes$i = nodes[i], removedNodes = _nodes$i.removedNodes, addedNodes = _nodes$i.addedNodes; notifyObserved(removedNodes, 'disconnected', wmout, wmin); notifyObserved(addedNodes, 'connected', wmin, wmout); } }); mo.add = add; mo.add(root || document); var attachShadow = Element.prototype.attachShadow; if (attachShadow) Element.prototype.attachShadow = function (init) { var sd = attachShadow.call(this, init); mo.add(sd); return sd; }; return { has: has, connect: connect, disconnect: disconnect, kill: function kill() { mo.disconnect(); } }; }; function add(node) { this.observe(node, { subtree: true, childList: true }); } function handleEvent(event) { if (event.type in this) this[event.type](event); } exports.observe = observe; return exports; }({}));