@sv443-network/userutils 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @sv443-network/userutils
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 54e7905: Features:
8
+
9
+ - add function `amplifyMedia()` to boost the volume of a MediaElement past its default maximum
10
+ - allow all `MutationObserver.observe()` options to be passed to `initOnSelector()`
11
+
12
+ Fixes:
13
+
14
+ - fix `onSelector()` not triggering correctly
15
+
3
16
  ## 0.4.1
4
17
 
5
18
  ### Patch Changes
@@ -11,12 +24,12 @@
11
24
  ### Minor Changes
12
25
 
13
26
  - 231a79c: Refactored code and documentation and added new functions:
14
- - mapRange() to map a number from one range to the same spot in another range
15
- - randRange() to generate a random number between a min and max boundary
16
- - randomItem() to return a random item from an array
17
- - randomItemIndex() to return a tuple of a random item and its index from an array
18
- - takeRandomItem() to return a random item from an array and mutate it to remove the item
19
- - randomizeArray() to return a copy of the array with its items in a random order
27
+ - `mapRange()` to map a number from one range to the same spot in another range
28
+ - `randRange()` to generate a random number between a min and max boundary
29
+ - `randomItem()` to return a random item from an array
30
+ - `randomItemIndex()` to return a tuple of a random item and its index from an array
31
+ - `takeRandomItem()` to return a random item from an array and mutate it to remove the item
32
+ - `randomizeArray()` to return a copy of the array with its items in a random order
20
33
 
21
34
  ### Patch Changes
22
35
 
@@ -26,13 +39,13 @@
26
39
 
27
40
  ### Minor Changes
28
41
 
29
- - 07ec443: add getSelectorMap() to return all currently registered selectors
42
+ - 07ec443: add `getSelectorMap()` to return all currently registered selectors
30
43
 
31
44
  ## 0.2.0
32
45
 
33
46
  ### Minor Changes
34
47
 
35
- - 0cf2254: add onSelector() to call a listener once a selector is found in the DOM
48
+ - 0cf2254: add `onSelector()` to call a listener once a selector is found in the DOM
36
49
 
37
50
  ## 0.1.1
38
51
 
package/README.md CHANGED
@@ -2,14 +2,17 @@
2
2
 
3
3
  ## UserUtils
4
4
  Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, modify the DOM more easily and more.
