Mirror of UserUtils' source code https://github.com/Sv443-Network/UserUtils

Sven 3d46876d0a fix: missing export 1 سال پیش
.changeset 174049fa48 Version Packages 1 سال پیش
.github fc03613125 ci: pr title & commit msg for releases 1 سال پیش
lib 3d46876d0a fix: missing export 1 سال پیش
.eslintrc.cjs e54ccbcf24 feat: initial commit 1 سال پیش
.gitignore 72181703dd docs: readme stuff 1 سال پیش
.npmignore dcfe430eaf fix: update npmignore 1 سال پیش
CHANGELOG.md 174049fa48 Version Packages 1 سال پیش
LICENSE.txt e54ccbcf24 feat: initial commit 1 سال پیش
README.md e85bcbc6ad docs: capitalization 1 سال پیش
package-lock.json 9c9426a111 ref: improve build commands 1 سال پیش
package.json 174049fa48 Version Packages 1 سال پیش
tsconfig.json 72181703dd docs: readme stuff 1 سال پیش

README.md

## UserUtils Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, modify the DOM more easily and more. Contains builtin TypeScript declarations. Webpack compatible and supports ESM and CJS.

## Table of Contents: - [Installation](#installation) - [Features](#features) - [DOM:](#dom) - [onSelector()](#onselector) - call a listener once a selector is found in the DOM - [initOnSelector()](#initonselector) - needs to be called once to be able to use `onSelector()` - [getSelectorMap()](#getselectormap) - returns all currently registered selectors, listeners and options - [getUnsafeWindow()](#getunsafewindow) - get the unsafeWindow object or fall back to the regular window object - [insertAfter()](#insertafter) - insert an element as a sibling after another element - [addParent()](#addparent) - add a parent element around another element - [addGlobalStyle()](#addglobalstyle) - add a global style to the page - [preloadImages()](#preloadimages) - preload images into the browser cache for faster loading later on - [openInNewTab()](#openinnewtab) - open a link in a new tab - [interceptEvent()](#interceptevent) - conditionally intercepts events registered by `addEventListener()` on any given EventTarget object - [interceptWindowEvent()](#interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object - [Math:](#math) - [clamp()](#clamp) - clamp a number between a min and max value - [mapRange()](#maprange) - map a number from one range to the same spot in another range - [randRange()](#randrange) - generate a random number between a min and max boundary - [Misc:](#misc) - [autoPlural()](#autoplural) - automatically pluralize a string - [pauseFor()](#pausefor) - pause the execution of a function for a given amount of time - [debounce()](#debounce) - call a function only once, after a given amount of time - [fetchAdvanced()](#fetchadvanced) - wrapper around the fetch API with a timeout option - [Arrays:](#arrays) - [randomItem()](#randomitem) - returns a random item from an array - [randomItemIndex()](#randomitemindex) - returns a tuple of a random item and its index from an array - [takeRandomItem()](#takerandomitem) - returns a random item from an array and mutates it to remove the item - [randomizeArray()](#randomizearray) - returns a copy of the array with its items in a random order - [License](#license)

