Created
September 24, 2024 20:08
-
-
Save blakek/31a0e6cc8deaab1ab53f535e23791da7 to your computer and use it in GitHub Desktop.
Temporary UserScript helpers until I migrate to something more permanent
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Prevents an attribute from being changed on an element, meaning once the | |
* attribute is changed, it will be immediately set back to the original value. | |
* @param {string} selector | |
* @param {string} attributeName | |
*/ | |
function preventAttributeChange(selector, attributeName) { | |
const element = document.querySelector(selector); | |
const originalValue = element.getAttribute(attributeName); | |
const observer = new MutationObserver((mutations) => { | |
for (const mutation of mutations) { | |
if (mutation.attributeName === attributeName) { | |
element.setAttribute(attributeName, originalValue); | |
observer.disconnect(); | |
} | |
} | |
}); | |
observer.observe(element, { | |
attributes: true, | |
attributeFilter: [attributeName], | |
}); | |
} | |
/** | |
* Prevents an element from being added to the DOM. If the element is already | |
* present, it will be removed immediately. | |
* @param {string} selector | |
* @param {{ runOnce: boolean, parentElement: Element }} options | |
*/ | |
function preventElement(selector, options = {}) { | |
const { runOnce = false, parentElement = document.body } = options; | |
const tryRemoveElement = () => { | |
const element = parentElement.querySelector(selector); | |
if (element) { | |
element.remove(); | |
return true; | |
} | |
return false; | |
}; | |
// Try removing the element immediately | |
if (tryRemoveElement() && runOnce) { | |
return; | |
} | |
// If the element isn't there, watch for it to be added | |
const observer = new MutationObserver((mutations) => { | |
// The target could be a deeply nested child of the mutation. Instead, we | |
// can just do `querySelector()` on the target on each change. | |
for (let _ of mutations) { | |
const removed = tryRemoveElement(); | |
if (removed && runOnce) { | |
observer.disconnect(); | |
return; | |
} | |
} | |
}); | |
observer.observe(parentElement, { | |
childList: true, | |
subtree: true, | |
}); | |
} | |
/** | |
* Adds a style tag to the document with the given CSS content. | |
* @param {string} css | |
*/ | |
function addStyle(css) { | |
const style = document.createElement("style"); | |
style.textContent = css; | |
document.head.appendChild(style); | |
} | |
/** | |
* Template string for adding global styles. | |
* This is purposely named to look like `styled-components`'s `createGlobalStyle` so VSCode will change the language mode. | |
* @param {TemplateStringsArray} strings | |
* @param {...(string | number | boolean | null | undefined)} values | |
*/ | |
function createGlobalStyle(strings, ...values) { | |
return addStyle(String.raw(strings, ...values)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment