Callback binding for HTML Node creation events
目前為
此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/19857/126895/node-creation-observer.js
/**
* https://github.com/soufianesakhi/node-creation-observer-js
* MIT licensed
* Copyright (c) 2016 Soufiane Sakhi
*/
var NodeCreationObserver = function () {
var mutationObserver = null;
var observedNodeAttribute = "node-creation-observer";
var listeners = {};
var options = {
childList: true,
subtree: true
};
function ListenerContext(removeOnFirstMatch) {
this.callbacks = [];
this.removeOnFirstMatch = removeOnFirstMatch == undefined ? false : removeOnFirstMatch;
}
function onMutationCallback(mutationRecordArray) {
Object.keys(listeners).forEach(function (selector) {
invokeCallbacks(selector);
});
}
function invokeCallbacks(selector) {
var callbacks = listeners[selector].callbacks;
var elements = document.querySelectorAll(selector);
var newElements = filterNewElements(elements);
if (newElements.length > 0) {
if (listeners[selector].removeOnFirstMatch) {
removeListener(selector);
}
newElements.forEach(function (element) {
callbacks.forEach(function (callback) {
callback.call(element, element);
});
});
}
}
function filterNewElements(elements) {
var newElements = [];
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
var attr = element.getAttribute(observedNodeAttribute);
if (attr == null) {
element.setAttribute(observedNodeAttribute, 1);
newElements.push(element);
}
};
return newElements;
}
function observe() {
if (mutationObserver == null) {
mutationObserver = new MutationObserver(onMutationCallback);
mutationObserver.observe(document.documentElement, options);
}
}
function removeListener(selector) {
delete listeners[selector];
if (Object.keys(listeners).length == 0) {
stopObserving();
}
}
function stopObserving() {
if (mutationObserver != null) {
mutationObserver.disconnect();
mutationObserver = null;
}
}
return {
onCreation: function (selector, callback, removeOnFirstMatch) {
if (!listeners[selector]) {
listeners[selector] = new ListenerContext(removeOnFirstMatch);
}
listeners[selector].callbacks.push(callback);
observe();
if (document.querySelector(selector) != null) {
invokeCallbacks(selector);
}
},
remove: removeListener,
stop: function () {
listeners = {};
stopObserving();
}
};
} ();