## Installation: - If you are using a bundler like webpack, you can install this package using npm: ``` npm i @sv443-network/userutils ``` Then, import it in your script as usual: ```ts import { addGlobalStyle } from "@sv443-network/userutils"; // or import * as userUtils from "@sv443-network/userutils"; ``` Shameless plug: I also have a [webpack-based template for userscripts in TypeScript](https://github.com/Sv443/Userscript.ts) that you can use to get started quickly.
- If you are not using a bundler, you can include the latest release from GreasyFork by adding this directive to the userscript header: ``` // @require https://greasyfork.org/scripts/TODO ```
If you like using this library, please consider [supporting development](https://github.com/sponsors/Sv443)

## Features: ## DOM: ### onSelector() Usage: ```ts onSelector(selector: string, options: { listener: (elements: TElement | NodeListOf) => void, all?: boolean, continuous?: boolean, }): void ``` Registers a listener to be called whenever the element(s) behind a selector is/are found in the DOM. If the selector already exists, the listener will be called immediately. If `all` is set to `true`, querySelectorAll() will be used instead and the listener will return a NodeList of matching elements. This will also include elements that were already found in a previous listener call. If set to `false` (default), querySelector() will be used and only the first matching element will be returned. If `continuous` is set to `true`, the listener will not be deregistered after it was called once (defaults to false). When using TypeScript, the generic `TElement` can be used to specify the type of the element(s) that the listener will return. ⚠️ In order to use this function, [`initOnSelector()`](#initonselector) has to be called as soon as possible. This initialization function has to be called after `DOMContentLoaded` is fired (or immediately if `@run-at document-end` is set). Calling onSelector() before `DOMContentLoaded` is fired will not throw an error, but it also won't trigger listeners until the DOM is accessible.
Example - click to view ```ts document.addEventListener("DOMContentLoaded", initOnSelector); // Continuously checks if `div` elements are added to the DOM, then returns all of them (even previously detected ones) in a NodeList onSelector("div", { listener: (elements) => { console.log("Elements found:", elements); // type = NodeListOf }, all: true, continuous: true, }); // Checks if an input element with a value attribute of "5" is added to the DOM, then returns it and deregisters the listener onSelector("input[value=\"5\"]", { listener: (element) => { console.log("Element found:", element); // type = HTMLInputElement }, }); ```
### initOnSelector() Usage: ```ts initOnSelector(options?: { attributes?: boolean, characterData?: boolean, }): void ``` Initializes the MutationObserver that is used by [`onSelector()`](#onselector) to check for the registered selectors whenever a DOM change occurs on the `` By default, this only checks if elements are added or removed (at any depth). Set `attributes` to `true` to also check for attribute changes on every single descendant of the `` (defaults to false). Set `characterData` to `true` to also check for character data changes on every single descendant of the `` (defaults to false). ⚠️ Using these extra options can have a performance impact on larger sites or sites with a constantly changing DOM. ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
Example - click to view ```ts document.addEventListener("DOMContentLoaded", () => { initOnSelector({ attributes: true, characterData: true, }); }); ```

### getSelectorMap() Usage: `getSelectorMap(): Map` Returns a Map of all currently registered selectors and their options, including listener function. Since multiple listeners can be registered for the same selector, the value of the Map is an array of `OnSelectorOptions` objects.
Example - click to view ```ts document.addEventListener("DOMContentLoaded", initOnSelector); onSelector("div", { listener: (elements) => void 0, all: true, continuous: true, }); onSelector("div", { listener: (elements) => void 0, }); const selectorMap = getSelectorMap(); // Map(1) { // "div" => [ // { // listener: (elements) => void 0, // all: true, // continuous: true, // }, // { // listener: (elements) => void 0, // }, // ] // } ```
### getUnsafeWindow() Usage: `getUnsafeWindow(): Window` Returns the unsafeWindow object or falls back to the regular window object if the `@grant unsafeWindow` is not given. Userscripts are sandboxed and do not have access to the regular window object, so this function is useful for websites that reject some events that were dispatched by the userscript.
Example - click to view ```ts // trick the site into thinking the mouse was moved: const mouseEvent = new MouseEvent("mousemove", { view: getUnsafeWindow(), screenY: 69, screenX: 420, movementX: 10, movementY: 0, }); document.body.dispatchEvent(mouseEvent); ```

### insertAfter() Usage: `insertAfter(beforeElement: HTMLElement, afterElement: HTMLElement): HTMLElement` Inserts the element passed as `afterElement` as a sibling after the passed `beforeElement`. The passed `afterElement` will be returned. ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
Example - click to view ```ts // insert a
as a sibling next to an element const beforeElement = document.querySelector("#before"); const afterElement = document.createElement("div"); afterElement.innerText = "After"; insertAfter(beforeElement, afterElement); ```

### addParent() Usage: `addParent(element: HTMLElement, newParent: HTMLElement): HTMLElement` Adds a parent element around the passed `element` and returns the new parent. Previously registered event listeners are kept intact. ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
Example - click to view ```ts // add an around an element const element = document.querySelector("#element"); const newParent = document.createElement("a"); newParent.href = "https://example.org/"; addParent(element, newParent); ```

### addGlobalStyle() Usage: `addGlobalStyle(css: string): void` Adds a global style to the page in form of a `