Skip to content

Instantly share code, notes, and snippets.

@blakek
Created September 24, 2024 20:08
Show Gist options
  • Save blakek/31a0e6cc8deaab1ab53f535e23791da7 to your computer and use it in GitHub Desktop.
Save blakek/31a0e6cc8deaab1ab53f535e23791da7 to your computer and use it in GitHub Desktop.
Temporary UserScript helpers until I migrate to something more permanent
/**
* 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