Core library to handle webpages dom with userscripts from document-start
Version vom
Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyfork.org/scripts/476017/1255617/userscripts-core-library.js
// ==UserScript==
// @name userscripts-core-library
// @version 0.1.0
// @author lucianjp
// @description Core library to handle webpages dom with userscripts from document-start
// ==/UserScript==
const core = {
ready: (callback) =>
document.readyState !== "loading"
? callback()
: document.addEventListener("DOMContentLoaded", callback),
addStyle: (aCss) => {
let head = document.getElementsByTagName("head")[0];
if (!head) {
console.error("Head element not found. Cannot add style.");
return null;
}
let style = document.createElement("style");
style.setAttribute("type", "text/css");
style.textContent = aCss;
head.appendChild(style);
return style;
},
observe: (observableCollection, continuous = false) => {
const observables = Array.from(observableCollection.entries()).filter(
([_, observable]) => !observable.currentValue
);
const observer = new MutationObserver(function (mutations) {
for (var i = mutations.length - 1; i >= 0; i--) {
const mutation = mutations[i];
const addedNodesLength = mutation.addedNodes.length;
if (addedNodesLength > 0) {
for (var j = addedNodesLength - 1; j >= 0; j--) {
const $node = mutation.addedNodes[j];
if ($node && $node.nodeType === 1) {
let observablesLength = observables.length;
for (let k = observablesLength - 1; k >= 0; k--) {
const [_, observable] = observables[k];
if (observable.test($node)) {
observable.set($node);
const last = observables.pop();
if (k < observablesLength - 1) observables[k] = last;
observablesLength = observablesLength - 1;
break;
}
}
}
}
if (observables.length === 0 && !continuous) {
observer.disconnect();
return;
}
}
}
});
observer.observe(document, { childList: true, subtree: true });
if (!continuous) core.ready(() => observer.disconnect());
return observer;
},
};
class Observable {
constructor(lookup, test) {
this.value = undefined;
this.callbacks = [];
this.lookup = lookup;
this.test = test;
if (typeof lookup === "function") {
this.value = lookup();
}
}
set(newValue) {
this.value = newValue;
this.executeCallbacks(this.value);
}
then(callback) {
if (typeof callback === "function") {
this.callbacks.push(callback);
if (this.value) callback(this.value);
}
return this;
}
executeCallbacks(value) {
this.callbacks.forEach((callback) => callback(value));
}
get currentValue() {
return this.value;
}
}
class ObservableCollection extends Map {
constructor() {
super();
}
add(name, observable) {
this.set(name, observable);
return observable;
}
}