5
- Contains builtin TypeScript declarations. Webpack compatible and supports ESM and CJS.
5
+ Contains builtin TypeScript declarations. Webpack compatible and supports ESM and CJS.
6
+ If you like using this library, please consider [supporting the development ❤️](https://github.com/sponsors/Sv443)
6
7
 
7
8
  </div>
8
9
  <br>
9
10
 
10
11
  ## Table of Contents:
11
- - [Installation](#installation)
12
- - [Features](#features)
12
+ - [**Installation**](#installation)
13
+ - [**Preamble**](#preamble)
14
+ - [**License**](#license)
15
+ - [**Features**](#features)
13
16
  - [DOM:](#dom)
14
17
  - [onSelector()](#onselector) - call a listener once a selector is found in the DOM
15
18
  - [initOnSelector()](#initonselector) - needs to be called once to be able to use `onSelector()`
@@ -22,8 +25,9 @@ Contains builtin TypeScript declarations. Webpack compatible and supports ESM an
22
25
  - [openInNewTab()](#openinnewtab) - open a link in a new tab
23
26
  - [interceptEvent()](#interceptevent) - conditionally intercepts events registered by `addEventListener()` on any given EventTarget object
24
27
  - [interceptWindowEvent()](#interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object
28
+ - [amplifyMedia()](#amplifymedia) - amplify an audio or video element's volume past the maximum of 100%
25
29
  - [Math:](#math)
26
- - [clamp()](#clamp) - clamp a number between a min and max value
30
+ - [clamp()](#clamp) - constrain a number between a min and max value
27
31
  - [mapRange()](#maprange) - map a number from one range to the same spot in another range
28
32
  - [randRange()](#randrange) - generate a random number between a min and max boundary
29
33
  - [Misc:](#misc)
@@ -36,7 +40,6 @@ Contains builtin TypeScript declarations. Webpack compatible and supports ESM an
36
40
  - [randomItemIndex()](#randomitemindex) - returns a tuple of a random item and its index from an array
37
41
  - [takeRandomItem()](#takerandomitem) - returns a random item from an array and mutates it to remove the item
38
42
  - [randomizeArray()](#randomizearray) - returns a copy of the array with its items in a random order
39
- - [License](#license)
40
43
 
41
44
  <br><br>
42
45
 
@@ -60,14 +63,29 @@ Contains builtin TypeScript declarations. Webpack compatible and supports ESM an
60
63
  // @require https://greasyfork.org/scripts/TODO
61
64
  ```
62
65
 
63
- <br>
66
+ <br><br>
64
67
 
65
- If you like using this library, please consider [supporting development](https://github.com/sponsors/Sv443)
68
+ ## Preamble:
69
+ This library is written in TypeScript and contains builtin TypeScript declarations.
70
+ The usages and examples in this readme are written in TypeScript, but the library can also be used in plain JavaScript.
71
+
72
+ Some functions require the `@run-at` or `@grant` directives to be tweaked in the userscript header or have other requirements.
73
+ Their documentation will contain a section marked by a warning emoji (⚠️) that will go into more detail.
74
+
75
+ If the usage contains multiple definitions of the function, each line represents an overload and you can choose which one you want to use.
76
+
77
+ <br><br>
78
+
79
+ ## License:
80
+ This library is licensed under the MIT License.
81
+ See the [license file](./LICENSE.txt) for details.
66
82
 
67
83
  <br><br>
68
84
 
69
85
  ## Features:
70
86
 
87
+ <br>
88
+
71
89
  ## DOM:
72
90
 
73
91
  ### onSelector()
@@ -125,22 +143,22 @@ onSelector<HTMLInputElement>("input[value=\"5\"]", {
125
143
  ### initOnSelector()
126
144
  Usage:
127
145
  ```ts
128
- initOnSelector(options?: {
129
- attributes?: boolean,
130
- characterData?: boolean,
131
- }): void
146
+ initOnSelector(options?: MutationObserverInit): void
132
147
  ```
133
148
 
134
149
  Initializes the MutationObserver that is used by [`onSelector()`](#onselector) to check for the registered selectors whenever a DOM change occurs on the `<body>`
135
150
  By default, this only checks if elements are added or removed (at any depth).
136
-
137
- Set `attributes` to `true` to also check for attribute changes on every single descendant of the `<body>` (defaults to false).
138
- Set `characterData` to `true` to also check for character data changes on every single descendant of the `<body>` (defaults to false).
139
-
140
- ⚠️ Using these extra options can have a performance impact on larger sites or sites with a constantly changing DOM.
141
-
151
+
142
152
  ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
143
153
 
154
+ The options object is passed directly to the MutationObserver.observe() method.
155
+ Note that `options.subtree` and `options.childList` will be set to true by default.
156
+ You may see all options [here](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/observe#options), but these are the important ones:
157
+ > Set `options.attributes` to `true` to also check for attribute changes on every single descendant of the `<body>` (defaults to false).
158
+ > Set `options.characterData` to `true` to also check for character data changes on every single descendant of the `<body>` (defaults to false).
159
+ >
160
+ > ⚠️ Using these extra options can have a performance impact on larger sites or sites with a constantly changing DOM.
161
+
144
162
  <details><summary><b>Example - click to view</b></summary>
145
163
 
146
164
  ```ts
@@ -315,7 +333,7 @@ Usage: `openInNewTab(url: string): void`
315
333
 
316
334
  Creates an invisible anchor with a `_blank` target and clicks it.
317
335
  Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
318
- This function has to be run in relatively quick succession in response to a user interaction event, else the browser might reject it.
336
+ This function has to be run in response to a user interaction event, else the browser might reject it.
319
337
 
320
338
  ⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
321
339
 
@@ -369,6 +387,50 @@ interceptWindowEvent("beforeunload", () => {
369
387
 
370
388
  </details>
371
389
 
390
+ <br>
391
+
392
+ ### amplifyMedia()
393
+ Usage: `amplifyMedia(mediaElement: HTMLMediaElement, multiplier?: number): AmplifyMediaResult`
394
+
395
+ Amplifies the gain of a media element (like `<audio>` or `<video>`) by a given multiplier (defaults to 1.0).
396
+ This is how you can increase the volume of a media element beyond the default maximum volume of 1.0 or 100%.
397
+ Make sure to limit the multiplier to a reasonable value ([clamp()](#clamp) is good for this), as it may cause clipping or bleeding eardrums.
398
+
399
+ ⚠️ This function has to be run in response to a user interaction event, else the browser will reject it because of the strict autoplay policy.
400
+
401
+ Returns an object with the following properties:
402
+ | Property | Description |
403
+ | :-- | :-- |
404
+ | `mediaElement` | The passed media element |
405
+ | `amplify()` | A function to change the amplification level |
406
+ | `getAmpLevel()` | A function to return the current amplification level |
407
+ | `context` | The AudioContext instance |
408
+ | `source` | The MediaElementSourceNode instance |
409
+ | `gain` | The GainNode instance |
410
+
411
+ <details><summary><b>Example - click to view</b></summary>
412
+
413
+ ```ts
414
+ const audio = document.querySelector<HTMLAudioElement>("audio");
415
+ const button = document.querySelector<HTMLButtonElement>("button");
416
+
417
+ // amplifyMedia needs to be called in response to a user interaction event:
418
+ button.addEventListener("click", () => {
419
+ const { amplify, getAmpLevel } = amplifyMedia(audio);
420
+
421
+ const setGain = (value: number) => {
422
+ // constrain the value to between 0 and 5
423
+ amplify(clamp(value, 0, 5));
424
+ console.log("Gain set to", getAmpLevel());
425
+ }
426
+
427
+ setGain(2); // set gain to 2x
428
+ setGain(3.5); // set gain to 3.5x
429
+
430
+ console.log(getAmpLevel()); // 3.5
431
+ });
432
+ ```
433
+
372
434
  <br><br>
373
435
 
374
436
  ## Math:
@@ -599,14 +661,7 @@ randomizeArray([1, 2, 3, 4, 5, 6]); // [3, 1, 5, 2, 4, 6]
599
661
 
600
662
  <br>
601
663
 
602
-
603
- <br><br>
604
-
605
- ## License:
606
- This library is licensed under the MIT License.
607
- See the [license file](./LICENSE.txt) for details.
608
-
609
- <br><br>
664
+ <br><br><br><br>
610
665
 
611
666
  <div style="text-align: center;" align="center">
612
667
 
package/dist/index.d.mts CHANGED
@@ -40,7 +40,7 @@ declare function preloadImages(srcUrls: string[], rejects?: boolean): Promise<Pr
40
40
  * Creates an invisible anchor with a `_blank` target and clicks it.
41
41
  * Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
42
42
  *
43
- * This function has to be run in relatively quick succession in response to a user interaction event, else the browser might reject it.
43
+ * This function has to be run in response to a user interaction event, else the browser might reject it.
44
44
  */
45
45
  declare function openInNewTab(href: string): void;
46
46
  /**
@@ -55,6 +55,30 @@ declare function interceptEvent<TEvtObj extends EventTarget>(eventObject: TEvtOb
55
55
  * Calling this function will set the `Error.stackTraceLimit` to 1000 to ensure the stack trace is preserved.
56
56
  */
57
57
  declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate: () => boolean): void;
58
+ /**
59
+ * Amplifies the gain of the passed media element's audio by the specified multiplier.
60
+ * This function supports any media element like `<audio>` or `<video>`
61
+ *
62
+ * This function has to be run in response to a user interaction event, else the browser will reject it because of the strict autoplay policy.
63
+ *
64
+ * @returns Returns an object with the following properties:
65
+ * | Property | Description |
66
+ * | :-- | :-- |
67
+ * | `mediaElement` | The passed media element |
68
+ * | `amplify()` | A function to change the amplification level |
69
+ * | `getAmpLevel()` | A function to return the current amplification level |
70
+ * | `context` | The AudioContext instance |
71
+ * | `source` | The MediaElementSourceNode instance |
72
+ * | `gain` | The GainNode instance |
73
+ */
74
+ declare function amplifyMedia<TElem extends HTMLMediaElement>(mediaElement: TElem, multiplier?: number): {
75
+ mediaElement: TElem;
76
+ amplify: (multiplier: number) => void;
77
+ getAmpLevel: () => number;
78
+ context: AudioContext;
79
+ source: MediaElementAudioSourceNode;
80
+ gain: GainNode;
81
+ };
58
82
 
59
83
  /** Ensures the passed `value` always stays between `min` and `max` */
60
84
  declare function clamp(value: number, min: number, max: number): number;
@@ -68,12 +92,6 @@ declare function randRange(min: number, max: number): number;
68
92
  /** Returns a random number between 0 and `max` (inclusive) */
69
93
  declare function randRange(max: number): number;
70
94
 
71
- type InitOnSelectorOpts = {
72
- /** Set to true if mutations to any element's attributes are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
73
- attributes?: boolean;
74
- /** Set to true if mutations to any element's character data are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
75
- characterData?: boolean;
76
- };
77
95
  type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
78
96
  type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
79
97
  /** Whether to use `querySelectorAll()` instead - default is false */
@@ -128,10 +146,10 @@ declare function onSelector<TElem extends Element = HTMLElement>(selector: strin
128
146
  declare function removeOnSelector(selector: string): boolean;
129
147
  /**
130
148
  * Initializes a MutationObserver that checks for all registered selectors whenever an element is added to or removed from the `<body>`
131
- * @param opts For fine-tuning when the MutationObserver checks for the selectors
149
+ * @param options For fine-tuning what triggers the MutationObserver's checking function - `subtree` and `childList` are set to true by default
132
150
  */
133
- declare function initOnSelector(opts?: InitOnSelectorOpts): void;
151
+ declare function initOnSelector(options?: MutationObserverInit): void;
134
152
  /** Returns all currently registered selectors, as a map of selector strings to their associated options */
135
153
  declare function getSelectorMap(): Map<string, OnSelectorOpts[]>;
136
154
 
137
- export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, randomItem, randomItemIndex, randomizeArray, removeOnSelector, takeRandomItem };
155
+ export { FetchAdvancedOpts, OnSelectorOpts, addGlobalStyle, addParent, amplifyMedia, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, randomItem, randomItemIndex, randomizeArray, removeOnSelector, takeRandomItem };
package/dist/index.d.ts CHANGED
@@ -40,7 +40,7 @@ declare function preloadImages(srcUrls: string[], rejects?: boolean): Promise<Pr
40
40
  * Creates an invisible anchor with a `_blank` target and clicks it.
41
41
  * Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.
42
42
  *
43
- * This function has to be run in relatively quick succession in response to a user interaction event, else the browser might reject it.
43
+ * This function has to be run in response to a user interaction event, else the browser might reject it.
44
44
  */
45
45
  declare function openInNewTab(href: string): void;
46
46
  /**
@@ -55,6 +55,30 @@ declare function interceptEvent<TEvtObj extends EventTarget>(eventObject: TEvtOb
55
55
  * Calling this function will set the `Error.stackTraceLimit` to 1000 to ensure the stack trace is preserved.
56
56
  */
57
57
  declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate: () => boolean): void;
58
+ /**
59
+ * Amplifies the gain of the passed media element's audio by the specified multiplier.
60
+ * This function supports any media element like `<audio>` or `<video>`
61
+ *
62
+ * This function has to be run in response to a user interaction event, else the browser will reject it because of the strict autoplay policy.
63
+ *
64
+ * @returns Returns an object with the following properties:
65
+ * | Property | Description |
66
+ * | :-- | :-- |
67
+ * | `mediaElement` | The passed media element |
68
+ * | `amplify()` | A function to change the amplification level |
69
+ * | `getAmpLevel()` | A function to return the current amplification level |
70
+ * | `context` | The AudioContext instance |
71
+ * | `source` | The MediaElementSourceNode instance |
72
+ * | `gain` | The GainNode instance |
73
+ */
74
+ declare function amplifyMedia<TElem extends HTMLMediaElement>(mediaElement: TElem, multiplier?: number): {
75
+ mediaElement: TElem;
76
+ amplify: (multiplier: number) => void;
77
+ getAmpLevel: () => number;
78
+ context: AudioContext;
79
+ source: MediaElementAudioSourceNode;
80
+ gain: GainNode;
81
+ };
58
82
 
59
83
  /** Ensures the passed `value` always stays between `min` and `max` */
60
84
  declare function clamp(value: number, min: number, max: number): number;
@@ -68,12 +92,6 @@ declare function randRange(min: number, max: number): number;
68
92
  /** Returns a random number between 0 and `max` (inclusive) */
69
93
  declare function randRange(max: number): number;
70
94
 
71
- type InitOnSelectorOpts = {
72
- /** Set to true if mutations to any element's attributes are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
73
- attributes?: boolean;
74
- /** Set to true if mutations to any element's character data are to also trigger the onSelector check (warning: this might draw a lot of performance on larger sites) */
75
- characterData?: boolean;
76
- };
77
95
  type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
78
96
  type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
79
97
  /** Whether to use `querySelectorAll()` instead - default is false */
@@ -128,10 +146,10 @@ declare function onSelector<TElem extends Element = HTMLElement>(selector: strin
128
146
  declare function removeOnSelector(selector: string): boolean;
129
147
  /**
130
148
  * Initializes a MutationObserver that checks for all registered selectors whenever an element is added to or removed from the `<body>`
131
- * @param opts For fine-tuning when the MutationObserver checks for the selectors
149
+ * @param options For fine-tuning what triggers the MutationObserver's checking function - `subtree` and `childList` are set to true by default
132
150
  */
133
- declare function initOnSelector(opts?: InitOnSelectorOpts): void;
151
+ declare function initOnSelector(options?: MutationObserverInit): void;
134
152
  /** Returns all currently registered selectors, as a map of selector strings to their associated options */
135
153
  declare function getSelectorMap(): Map<string, OnSelectorOpts[]>;
136
154
 
137
- export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, randomItem, randomItemIndex, randomizeArray, removeOnSelector, takeRandomItem };
155
+ export { FetchAdvancedOpts, OnSelectorOpts, addGlobalStyle, addParent, amplifyMedia, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, randomItem, randomItemIndex, randomizeArray, removeOnSelector, takeRandomItem };
package/dist/index.js CHANGED
@@ -1,27 +1,28 @@
1
1
  'use strict';
2
2
 
3
- var h=Object.defineProperty,y=Object.defineProperties;var w=Object.getOwnPropertyDescriptors;var f=Object.getOwnPropertySymbols;var g=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var b=(t,e,n)=>e in t?h(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,a=(t,e)=>{for(var n in e||(e={}))g.call(e,n)&&b(t,n,e[n]);if(f)for(var n of f(e))v.call(e,n)&&b(t,n,e[n]);return t},d=(t,e)=>y(t,w(e));var T=(t,e,n)=>new Promise((r,o)=>{var i=c=>{try{m(n.next(c));}catch(l){o(l);}},u=c=>{try{m(n.throw(c));}catch(l){o(l);}},m=c=>c.done?r(c.value):Promise.resolve(c.value).then(i,u);m((n=n.apply(t,e)).next());});function S(t,e,n){return Math.max(Math.min(t,n),e)}function N(t,e,n,r,o){return Number(e)===0&&Number(r)===0?t*(o/n):(t-e)*((o-r)/(n-e))+r}function p(...t){let e,n;if(typeof t[0]=="number"&&typeof t[1]=="number")[e,n]=t;else if(typeof t[0]=="number"&&typeof t[1]!="number")e=0,n=t[0];else throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof t[0]}" and "${typeof t[1]}"`);if(e=Number(e),n=Number(n),isNaN(e)||isNaN(n))throw new TypeError(`Parameters "min" and "max" can't be NaN`);if(e>n)throw new TypeError(`Parameter "min" can't be bigger than "max"`);return Math.floor(Math.random()*(n-e+1))+e}function I(t){return x(t)[0]}function x(t){if(t.length===0)return [void 0,void 0];let e=p(t.length-1);return [t[e],e]}function H(t){let[e,n]=x(t);if(n!==void 0)return t.splice(n,1),e}function P(t){let e=[...t];if(t.length===0)return t;for(let n=e.length-1;n>0;n--){let r=Math.floor(p(0,1e4)/1e4*(n+1));[e[n],e[r]]=[e[r],e[n]];}return e}function O(){try{return unsafeWindow}catch(t){return window}}function C(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function R(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function F(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function W(t,e=!1){let n=t.map(r=>new Promise((o,i)=>{let u=new Image;u.src=r,u.addEventListener("load",()=>o(u)),u.addEventListener("error",m=>e&&i(m));}));return Promise.allSettled(n)}function $(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function L(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&n()))return r.apply(this,o)};}(t.__proto__.addEventListener);}function q(t,e){return L(O(),t,e)}function B(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function G(t){return new Promise(e=>{setTimeout(e,t);})}function U(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function D(n){return T(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,i=setTimeout(()=>o.abort(),r),u=yield fetch(t,d(a({},e),{signal:o.signal}));return clearTimeout(i),u})}var s=new Map;function Q(t,e){let n=[];s.has(t)&&(n=s.get(t)),n.push(e),s.set(t,n),E(t,n);}function V(t){return s.delete(t)}function E(t,e){let n=[];if(e.forEach((r,o)=>{try{let i=r.all?document.querySelectorAll(t):document.querySelector(t);i&&(r.listener(i),r.continuous||n.push(o));}catch(i){console.error(`Couldn't call listener for selector '${t}'`,i);}}),n.length>0){let r=e.filter((o,i)=>!n.includes(i));r.length===0?s.delete(t):s.set(t,r);}}function X(t={}){new MutationObserver(()=>{for(let[n,r]of s.entries())E(n,r);}).observe(document.body,d(a({},t),{childList:!0}));}function Y(){return s}
3
+ var h=Object.defineProperty,y=Object.defineProperties;var g=Object.getOwnPropertyDescriptors;var p=Object.getOwnPropertySymbols;var w=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var f=(n,e,t)=>e in n?h(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,m=(n,e)=>{for(var t in e||(e={}))w.call(e,t)&&f(n,t,e[t]);if(p)for(var t of p(e))v.call(e,t)&&f(n,t,e[t]);return n},b=(n,e)=>y(n,g(e));var x=(n,e,t)=>new Promise((r,o)=>{var i=s=>{try{a(t.next(s));}catch(l){o(l);}},u=s=>{try{a(t.throw(s));}catch(l){o(l);}},a=s=>s.done?r(s.value):Promise.resolve(s.value).then(i,u);a((t=t.apply(n,e)).next());});function A(n,e,t){return Math.max(Math.min(n,t),e)}function N(n,e,t,r,o){return Number(e)===0&&Number(r)===0?n*(o/t):(n-e)*((o-r)/(t-e))+r}function d(...n){let e,t;if(typeof n[0]=="number"&&typeof n[1]=="number")[e,t]=n;else if(typeof n[0]=="number"&&typeof n[1]!="number")e=0,t=n[0];else throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof n[0]}" and "${typeof n[1]}"`);if(e=Number(e),t=Number(t),isNaN(e)||isNaN(t))throw new TypeError(`Parameters "min" and "max" can't be NaN`);if(e>t)throw new TypeError(`Parameter "min" can't be bigger than "max"`);return Math.floor(Math.random()*(t-e+1))+e}function H(n){return T(n)[0]}function T(n){if(n.length===0)return [void 0,void 0];let e=d(n.length-1);return [n[e],e]}function I(n){let[e,t]=T(n);if(t!==void 0)return n.splice(t,1),e}function C(n){let e=[...n];if(n.length===0)return n;for(let t=e.length-1;t>0;t--){let r=Math.floor(d(0,1e4)/1e4*(t+1));[e[t],e[r]]=[e[r],e[t]];}return e}function L(){try{return unsafeWindow}catch(n){return window}}function j(n,e){var t;return (t=n.parentNode)==null||t.insertBefore(e,n.nextSibling),e}function R(n,e){let t=n.parentNode;if(!t)throw new Error("Element doesn't have a parent node");return t.replaceChild(e,n),e.appendChild(n),e}function F(n){let e=document.createElement("style");e.innerHTML=n,document.head.appendChild(e);}function W(n,e=!1){let t=n.map(r=>new Promise((o,i)=>{let u=new Image;u.src=r,u.addEventListener("load",()=>o(u)),u.addEventListener("error",a=>e&&i(a));}));return Promise.allSettled(t)}function $(n){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:n}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function M(n,e,t){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&t()))return r.apply(this,o)};}(n.__proto__.addEventListener);}function q(n,e){return M(L(),n,e)}function G(n,e=1){let t=new(window.AudioContext||window.webkitAudioContext),r={mediaElement:n,amplify:o=>{r.gain.gain.value=o;},getAmpLevel:()=>r.gain.gain.value,context:t,source:t.createMediaElementSource(n),gain:t.createGain()};return r.source.connect(r.gain),r.gain.connect(t.destination),r.amplify(e),r}function B(n,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${n}${e===1?"":"s"}`}function U(n){return new Promise(e=>{setTimeout(e,n);})}function D(n,e=300){let t;return function(...r){clearTimeout(t),t=setTimeout(()=>n.apply(this,r),e);}}function J(t){return x(this,arguments,function*(n,e={}){let{timeout:r=1e4}=e,o=new AbortController,i=setTimeout(()=>o.abort(),r),u=yield fetch(n,b(m({},e),{signal:o.signal}));return clearTimeout(i),u})}var c=new Map;function V(n,e){let t=[];c.has(n)&&(t=c.get(n)),t.push(e),c.set(n,t),E(n,t);}function X(n){return c.delete(n)}function E(n,e){let t=[];if(e.forEach((r,o)=>{try{let i=r.all?document.querySelectorAll(n):document.querySelector(n);(i!==null&&i instanceof NodeList&&i.length>0||i!==null)&&(r.listener(i),r.continuous||t.push(o));}catch(i){console.error(`Couldn't call listener for selector '${n}'`,i);}}),t.length>0){let r=e.filter((o,i)=>!t.includes(i));r.length===0?c.delete(n):c.set(n,r);}}function Y(n={}){new MutationObserver(()=>{for(let[t,r]of c.entries())E(t,r);}).observe(document.body,m({subtree:!0,childList:!0},n));}function Z(){return c}
4
4
 
5
5
  exports.addGlobalStyle = F;
6
6
  exports.addParent = R;
7
+ exports.amplifyMedia = G;
7
8
  exports.autoPlural = B;
8
- exports.clamp = S;
9
- exports.debounce = U;
10
- exports.fetchAdvanced = D;
11
- exports.getSelectorMap = Y;
12
- exports.getUnsafeWindow = O;
13
- exports.initOnSelector = X;
14
- exports.insertAfter = C;
15
- exports.interceptEvent = L;
9
+ exports.clamp = A;
10
+ exports.debounce = D;
11
+ exports.fetchAdvanced = J;
12
+ exports.getSelectorMap = Z;
13
+ exports.getUnsafeWindow = L;
14
+ exports.initOnSelector = Y;
15
+ exports.insertAfter = j;
16
+ exports.interceptEvent = M;
16
17
  exports.interceptWindowEvent = q;
17
18
  exports.mapRange = N;
18
- exports.onSelector = Q;
19
+ exports.onSelector = V;
19
20
  exports.openInNewTab = $;
20
- exports.pauseFor = G;
21
+ exports.pauseFor = U;
21
22
  exports.preloadImages = W;
22
- exports.randRange = p;
23
- exports.randomItem = I;
24
- exports.randomItemIndex = x;
25
- exports.randomizeArray = P;
26
- exports.removeOnSelector = V;
27
- exports.takeRandomItem = H;
23
+ exports.randRange = d;
24
+ exports.randomItem = H;
25
+ exports.randomItemIndex = T;
26
+ exports.randomizeArray = C;
27
+ exports.removeOnSelector = X;
28
+ exports.takeRandomItem = I;
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- var h=Object.defineProperty,y=Object.defineProperties;var w=Object.getOwnPropertyDescriptors;var f=Object.getOwnPropertySymbols;var g=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var b=(t,e,n)=>e in t?h(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,a=(t,e)=>{for(var n in e||(e={}))g.call(e,n)&&b(t,n,e[n]);if(f)for(var n of f(e))v.call(e,n)&&b(t,n,e[n]);return t},d=(t,e)=>y(t,w(e));var T=(t,e,n)=>new Promise((r,o)=>{var i=c=>{try{m(n.next(c));}catch(l){o(l);}},u=c=>{try{m(n.throw(c));}catch(l){o(l);}},m=c=>c.done?r(c.value):Promise.resolve(c.value).then(i,u);m((n=n.apply(t,e)).next());});function S(t,e,n){return Math.max(Math.min(t,n),e)}function N(t,e,n,r,o){return Number(e)===0&&Number(r)===0?t*(o/n):(t-e)*((o-r)/(n-e))+r}function p(...t){let e,n;if(typeof t[0]=="number"&&typeof t[1]=="number")[e,n]=t;else if(typeof t[0]=="number"&&typeof t[1]!="number")e=0,n=t[0];else throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof t[0]}" and "${typeof t[1]}"`);if(e=Number(e),n=Number(n),isNaN(e)||isNaN(n))throw new TypeError(`Parameters "min" and "max" can't be NaN`);if(e>n)throw new TypeError(`Parameter "min" can't be bigger than "max"`);return Math.floor(Math.random()*(n-e+1))+e}function I(t){return x(t)[0]}function x(t){if(t.length===0)return [void 0,void 0];let e=p(t.length-1);return [t[e],e]}function H(t){let[e,n]=x(t);if(n!==void 0)return t.splice(n,1),e}function P(t){let e=[...t];if(t.length===0)return t;for(let n=e.length-1;n>0;n--){let r=Math.floor(p(0,1e4)/1e4*(n+1));[e[n],e[r]]=[e[r],e[n]];}return e}function O(){try{return unsafeWindow}catch(t){return window}}function C(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function R(t,e){let n=t.parentNode;if(!n)throw new Error("Element doesn't have a parent node");return n.replaceChild(e,t),e.appendChild(t),e}function F(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function W(t,e=!1){let n=t.map(r=>new Promise((o,i)=>{let u=new Image;u.src=r,u.addEventListener("load",()=>o(u)),u.addEventListener("error",m=>e&&i(m));}));return Promise.allSettled(n)}function $(t){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:t}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function L(t,e,n){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&n()))return r.apply(this,o)};}(t.__proto__.addEventListener);}function q(t,e){return L(O(),t,e)}function B(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function G(t){return new Promise(e=>{setTimeout(e,t);})}function U(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function D(n){return T(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,i=setTimeout(()=>o.abort(),r),u=yield fetch(t,d(a({},e),{signal:o.signal}));return clearTimeout(i),u})}var s=new Map;function Q(t,e){let n=[];s.has(t)&&(n=s.get(t)),n.push(e),s.set(t,n),E(t,n);}function V(t){return s.delete(t)}function E(t,e){let n=[];if(e.forEach((r,o)=>{try{let i=r.all?document.querySelectorAll(t):document.querySelector(t);i&&(r.listener(i),r.continuous||n.push(o));}catch(i){console.error(`Couldn't call listener for selector '${t}'`,i);}}),n.length>0){let r=e.filter((o,i)=>!n.includes(i));r.length===0?s.delete(t):s.set(t,r);}}function X(t={}){new MutationObserver(()=>{for(let[n,r]of s.entries())E(n,r);}).observe(document.body,d(a({},t),{childList:!0}));}function Y(){return s}
1
+ var h=Object.defineProperty,y=Object.defineProperties;var g=Object.getOwnPropertyDescriptors;var p=Object.getOwnPropertySymbols;var w=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var f=(n,e,t)=>e in n?h(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,m=(n,e)=>{for(var t in e||(e={}))w.call(e,t)&&f(n,t,e[t]);if(p)for(var t of p(e))v.call(e,t)&&f(n,t,e[t]);return n},b=(n,e)=>y(n,g(e));var x=(n,e,t)=>new Promise((r,o)=>{var i=s=>{try{a(t.next(s));}catch(l){o(l);}},u=s=>{try{a(t.throw(s));}catch(l){o(l);}},a=s=>s.done?r(s.value):Promise.resolve(s.value).then(i,u);a((t=t.apply(n,e)).next());});function A(n,e,t){return Math.max(Math.min(n,t),e)}function N(n,e,t,r,o){return Number(e)===0&&Number(r)===0?n*(o/t):(n-e)*((o-r)/(t-e))+r}function d(...n){let e,t;if(typeof n[0]=="number"&&typeof n[1]=="number")[e,t]=n;else if(typeof n[0]=="number"&&typeof n[1]!="number")e=0,t=n[0];else throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof n[0]}" and "${typeof n[1]}"`);if(e=Number(e),t=Number(t),isNaN(e)||isNaN(t))throw new TypeError(`Parameters "min" and "max" can't be NaN`);if(e>t)throw new TypeError(`Parameter "min" can't be bigger than "max"`);return Math.floor(Math.random()*(t-e+1))+e}function H(n){return T(n)[0]}function T(n){if(n.length===0)return [void 0,void 0];let e=d(n.length-1);return [n[e],e]}function I(n){let[e,t]=T(n);if(t!==void 0)return n.splice(t,1),e}function C(n){let e=[...n];if(n.length===0)return n;for(let t=e.length-1;t>0;t--){let r=Math.floor(d(0,1e4)/1e4*(t+1));[e[t],e[r]]=[e[r],e[t]];}return e}function L(){try{return unsafeWindow}catch(n){return window}}function j(n,e){var t;return (t=n.parentNode)==null||t.insertBefore(e,n.nextSibling),e}function R(n,e){let t=n.parentNode;if(!t)throw new Error("Element doesn't have a parent node");return t.replaceChild(e,n),e.appendChild(n),e}function F(n){let e=document.createElement("style");e.innerHTML=n,document.head.appendChild(e);}function W(n,e=!1){let t=n.map(r=>new Promise((o,i)=>{let u=new Image;u.src=r,u.addEventListener("load",()=>o(u)),u.addEventListener("error",a=>e&&i(a));}));return Promise.allSettled(t)}function $(n){let e=document.createElement("a");Object.assign(e,{className:"userutils-open-in-new-tab",target:"_blank",rel:"noopener noreferrer",href:n}),e.style.display="none",document.body.appendChild(e),e.click(),setTimeout(e.remove,50);}function M(n,e,t){typeof Error.stackTraceLimit=="number"&&Error.stackTraceLimit<1e3&&(Error.stackTraceLimit=1e3),function(r){element.__proto__.addEventListener=function(...o){if(!(o[0]===e&&t()))return r.apply(this,o)};}(n.__proto__.addEventListener);}function q(n,e){return M(L(),n,e)}function G(n,e=1){let t=new(window.AudioContext||window.webkitAudioContext),r={mediaElement:n,amplify:o=>{r.gain.gain.value=o;},getAmpLevel:()=>r.gain.gain.value,context:t,source:t.createMediaElementSource(n),gain:t.createGain()};return r.source.connect(r.gain),r.gain.connect(t.destination),r.amplify(e),r}function B(n,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${n}${e===1?"":"s"}`}function U(n){return new Promise(e=>{setTimeout(e,n);})}function D(n,e=300){let t;return function(...r){clearTimeout(t),t=setTimeout(()=>n.apply(this,r),e);}}function J(t){return x(this,arguments,function*(n,e={}){let{timeout:r=1e4}=e,o=new AbortController,i=setTimeout(()=>o.abort(),r),u=yield fetch(n,b(m({},e),{signal:o.signal}));return clearTimeout(i),u})}var c=new Map;function V(n,e){let t=[];c.has(n)&&(t=c.get(n)),t.push(e),c.set(n,t),E(n,t);}function X(n){return c.delete(n)}function E(n,e){let t=[];if(e.forEach((r,o)=>{try{let i=r.all?document.querySelectorAll(n):document.querySelector(n);(i!==null&&i instanceof NodeList&&i.length>0||i!==null)&&(r.listener(i),r.continuous||t.push(o));}catch(i){console.error(`Couldn't call listener for selector '${n}'`,i);}}),t.length>0){let r=e.filter((o,i)=>!t.includes(i));r.length===0?c.delete(n):c.set(n,r);}}function Y(n={}){new MutationObserver(()=>{for(let[t,r]of c.entries())E(t,r);}).observe(document.body,m({subtree:!0,childList:!0},n));}function Z(){return c}
2
2
 
3
- export { F as addGlobalStyle, R as addParent, B as autoPlural, S as clamp, U as debounce, D as fetchAdvanced, Y as getSelectorMap, O as getUnsafeWindow, X as initOnSelector, C as insertAfter, L as interceptEvent, q as interceptWindowEvent, N as mapRange, Q as onSelector, $ as openInNewTab, G as pauseFor, W as preloadImages, p as randRange, I as randomItem, x as randomItemIndex, P as randomizeArray, V as removeOnSelector, H as takeRandomItem };
3
+ export { F as addGlobalStyle, R as addParent, G as amplifyMedia, B as autoPlural, A as clamp, D as debounce, J as fetchAdvanced, Z as getSelectorMap, L as getUnsafeWindow, Y as initOnSelector, j as insertAfter, M as interceptEvent, q as interceptWindowEvent, N as mapRange, V as onSelector, $ as openInNewTab, U as pauseFor, W as preloadImages, d as randRange, H as randomItem, T as randomItemIndex, C as randomizeArray, X as removeOnSelector, I as takeRandomItem };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sv443-network/userutils",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, modify the DOM more easily and more ",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",