Prevents specified DOM elements from being destroyed by page state changes
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/584836/1863342/Anti-UI%20Purge%20Library.js
// ==UserScript==
// @name Anti-UI Purge Library
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Prevents specified DOM elements from being destroyed by page state changes
// @author Gemini
// @grant none
// ==/UserScript==
(function(win) {
'use strict';
const protectedIDs = new Set();
const protectedElements = new Map();
// ==========================================
// 1. NATIVE METHOD HOOKING (Proactive Defense)
// ==========================================
// Hook removeChild to intercept direct removal attempts
const originalRemoveChild = Node.prototype.removeChild;
Node.prototype.removeChild = function(child) {
if (child && child.id && protectedIDs.has(child.id)) {
console.warn(`[Anti-Purge] Blocked attempt to remove protected element: #${child.id}`);
return child; // Pretend it was removed successfully
}
return originalRemoveChild.apply(this, arguments);
};
// Hook replaceChild
const originalReplaceChild = Node.prototype.replaceChild;
Node.prototype.replaceChild = function(newChild, oldChild) {
if (oldChild && oldChild.id && protectedIDs.has(oldChild.id)) {
console.warn(`[Anti-Purge] Blocked attempt to replace protected element: #${oldChild.id}`);
// Insert the new child, but keep the old protected child
this.insertBefore(newChild, oldChild);
return oldChild;
}
return originalReplaceChild.apply(this, arguments);
};
// Hook innerHTML to catch blanket wipes (e.g., document.body.innerHTML = '')
const originalInnerHTML = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');
Object.defineProperty(Element.prototype, 'innerHTML', {
set: function(value) {
// Find if any protected elements are currently inside this container
const elementsToSave = [];
protectedIDs.forEach(id => {
const el = this.querySelector(`#${id}`);
if (el) elementsToSave.push(el);
});
// Allow the wipe
originalInnerHTML.set.call(this, value);
// Re-append the protected elements immediately
elementsToSave.forEach(el => {
this.appendChild(el);
console.warn(`[Anti-Purge] Restored #${el.id} after innerHTML wipe.`);
});
},
get: originalInnerHTML.get
});
// ==========================================
// 2. MUTATION OBSERVER (Reactive Fallback)
// ==========================================
const observer = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
mutation.removedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
// Check if the node itself is protected
if (protectedIDs.has(node.id)) {
document.body.appendChild(protectedElements.get(node.id));
console.warn(`[Anti-Purge] Observer restored orphaned element: #${node.id}`);
}
// Check if the removed node *contained* our protected element
else {
protectedIDs.forEach(id => {
if (node.querySelector(`#${id}`)) {
document.body.appendChild(protectedElements.get(id));
console.warn(`[Anti-Purge] Observer restored element #${id} from purged parent container.`);
}
});
}
}
});
});
});
win.addEventListener('DOMContentLoaded', () => {
observer.observe(document.body, { childList: true, subtree: true });
});
// ==========================================
// 3. EXPORTED API
// ==========================================
win.AntiPurge = {
/**
* Registers an element to be protected from DOM deletion.
* @param {HTMLElement} element - The DOM node to protect. Must have a unique ID.
*/
protect: function(element) {
if (!element.id) {
console.error('[Anti-Purge] Element must have an ID to be protected.');
return;
}
protectedIDs.add(element.id);
protectedElements.set(element.id, element);
console.log(`[Anti-Purge] Now protecting: #${element.id}`);
},
/**
* Unregisters an element, allowing normal deletion.
* @param {string} id - The ID of the element to release.
*/
release: function(id) {
protectedIDs.delete(id);
protectedElements.delete(id);
console.log(`[Anti-Purge] Released protection for: #${id}`);
}
};
})(typeof unsafeWindow !== 'undefined' ? unsafeWindow : window);