Skip to content

Instantly share code, notes, and snippets.

@semlinker
Created August 18, 2020 01:07
Show Gist options
  • Save semlinker/a149763bf033d7f2dff2d32d60c27865 to your computer and use it in GitHub Desktop.
Save semlinker/a149763bf033d7f2dff2d32d60c27865 to your computer and use it in GitHub Desktop.
Code Snippet for MutationObserver
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 (Object.keys(watch).length < 1) return;
for (let i = 0; i < mutations.length; 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],
});
}
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;
}
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] && nodes[i].childNodes.length > 0) {
eachMutation(nodes[i].childNodes, fn);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment