@sv443-network/userutils 0.2.0 → 0.4.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 +22 -0
- package/README.md +302 -114
- package/dist/index.d.mts +63 -47
- package/dist/index.d.ts +63 -47
- package/dist/index.js +20 -17
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @sv443-network/userutils
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 231a79c: Refactored code and documentation and added new functions:
|
|
8
|
+
- mapRange() to map a number from one range to the same spot in another range
|
|
9
|
+
- randRange() to generate a random number between a min and max boundary
|
|
10
|
+
- randomItem() to return a random item from an array
|
|
11
|
+
- randomItemIndex() to return a tuple of a random item and its index from an array
|
|
12
|
+
- takeRandomItem() to return a random item from an array and mutate it to remove the item
|
|
13
|
+
- randomizeArray() to return a copy of the array with its items in a random order
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 7edf837: decrease npm bundle size
|
|
18
|
+
|
|
19
|
+
## 0.3.0
|
|
20
|
+
|
|
21
|
+
### Minor Changes
|
|
22
|
+
|
|
23
|
+
- 07ec443: add getSelectorMap() to return all currently registered selectors
|
|
24
|
+
|
|
3
25
|
## 0.2.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,27 +1,41 @@
|
|
|
1
|
+
<div style="text-align: center;" align="center">
|
|
2
|
+
|
|
1
3
|
## UserUtils
|
|
2
4
|
Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, modify the DOM more easily and more.
|
|
3
|
-
Contains builtin TypeScript declarations.
|
|
5
|
+
Contains builtin TypeScript declarations. Webpack compatible and supports ESM and CJS.
|
|
4
6
|
|
|
7
|
+
</div>
|
|
5
8
|
<br>
|
|
6
9
|
|
|
7
10
|
## Table of Contents:
|
|
8
11
|
- [Installation](#installation)
|
|
9
12
|
- [Features](#features)
|
|
10
|
-
- [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
- [
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
- [DOM:](#dom)
|
|
14
|
+
- [onSelector()](#onselector) - call a listener once a selector is found in the DOM
|
|
15
|
+
- [initOnSelector()](#initonselector) - needs to be called once to be able to use `onSelector()`
|
|
16
|
+
- [getSelectorMap()](#getselectormap) - returns all currently registered selectors, listeners and options
|
|
17
|
+
- [getUnsafeWindow()](#getunsafewindow) - get the unsafeWindow object or fall back to the regular window object
|
|
18
|
+
- [insertAfter()](#insertafter) - insert an element as a sibling after another element
|
|
19
|
+
- [addParent()](#addparent) - add a parent element around another element
|
|
20
|
+
- [addGlobalStyle()](#addglobalstyle) - add a global style to the page
|
|
21
|
+
- [preloadImages()](#preloadimages) - preload images into the browser cache for faster loading later on
|
|
22
|
+
- [openInNewTab()](#openinnewtab) - open a link in a new tab
|
|
23
|
+
- [interceptEvent()](#interceptevent) - conditionally intercepts events registered by `addEventListener()` on any given EventTarget object
|
|
24
|
+
- [interceptWindowEvent()](#interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object
|
|
25
|
+
- [Math:](#math)
|
|
26
|
+
- [clamp()](#clamp) - clamp a number between a min and max value
|
|
27
|
+
- [mapRange()](#maprange) - map a number from one range to the same spot in another range
|
|
28
|
+
- [randRange()](#randrange) - generate a random number between a min and max boundary
|
|
29
|
+
- [Misc:](#misc)
|
|
30
|
+
- [autoPlural()](#autoplural) - automatically pluralize a string
|
|
31
|
+
- [pauseFor()](#pausefor) - pause the execution of a function for a given amount of time
|
|
32
|
+
- [debounce()](#debounce) - call a function only once, after a given amount of time
|
|
33
|
+
- [fetchAdvanced()](#fetchadvanced) - wrapper around the fetch API with a timeout option
|
|
34
|
+
- [Arrays:](#arrays)
|
|
35
|
+
- [randomItem()](#randomitem) - returns a random item from an array
|
|
36
|
+
- [randomItemIndex()](#randomitemindex) - returns a tuple of a random item and its index from an array
|
|
37
|
+
- [takeRandomItem()](#takerandomitem) - returns a random item from an array and mutates it to remove the item
|
|
38
|
+
- [randomizeArray()](#randomizearray) - returns a copy of the array with its items in a random order
|
|
25
39
|
- [License](#license)
|
|
26
40
|
|
|
27
41
|
<br><br>
|
|
@@ -54,6 +68,8 @@ If you like using this library, please consider [supporting development](https:/
|
|
|
54
68
|
|
|
55
69
|
## Features:
|
|
56
70
|
|
|
71
|
+
## DOM:
|
|
72
|
+
|
|
57
73
|
### onSelector()
|
|
58
74
|
Usage:
|
|
59
75
|
```ts
|
|
@@ -69,7 +85,7 @@ If the selector already exists, the listener will be called immediately.
|
|
|
69
85
|
|
|
70
86
|
If `all` is set to `true`, querySelectorAll() will be used instead and the listener will return a NodeList of matching elements.
|
|
71
87
|
This will also include elements that were already found in a previous listener call.
|
|
72
|
-
If set to `false` (default), querySelector() will be used and only the first element will be returned.
|
|
88
|
+
If set to `false` (default), querySelector() will be used and only the first matching element will be returned.
|
|
73
89
|
|
|
74
90
|
If `continuous` is set to `true`, the listener will not be deregistered after it was called once (defaults to false).
|
|
75
91
|
|
|
@@ -86,18 +102,18 @@ Calling onSelector() before `DOMContentLoaded` is fired will not throw an error,
|
|
|
86
102
|
document.addEventListener("DOMContentLoaded", initOnSelector);
|
|
87
103
|
|
|
88
104
|
// Continuously checks if `div` elements are added to the DOM, then returns all of them (even previously detected ones) in a NodeList
|
|
89
|
-
onSelector("div", {
|
|
90
|
-
listener: (
|
|
91
|
-
console.log("Elements found:",
|
|
105
|
+
onSelector<HTMLDivElement>("div", {
|
|
106
|
+
listener: (elements) => {
|
|
107
|
+
console.log("Elements found:", elements); // type = NodeListOf<HTMLDivElement>
|
|
92
108
|
},
|
|
93
109
|
all: true,
|
|
94
110
|
continuous: true,
|
|
95
111
|
});
|
|
96
112
|
|
|
97
113
|
// Checks if an input element with a value attribute of "5" is added to the DOM, then returns it and deregisters the listener
|
|
98
|
-
onSelector("input[value=\"5\"]", {
|
|
114
|
+
onSelector<HTMLInputElement>("input[value=\"5\"]", {
|
|
99
115
|
listener: (element) => {
|
|
100
|
-
console.log("Element found:", element);
|
|
116
|
+
console.log("Element found:", element); // type = HTMLInputElement
|
|
101
117
|
},
|
|
102
118
|
});
|
|
103
119
|
```
|
|
@@ -109,7 +125,7 @@ onSelector("input[value=\"5\"]", {
|
|
|
109
125
|
### initOnSelector()
|
|
110
126
|
Usage:
|
|
111
127
|
```ts
|
|
112
|
-
initOnSelector(options
|
|
128
|
+
initOnSelector(options?: {
|
|
113
129
|
attributes?: boolean,
|
|
114
130
|
characterData?: boolean,
|
|
115
131
|
}): void
|
|
@@ -140,76 +156,40 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
140
156
|
|
|
141
157
|
<br>
|
|
142
158
|
|
|
143
|
-
###
|
|
144
|
-
Usage: `
|
|
145
|
-
|
|
146
|
-
Automatically pluralizes a string if the given number is not 1.
|
|
147
|
-
If an array or NodeList is passed, the length of it will be used.
|
|
148
|
-
|
|
149
|
-
<details><summary><b>Example - click to view</b></summary>
|
|
150
|
-
|
|
151
|
-
```ts
|
|
152
|
-
autoPlural("apple", 0); // "apples"
|
|
153
|
-
autoPlural("apple", 1); // "apple"
|
|
154
|
-
autoPlural("apple", 2); // "apples"
|
|
155
|
-
|
|
156
|
-
autoPlural("apple", [1]); // "apple"
|
|
157
|
-
autoPlural("apple", [1, 2]); // "apples"
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
</details>
|
|
161
|
-
|
|
162
|
-
<br>
|
|
163
|
-
|
|
164
|
-
### clamp()
|
|
165
|
-
Usage: `clamp(num: number, min: number, max: number): number`
|
|
166
|
-
|
|
167
|
-
Clamps a number between a min and max value.
|
|
168
|
-
|
|
169
|
-
<details><summary><b>Example - click to view</b></summary>
|
|
170
|
-
|
|
171
|
-
```ts
|
|
172
|
-
clamp(5, 0, 10); // 5
|
|
173
|
-
clamp(-1, 0, 10); // 0
|
|
174
|
-
clamp(Infinity, 0, 10); // 10
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
</details>
|
|
178
|
-
|
|
179
|
-
<br>
|
|
180
|
-
|
|
181
|
-
### pauseFor()
|
|
182
|
-
Usage: `pauseFor(ms: number): Promise<void>`
|
|
159
|
+
### getSelectorMap()
|
|
160
|
+
Usage: `getSelectorMap(): Map<string, OnSelectorOptions[]>`
|
|
183
161
|
|
|
184
|
-
|
|
162
|
+
Returns a Map of all currently registered selectors and their options, including listener function.
|
|
163
|
+
Since multiple listeners can be registered for the same selector, the value of the Map is an array of `OnSelectorOptions` objects.
|
|
185
164
|
|
|
186
165
|
<details><summary><b>Example - click to view</b></summary>
|
|
187
166
|
|
|
188
167
|
```ts
|
|
189
|
-
|
|
190
|
-
console.log("Hello");
|
|
191
|
-
await pauseFor(3000); // waits for 3 seconds
|
|
192
|
-
console.log("World");
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
</details>
|
|
168
|
+
document.addEventListener("DOMContentLoaded", initOnSelector);
|
|
197
169
|
|
|
198
|
-
<
|
|
170
|
+
onSelector<HTMLDivElement>("div", {
|
|
171
|
+
listener: (elements) => void 0,
|
|
172
|
+
all: true,
|
|
173
|
+
continuous: true,
|
|
174
|
+
});
|
|
199
175
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
Debounces a function, meaning that it will only be called once after a given amount of time.
|
|
204
|
-
This is very useful for functions that are called repeatedly, like event listeners, to remove extraneous calls.
|
|
205
|
-
The timeout will default to 300ms if left undefined.
|
|
206
|
-
|
|
207
|
-
<details><summary><b>Example - click to view</b></summary>
|
|
176
|
+
onSelector<HTMLDivElement>("div", {
|
|
177
|
+
listener: (elements) => void 0,
|
|
178
|
+
});
|
|
208
179
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
180
|
+
const selectorMap = getSelectorMap();
|
|
181
|
+
// Map(1) {
|
|
182
|
+
// "div" => [
|
|
183
|
+
// {
|
|
184
|
+
// listener: (elements) => void 0,
|
|
185
|
+
// all: true,
|
|
186
|
+
// continuous: true,
|
|
187
|
+
// },
|
|
188
|
+
// {
|
|
189
|
+
// listener: (elements) => void 0,
|
|
190
|
+
// },
|
|
191
|
+
// ]
|
|
192
|
+
// }
|
|
213
193
|
```
|
|
214
194
|
|
|
215
195
|
</details>
|
|
@@ -225,8 +205,13 @@ Userscripts are sandboxed and do not have access to the regular window object, s
|
|
|
225
205
|
<details><summary><b>Example - click to view</b></summary>
|
|
226
206
|
|
|
227
207
|
```ts
|
|
228
|
-
|
|
208
|
+
// trick the site into thinking the mouse was moved:
|
|
209
|
+
const mouseEvent = new MouseEvent("mousemove", {
|
|
229
210
|
view: getUnsafeWindow(),
|
|
211
|
+
screenY: 69,
|
|
212
|
+
screenX: 420,
|
|
213
|
+
movementX: 10,
|
|
214
|
+
movementY: 0,
|
|
230
215
|
});
|
|
231
216
|
document.body.dispatchEvent(mouseEvent);
|
|
232
217
|
```
|
|
@@ -246,6 +231,7 @@ The passed `afterElement` will be returned.
|
|
|
246
231
|
<details><summary><b>Example - click to view</b></summary>
|
|
247
232
|
|
|
248
233
|
```ts
|
|
234
|
+
// insert a <div> as a sibling next to an element
|
|
249
235
|
const beforeElement = document.querySelector("#before");
|
|
250
236
|
const afterElement = document.createElement("div");
|
|
251
237
|
afterElement.innerText = "After";
|
|
@@ -267,6 +253,7 @@ Previously registered event listeners are kept intact.
|
|
|
267
253
|
<details><summary><b>Example - click to view</b></summary>
|
|
268
254
|
|
|
269
255
|
```ts
|
|
256
|
+
// add an <a> around an element
|
|
270
257
|
const element = document.querySelector("#element");
|
|
271
258
|
const newParent = document.createElement("a");
|
|
272
259
|
newParent.href = "https://example.org/";
|
|
@@ -323,6 +310,191 @@ preloadImages([
|
|
|
323
310
|
|
|
324
311
|
<br>
|
|
325
312
|
|
|
313
|
+
### openInNewTab()
|
|
314
|
+
Usage: `openInNewTab(url: string): void`
|
|
315
|
+
|
|
316
|
+
Creates an invisible anchor with a `_blank` target and clicks it.
|
|
317
|
+
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.
|
|
319
|
+
|
|
320
|
+
⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
|
|
321
|
+
|
|
322
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
document.querySelector("#my-button").addEventListener("click", () => {
|
|
326
|
+
openInNewTab("https://example.org/");
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
</details>
|
|
331
|
+
|
|
332
|
+
<br>
|
|
333
|
+
|
|
334
|
+
### interceptEvent()
|
|
335
|
+
Usage: `interceptEvent(eventObject: EventTarget, eventName: string, predicate: () => boolean): void`
|
|
336
|
+
|
|
337
|
+
Intercepts all events dispatched on the `eventObject` and prevents the listeners from being called as long as the predicate function returns a truthy value.
|
|
338
|
+
Calling this function will set the `Error.stackTraceLimit` to 1000 (if it's not already higher) to ensure the stack trace is preserved.
|
|
339
|
+
|
|
340
|
+
⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
|
|
341
|
+
|
|
342
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
interceptEvent(document.body, "click", () => {
|
|
346
|
+
return true; // prevent all click events on the body element
|
|
347
|
+
});
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
</details>
|
|
351
|
+
|
|
352
|
+
<br>
|
|
353
|
+
|
|
354
|
+
### interceptWindowEvent()
|
|
355
|
+
Usage: `interceptWindowEvent(eventName: string, predicate: () => boolean): void`
|
|
356
|
+
|
|
357
|
+
Intercepts all events dispatched on the `window` object and prevents the listeners from being called as long as the predicate function returns a truthy value.
|
|
358
|
+
This is essentially the same as [`interceptEvent()`](#interceptevent), but automatically uses the `unsafeWindow` (or falls back to regular `window`).
|
|
359
|
+
|
|
360
|
+
⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
|
|
361
|
+
|
|
362
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
363
|
+
|
|
364
|
+
```ts
|
|
365
|
+
interceptWindowEvent("beforeunload", () => {
|
|
366
|
+
return true; // prevent the pesky "Are you sure you want to leave this page?" popup
|
|
367
|
+
});
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
</details>
|
|
371
|
+
|
|
372
|
+
<br><br>
|
|
373
|
+
|
|
374
|
+
## Math:
|
|
375
|
+
|
|
376
|
+
### clamp()
|
|
377
|
+
Usage: `clamp(num: number, min: number, max: number): number`
|
|
378
|
+
|
|
379
|
+
Clamps a number between a min and max value.
|
|
380
|
+
|
|
381
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
382
|
+
|
|
383
|
+
```ts
|
|
384
|
+
clamp(5, 0, 10); // 5
|
|
385
|
+
clamp(-1, 0, 10); // 0
|
|
386
|
+
clamp(7, 0, 10); // 7
|
|
387
|
+
clamp(Infinity, 0, 10); // 10
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
</details>
|
|
391
|
+
|
|
392
|
+
<br>
|
|
393
|
+
|
|
394
|
+
### mapRange()
|
|
395
|
+
Usage: `mapRange(value: number, range_1_min: number, range_1_max: number, range_2_min: number, range_2_max: number): number`
|
|
396
|
+
|
|
397
|
+
Maps a number from one range to the spot it would be in another range.
|
|
398
|
+
|
|
399
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
400
|
+
|
|
401
|
+
```ts
|
|
402
|
+
mapRange(5, 0, 10, 0, 100); // 50
|
|
403
|
+
mapRange(5, 0, 10, 0, 50); // 25
|
|
404
|
+
// to calculate a percentage from arbitrary values, use 0 and 100 as the second range:
|
|
405
|
+
mapRange(4, 0, 13, 0, 100); // 30.76923076923077
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
</details>
|
|
409
|
+
|
|
410
|
+
<br>
|
|
411
|
+
|
|
412
|
+
### randRange()
|
|
413
|
+
Usages:
|
|
414
|
+
```ts
|
|
415
|
+
randRange(min: number, max: number): number
|
|
416
|
+
randRange(max: number): number
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Returns a random number between `min` and `max` (inclusive).
|
|
420
|
+
If only one argument is passed, it will be used as the `max` value and `min` will be set to 0.
|
|
421
|
+
|
|
422
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
423
|
+
|
|
424
|
+
```ts
|
|
425
|
+
randRange(0, 10); // 4
|
|
426
|
+
randRange(10, 20); // 17
|
|
427
|
+
randRange(10); // 7
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
</details>
|
|
431
|
+
|
|
432
|
+
<br><br>
|
|
433
|
+
|
|
434
|
+
## Misc:
|
|
435
|
+
|
|
436
|
+
### autoPlural()
|
|
437
|
+
Usage: `autoPlural(str: string, num: number | Array | NodeList): string`
|
|
438
|
+
|
|
439
|
+
Automatically pluralizes a string if the given number is not 1.
|
|
440
|
+
If an array or NodeList is passed, the length of it will be used.
|
|
441
|
+
|
|
442
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
443
|
+
|
|
444
|
+
```ts
|
|
445
|
+
autoPlural("apple", 0); // "apples"
|
|
446
|
+
autoPlural("apple", 1); // "apple"
|
|
447
|
+
autoPlural("apple", 2); // "apples"
|
|
448
|
+
|
|
449
|
+
autoPlural("apple", [1]); // "apple"
|
|
450
|
+
autoPlural("apple", [1, 2]); // "apples"
|
|
451
|
+
|
|
452
|
+
const items = [1, 2, 3, 4, "foo", "bar"];
|
|
453
|
+
console.log(`Found ${items.length} ${autoPlural("item", items)}`); // "Found 6 items"
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
</details>
|
|
457
|
+
|
|
458
|
+
<br>
|
|
459
|
+
|
|
460
|
+
### pauseFor()
|
|
461
|
+
Usage: `pauseFor(ms: number): Promise<void>`
|
|
462
|
+
|
|
463
|
+
Pauses async execution for a given amount of time.
|
|
464
|
+
|
|
465
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
async function run() {
|
|
469
|
+
console.log("Hello");
|
|
470
|
+
await pauseFor(3000); // waits for 3 seconds
|
|
471
|
+
console.log("World");
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
</details>
|
|
476
|
+
|
|
477
|
+
<br>
|
|
478
|
+
|
|
479
|
+
### debounce()
|
|
480
|
+
Usage: `debounce(func: Function, timeout?: number): Function`
|
|
481
|
+
|
|
482
|
+
Debounces a function, meaning that it will only be called once after a given amount of time.
|
|
483
|
+
This is very useful for functions that are called repeatedly, like event listeners, to remove extraneous calls.
|
|
484
|
+
The timeout will default to 300ms if left undefined.
|
|
485
|
+
|
|
486
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
487
|
+
|
|
488
|
+
```ts
|
|
489
|
+
window.addEventListener("resize", debounce((event) => {
|
|
490
|
+
console.log("Window was resized:", event);
|
|
491
|
+
}, 500)); // 500ms timeout
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
</details>
|
|
495
|
+
|
|
496
|
+
<br>
|
|
497
|
+
|
|
326
498
|
### fetchAdvanced()
|
|
327
499
|
Usage:
|
|
328
500
|
```ts
|
|
@@ -340,6 +512,7 @@ The timeout will default to 10 seconds if left undefined.
|
|
|
340
512
|
```ts
|
|
341
513
|
fetchAdvanced("https://api.example.org/data", {
|
|
342
514
|
timeout: 5000,
|
|
515
|
+
// also accepts any other fetch options like headers:
|
|
343
516
|
headers: {
|
|
344
517
|
"Accept": "application/json",
|
|
345
518
|
},
|
|
@@ -350,67 +523,82 @@ fetchAdvanced("https://api.example.org/data", {
|
|
|
350
523
|
|
|
351
524
|
</details>
|
|
352
525
|
|
|
353
|
-
<br>
|
|
526
|
+
<br><br>
|
|
354
527
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
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.
|
|
360
|
-
This function has to be run in relatively quick succession in response to a user interaction event, else the browser might reject it.
|
|
528
|
+
## Arrays:
|
|
529
|
+
|
|
530
|
+
### randomItem()
|
|
531
|
+
Usage: `randomItem(array: Array): any`
|
|
361
532
|
|
|
362
|
-
|
|
533
|
+
Returns a random item from an array.
|
|
534
|
+
Returns undefined if the array is empty.
|
|
363
535
|
|
|
364
536
|
<details><summary><b>Example - click to view</b></summary>
|
|
365
537
|
|
|
366
538
|
```ts
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
});
|
|
539
|
+
randomItem(["foo", "bar", "baz"]); // "bar"
|
|
540
|
+
randomItem([ ]); // undefined
|
|
370
541
|
```
|
|
371
542
|
|
|
372
543
|
</details>
|
|
373
544
|
|
|
374
545
|
<br>
|
|
375
546
|
|
|
376
|
-
###
|
|
377
|
-
Usage: `
|
|
547
|
+
### randomItemIndex()
|
|
548
|
+
Usage: `randomItemIndex(array: Array): [item: any, index: number]`
|
|
378
549
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
⚠️ This function should be called as soon as possible (I recommend using `@run-at document-start`), as it will only intercept events that are *attached* after this function is called.
|
|
550
|
+
Returns a tuple of a random item and its index from an array.
|
|
551
|
+
If the array is empty, it will return undefined for both values.
|
|
383
552
|
|
|
384
553
|
<details><summary><b>Example - click to view</b></summary>
|
|
385
554
|
|
|
386
555
|
```ts
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
556
|
+
randomItemIndex(["foo", "bar", "baz"]); // ["bar", 1]
|
|
557
|
+
randomItemIndex([ ]); // [undefined, undefined]
|
|
558
|
+
// using array destructuring:
|
|
559
|
+
const [item, index] = randomItemIndex(["foo", "bar", "baz"]);
|
|
560
|
+
// or if you only want the index:
|
|
561
|
+
const [, index] = randomItemIndex(["foo", "bar", "baz"]);
|
|
390
562
|
```
|
|
391
563
|
|
|
392
564
|
</details>
|
|
393
565
|
|
|
394
566
|
<br>
|
|
395
567
|
|
|
396
|
-
###
|
|
397
|
-
Usage: `
|
|
568
|
+
### takeRandomItem()
|
|
569
|
+
Usage: `takeRandomItem(array: Array): any`
|
|
398
570
|
|
|
399
|
-
|
|
400
|
-
|
|
571
|
+
Returns a random item from an array and mutates the array by removing the item.
|
|
572
|
+
Returns undefined if the array is empty.
|
|
401
573
|
|
|
402
|
-
|
|
574
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
575
|
+
|
|
576
|
+
```ts
|
|
577
|
+
const arr = ["foo", "bar", "baz"];
|
|
578
|
+
takeRandomItem(arr); // "bar"
|
|
579
|
+
console.log(arr); // ["foo", "baz"]
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
</details>
|
|
583
|
+
|
|
584
|
+
<br>
|
|
585
|
+
|
|
586
|
+
### randomizeArray()
|
|
587
|
+
Usage: `randomizeArray(array: Array): Array`
|
|
588
|
+
|
|
589
|
+
Returns a copy of the array with its items in a random order.
|
|
590
|
+
If the array is empty, the originally passed array will be returned.
|
|
403
591
|
|
|
404
592
|
<details><summary><b>Example - click to view</b></summary>
|
|
405
593
|
|
|
406
594
|
```ts
|
|
407
|
-
|
|
408
|
-
return true; // prevent the pesky "Are you sure you want to leave this page?" popup
|
|
409
|
-
});
|
|
595
|
+
randomizeArray([1, 2, 3, 4, 5, 6]); // [3, 1, 5, 2, 4, 6]
|
|
410
596
|
```
|
|
411
597
|
|
|
412
598
|
</details>
|
|
413
599
|
|
|
600
|
+
<br>
|
|
601
|
+
|
|
414
602
|
|
|
415
603
|
<br><br>
|
|
416
604
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,46 +1,3 @@
|
|
|
1
|
-
type InitOnSelectorOpts = {
|
|
2
|
-
/** 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) */
|
|
3
|
-
attributes?: boolean;
|
|
4
|
-
/** 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) */
|
|
5
|
-
characterData?: boolean;
|
|
6
|
-
};
|
|
7
|
-
type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
|
|
8
|
-
type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
|
|
9
|
-
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
10
|
-
all?: false;
|
|
11
|
-
/** Gets called whenever the selector was found in the DOM */
|
|
12
|
-
listener: (element: TElem) => void;
|
|
13
|
-
};
|
|
14
|
-
type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
|
|
15
|
-
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
16
|
-
all: true;
|
|
17
|
-
/** Gets called whenever the selector was found in the DOM */
|
|
18
|
-
listener: (elements: NodeListOf<TElem>) => void;
|
|
19
|
-
};
|
|
20
|
-
type SelectorOptsBase = {
|
|
21
|
-
/** Whether to call the listener continuously instead of once - default is false */
|
|
22
|
-
continuous?: boolean;
|
|
23
|
-
};
|
|
24
|
-
type FetchAdvancedOpts = RequestInit & Partial<{
|
|
25
|
-
/** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
|
|
26
|
-
timeout: number;
|
|
27
|
-
}>;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Automatically appends an `s` to the passed `word`, if `num` is not equal to 1
|
|
31
|
-
* @param word A word in singular form, to auto-convert to plural
|
|
32
|
-
* @param num If this is an array or NodeList, the amount of items is used
|
|
33
|
-
*/
|
|
34
|
-
declare function autoPlural(word: string, num: number | unknown[] | NodeList): string;
|
|
35
|
-
/** Ensures the passed `value` always stays between `min` and `max` */
|
|
36
|
-
declare function clamp(value: number, min: number, max: number): number;
|
|
37
|
-
/** Pauses async execution for the specified time in ms */
|
|
38
|
-
declare function pauseFor(time: number): Promise<unknown>;
|
|
39
|
-
/**
|
|
40
|
-
* Calls the passed `func` after the specified `timeout` in ms.
|
|
41
|
-
* Any subsequent calls to this function will reset the timer and discard previous calls.
|
|
42
|
-
*/
|
|
43
|
-
declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
|
|
44
1
|
/**
|
|
45
2
|
* Returns `unsafeWindow` if the `@grant unsafeWindow` is given, otherwise falls back to the regular `window`
|
|
46
3
|
*/
|
|
@@ -67,8 +24,6 @@ declare function addGlobalStyle(style: string): void;
|
|
|
67
24
|
* @returns Returns an array of `PromiseSettledResult` - each resolved result will contain the loaded image element, while each rejected result will contain an `ErrorEvent`
|
|
68
25
|
*/
|
|
69
26
|
declare function preloadImages(srcUrls: string[], rejects?: boolean): Promise<PromiseSettledResult<unknown>[]>;
|
|
70
|
-
/** Calls the fetch API with special options like a timeout */
|
|
71
|
-
declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
|
|
72
27
|
/**
|
|
73
28
|
* Creates an invisible anchor with a `_blank` target and clicks it.
|
|
74
29
|
* 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.
|
|
@@ -89,6 +44,62 @@ declare function interceptEvent<TEvtObj extends EventTarget>(eventObject: TEvtOb
|
|
|
89
44
|
*/
|
|
90
45
|
declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate: () => boolean): void;
|
|
91
46
|
|
|
47
|
+
/** Ensures the passed `value` always stays between `min` and `max` */
|
|
48
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
49
|
+
/**
|
|
50
|
+
* Transforms the value parameter from the numerical range `range_1_min-range_1_max` to the numerical range `range_2_min-range_2_max`
|
|
51
|
+
* For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
|
|
52
|
+
*/
|
|
53
|
+
declare function mapRange(value: number, range_1_min: number, range_1_max: number, range_2_min: number, range_2_max: number): number;
|
|
54
|
+
/** Returns a random number between `min` and `max` (inclusive) */
|
|
55
|
+
declare function randRange(min: number, max: number): number;
|
|
56
|
+
/** Returns a random number between 0 and `max` (inclusive) */
|
|
57
|
+
declare function randRange(max: number): number;
|
|
58
|
+
|
|
59
|
+
type InitOnSelectorOpts = {
|
|
60
|
+
/** 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) */
|
|
61
|
+
attributes?: boolean;
|
|
62
|
+
/** 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) */
|
|
63
|
+
characterData?: boolean;
|
|
64
|
+
};
|
|
65
|
+
type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
|
|
66
|
+
type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
|
|
67
|
+
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
68
|
+
all?: false;
|
|
69
|
+
/** Gets called whenever the selector was found in the DOM */
|
|
70
|
+
listener: (element: TElem) => void;
|
|
71
|
+
};
|
|
72
|
+
type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
|
|
73
|
+
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
74
|
+
all: true;
|
|
75
|
+
/** Gets called whenever the selector was found in the DOM */
|
|
76
|
+
listener: (elements: NodeListOf<TElem>) => void;
|
|
77
|
+
};
|
|
78
|
+
type SelectorOptsBase = {
|
|
79
|
+
/** Whether to call the listener continuously instead of once - default is false */
|
|
80
|
+
continuous?: boolean;
|
|
81
|
+
};
|
|
82
|
+
type FetchAdvancedOpts = RequestInit & Partial<{
|
|
83
|
+
/** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
|
|
84
|
+
timeout: number;
|
|
85
|
+
}>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Automatically appends an `s` to the passed `word`, if `num` is not equal to 1
|
|
89
|
+
* @param word A word in singular form, to auto-convert to plural
|
|
90
|
+
* @param num If this is an array or NodeList, the amount of items is used
|
|
91
|
+
*/
|
|
92
|
+
declare function autoPlural(word: string, num: number | unknown[] | NodeList): string;
|
|
93
|
+
/** Pauses async execution for the specified time in ms */
|
|
94
|
+
declare function pauseFor(time: number): Promise<unknown>;
|
|
95
|
+
/**
|
|
96
|
+
* Calls the passed `func` after the specified `timeout` in ms.
|
|
97
|
+
* Any subsequent calls to this function will reset the timer and discard previous calls.
|
|
98
|
+
*/
|
|
99
|
+
declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
|
|
100
|
+
/** Calls the fetch API with special options like a timeout */
|
|
101
|
+
declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
|
|
102
|
+
|
|
92
103
|
/**
|
|
93
104
|
* Calls the `listener` as soon as the `selector` exists in the DOM.
|
|
94
105
|
* Listeners are deleted when they are called once, unless `options.continuous` is set.
|
|
@@ -98,12 +109,17 @@ declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate
|
|
|
98
109
|
* @template TElem The type of element that the listener will return as its argument (defaults to the generic HTMLElement)
|
|
99
110
|
*/
|
|
100
111
|
declare function onSelector<TElem extends Element = HTMLElement>(selector: string, options: OnSelectorOpts<TElem>): void;
|
|
101
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* Removes all listeners registered in `onSelector()` that have the given selector
|
|
114
|
+
* @returns Returns true when all listeners with the associated selector were found and removed, false otherwise
|
|
115
|
+
*/
|
|
102
116
|
declare function removeOnSelector(selector: string): boolean;
|
|
103
117
|
/**
|
|
104
118
|
* Initializes a MutationObserver that checks for all registered selectors whenever an element is added to or removed from the `<body>`
|
|
105
119
|
* @param opts For fine-tuning when the MutationObserver checks for the selectors
|
|
106
120
|
*/
|
|
107
121
|
declare function initOnSelector(opts?: InitOnSelectorOpts): void;
|
|
122
|
+
/** Returns all currently registered selectors, as a map of selector strings to their associated options */
|
|
123
|
+
declare function getSelectorMap(): Map<string, OnSelectorOpts[]>;
|
|
108
124
|
|
|
109
|
-
export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
|
|
125
|
+
export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, removeOnSelector };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,46 +1,3 @@
|
|
|
1
|
-
type InitOnSelectorOpts = {
|
|
2
|
-
/** 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) */
|
|
3
|
-
attributes?: boolean;
|
|
4
|
-
/** 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) */
|
|
5
|
-
characterData?: boolean;
|
|
6
|
-
};
|
|
7
|
-
type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
|
|
8
|
-
type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
|
|
9
|
-
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
10
|
-
all?: false;
|
|
11
|
-
/** Gets called whenever the selector was found in the DOM */
|
|
12
|
-
listener: (element: TElem) => void;
|
|
13
|
-
};
|
|
14
|
-
type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
|
|
15
|
-
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
16
|
-
all: true;
|
|
17
|
-
/** Gets called whenever the selector was found in the DOM */
|
|
18
|
-
listener: (elements: NodeListOf<TElem>) => void;
|
|
19
|
-
};
|
|
20
|
-
type SelectorOptsBase = {
|
|
21
|
-
/** Whether to call the listener continuously instead of once - default is false */
|
|
22
|
-
continuous?: boolean;
|
|
23
|
-
};
|
|
24
|
-
type FetchAdvancedOpts = RequestInit & Partial<{
|
|
25
|
-
/** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
|
|
26
|
-
timeout: number;
|
|
27
|
-
}>;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Automatically appends an `s` to the passed `word`, if `num` is not equal to 1
|
|
31
|
-
* @param word A word in singular form, to auto-convert to plural
|
|
32
|
-
* @param num If this is an array or NodeList, the amount of items is used
|
|
33
|
-
*/
|
|
34
|
-
declare function autoPlural(word: string, num: number | unknown[] | NodeList): string;
|
|
35
|
-
/** Ensures the passed `value` always stays between `min` and `max` */
|
|
36
|
-
declare function clamp(value: number, min: number, max: number): number;
|
|
37
|
-
/** Pauses async execution for the specified time in ms */
|
|
38
|
-
declare function pauseFor(time: number): Promise<unknown>;
|
|
39
|
-
/**
|
|
40
|
-
* Calls the passed `func` after the specified `timeout` in ms.
|
|
41
|
-
* Any subsequent calls to this function will reset the timer and discard previous calls.
|
|
42
|
-
*/
|
|
43
|
-
declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
|
|
44
1
|
/**
|
|
45
2
|
* Returns `unsafeWindow` if the `@grant unsafeWindow` is given, otherwise falls back to the regular `window`
|
|
46
3
|
*/
|
|
@@ -67,8 +24,6 @@ declare function addGlobalStyle(style: string): void;
|
|
|
67
24
|
* @returns Returns an array of `PromiseSettledResult` - each resolved result will contain the loaded image element, while each rejected result will contain an `ErrorEvent`
|
|
68
25
|
*/
|
|
69
26
|
declare function preloadImages(srcUrls: string[], rejects?: boolean): Promise<PromiseSettledResult<unknown>[]>;
|
|
70
|
-
/** Calls the fetch API with special options like a timeout */
|
|
71
|
-
declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
|
|
72
27
|
/**
|
|
73
28
|
* Creates an invisible anchor with a `_blank` target and clicks it.
|
|
74
29
|
* 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.
|
|
@@ -89,6 +44,62 @@ declare function interceptEvent<TEvtObj extends EventTarget>(eventObject: TEvtOb
|
|
|
89
44
|
*/
|
|
90
45
|
declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate: () => boolean): void;
|
|
91
46
|
|
|
47
|
+
/** Ensures the passed `value` always stays between `min` and `max` */
|
|
48
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
49
|
+
/**
|
|
50
|
+
* Transforms the value parameter from the numerical range `range_1_min-range_1_max` to the numerical range `range_2_min-range_2_max`
|
|
51
|
+
* For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
|
|
52
|
+
*/
|
|
53
|
+
declare function mapRange(value: number, range_1_min: number, range_1_max: number, range_2_min: number, range_2_max: number): number;
|
|
54
|
+
/** Returns a random number between `min` and `max` (inclusive) */
|
|
55
|
+
declare function randRange(min: number, max: number): number;
|
|
56
|
+
/** Returns a random number between 0 and `max` (inclusive) */
|
|
57
|
+
declare function randRange(max: number): number;
|
|
58
|
+
|
|
59
|
+
type InitOnSelectorOpts = {
|
|
60
|
+
/** 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) */
|
|
61
|
+
attributes?: boolean;
|
|
62
|
+
/** 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) */
|
|
63
|
+
characterData?: boolean;
|
|
64
|
+
};
|
|
65
|
+
type OnSelectorOpts<TElem extends Element = HTMLElement> = SelectorOptsOne<TElem> | SelectorOptsAll<TElem>;
|
|
66
|
+
type SelectorOptsOne<TElem extends Element> = SelectorOptsBase & {
|
|
67
|
+
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
68
|
+
all?: false;
|
|
69
|
+
/** Gets called whenever the selector was found in the DOM */
|
|
70
|
+
listener: (element: TElem) => void;
|
|
71
|
+
};
|
|
72
|
+
type SelectorOptsAll<TElem extends Element> = SelectorOptsBase & {
|
|
73
|
+
/** Whether to use `querySelectorAll()` instead - default is false */
|
|
74
|
+
all: true;
|
|
75
|
+
/** Gets called whenever the selector was found in the DOM */
|
|
76
|
+
listener: (elements: NodeListOf<TElem>) => void;
|
|
77
|
+
};
|
|
78
|
+
type SelectorOptsBase = {
|
|
79
|
+
/** Whether to call the listener continuously instead of once - default is false */
|
|
80
|
+
continuous?: boolean;
|
|
81
|
+
};
|
|
82
|
+
type FetchAdvancedOpts = RequestInit & Partial<{
|
|
83
|
+
/** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
|
|
84
|
+
timeout: number;
|
|
85
|
+
}>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Automatically appends an `s` to the passed `word`, if `num` is not equal to 1
|
|
89
|
+
* @param word A word in singular form, to auto-convert to plural
|
|
90
|
+
* @param num If this is an array or NodeList, the amount of items is used
|
|
91
|
+
*/
|
|
92
|
+
declare function autoPlural(word: string, num: number | unknown[] | NodeList): string;
|
|
93
|
+
/** Pauses async execution for the specified time in ms */
|
|
94
|
+
declare function pauseFor(time: number): Promise<unknown>;
|
|
95
|
+
/**
|
|
96
|
+
* Calls the passed `func` after the specified `timeout` in ms.
|
|
97
|
+
* Any subsequent calls to this function will reset the timer and discard previous calls.
|
|
98
|
+
*/
|
|
99
|
+
declare function debounce<TFunc extends (...args: TArgs[]) => void, TArgs = any>(func: TFunc, timeout?: number): (...args: TArgs[]) => void;
|
|
100
|
+
/** Calls the fetch API with special options like a timeout */
|
|
101
|
+
declare function fetchAdvanced(url: string, options?: FetchAdvancedOpts): Promise<Response>;
|
|
102
|
+
|
|
92
103
|
/**
|
|
93
104
|
* Calls the `listener` as soon as the `selector` exists in the DOM.
|
|
94
105
|
* Listeners are deleted when they are called once, unless `options.continuous` is set.
|
|
@@ -98,12 +109,17 @@ declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate
|
|
|
98
109
|
* @template TElem The type of element that the listener will return as its argument (defaults to the generic HTMLElement)
|
|
99
110
|
*/
|
|
100
111
|
declare function onSelector<TElem extends Element = HTMLElement>(selector: string, options: OnSelectorOpts<TElem>): void;
|
|
101
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* Removes all listeners registered in `onSelector()` that have the given selector
|
|
114
|
+
* @returns Returns true when all listeners with the associated selector were found and removed, false otherwise
|
|
115
|
+
*/
|
|
102
116
|
declare function removeOnSelector(selector: string): boolean;
|
|
103
117
|
/**
|
|
104
118
|
* Initializes a MutationObserver that checks for all registered selectors whenever an element is added to or removed from the `<body>`
|
|
105
119
|
* @param opts For fine-tuning when the MutationObserver checks for the selectors
|
|
106
120
|
*/
|
|
107
121
|
declare function initOnSelector(opts?: InitOnSelectorOpts): void;
|
|
122
|
+
/** Returns all currently registered selectors, as a map of selector strings to their associated options */
|
|
123
|
+
declare function getSelectorMap(): Map<string, OnSelectorOpts[]>;
|
|
108
124
|
|
|
109
|
-
export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
|
|
125
|
+
export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, mapRange, onSelector, openInNewTab, pauseFor, preloadImages, randRange, removeOnSelector };
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var x=Object.defineProperty,y=Object.defineProperties;var T=Object.getOwnPropertyDescriptors;var d=Object.getOwnPropertySymbols;var h=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?x(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,m=(t,e)=>{for(var n in e||(e={}))h.call(e,n)&&f(t,n,e[n]);if(d)for(var n of d(e))v.call(e,n)&&f(t,n,e[n]);return t},l=(t,e)=>y(t,T(e));var b=(t,e,n)=>new Promise((r,o)=>{var i=u=>{try{a(n.next(u));}catch(p){o(p);}},s=u=>{try{a(n.throw(u));}catch(p){o(p);}},a=u=>u.done?r(u.value):Promise.resolve(u.value).then(i,s);a((n=n.apply(t,e)).next());});function O(){try{return unsafeWindow}catch(t){return window}}function L(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function M(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 S(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function N(t,e=!1){let n=t.map(r=>new Promise((o,i)=>{let s=new Image;s.src=r,s.addEventListener("load",()=>o(s)),s.addEventListener("error",a=>e&&i(a));}));return Promise.allSettled(n)}function A(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 w(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 k(t,e){return w(O(),t,e)}function P(t,e,n){return Math.max(Math.min(t,n),e)}function I(t,e,n,r,o){return Number(e)===0&&Number(r)===0?t*(o/n):(t-e)*((o-r)/(n-e))+r}function j(...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 F(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function W(t){return new Promise(e=>{setTimeout(e,t);})}function $(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function R(n){return b(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,i=setTimeout(()=>o.abort(),r),s=yield fetch(t,l(m({},e),{signal:o.signal}));return clearTimeout(i),s})}var c=new Map;function G(t,e){let n=[];c.has(t)&&(n=c.get(t)),n.push(e),c.set(t,n),E(t,n);}function U(t){return c.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?c.delete(t):c.set(t,r);}}function z(t={}){new MutationObserver(()=>{for(let[n,r]of c.entries())E(n,r);}).observe(document.body,l(m({},t),{childList:!0}));}function D(){return c}
|
|
4
4
|
|
|
5
|
-
exports.addGlobalStyle =
|
|
6
|
-
exports.addParent =
|
|
7
|
-
exports.autoPlural =
|
|
8
|
-
exports.clamp =
|
|
9
|
-
exports.debounce =
|
|
10
|
-
exports.fetchAdvanced =
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
14
|
-
exports.
|
|
15
|
-
exports.
|
|
16
|
-
exports.
|
|
17
|
-
exports.
|
|
18
|
-
exports.
|
|
19
|
-
exports.
|
|
20
|
-
exports.
|
|
5
|
+
exports.addGlobalStyle = S;
|
|
6
|
+
exports.addParent = M;
|
|
7
|
+
exports.autoPlural = F;
|
|
8
|
+
exports.clamp = P;
|
|
9
|
+
exports.debounce = $;
|
|
10
|
+
exports.fetchAdvanced = R;
|
|
11
|
+
exports.getSelectorMap = D;
|
|
12
|
+
exports.getUnsafeWindow = O;
|
|
13
|
+
exports.initOnSelector = z;
|
|
14
|
+
exports.insertAfter = L;
|
|
15
|
+
exports.interceptEvent = w;
|
|
16
|
+
exports.interceptWindowEvent = k;
|
|
17
|
+
exports.mapRange = I;
|
|
18
|
+
exports.onSelector = G;
|
|
19
|
+
exports.openInNewTab = A;
|
|
20
|
+
exports.pauseFor = W;
|
|
21
|
+
exports.preloadImages = N;
|
|
22
|
+
exports.randRange = j;
|
|
23
|
+
exports.removeOnSelector = U;
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var x=Object.defineProperty,y=Object.defineProperties;var T=Object.getOwnPropertyDescriptors;var d=Object.getOwnPropertySymbols;var h=Object.prototype.hasOwnProperty,v=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?x(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,m=(t,e)=>{for(var n in e||(e={}))h.call(e,n)&&f(t,n,e[n]);if(d)for(var n of d(e))v.call(e,n)&&f(t,n,e[n]);return t},l=(t,e)=>y(t,T(e));var b=(t,e,n)=>new Promise((r,o)=>{var i=u=>{try{a(n.next(u));}catch(p){o(p);}},s=u=>{try{a(n.throw(u));}catch(p){o(p);}},a=u=>u.done?r(u.value):Promise.resolve(u.value).then(i,s);a((n=n.apply(t,e)).next());});function O(){try{return unsafeWindow}catch(t){return window}}function L(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function M(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 S(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function N(t,e=!1){let n=t.map(r=>new Promise((o,i)=>{let s=new Image;s.src=r,s.addEventListener("load",()=>o(s)),s.addEventListener("error",a=>e&&i(a));}));return Promise.allSettled(n)}function A(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 w(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 k(t,e){return w(O(),t,e)}function P(t,e,n){return Math.max(Math.min(t,n),e)}function I(t,e,n,r,o){return Number(e)===0&&Number(r)===0?t*(o/n):(t-e)*((o-r)/(n-e))+r}function j(...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 F(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function W(t){return new Promise(e=>{setTimeout(e,t);})}function $(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function R(n){return b(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,i=setTimeout(()=>o.abort(),r),s=yield fetch(t,l(m({},e),{signal:o.signal}));return clearTimeout(i),s})}var c=new Map;function G(t,e){let n=[];c.has(t)&&(n=c.get(t)),n.push(e),c.set(t,n),E(t,n);}function U(t){return c.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?c.delete(t):c.set(t,r);}}function z(t={}){new MutationObserver(()=>{for(let[n,r]of c.entries())E(n,r);}).observe(document.body,l(m({},t),{childList:!0}));}function D(){return c}
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { S as addGlobalStyle, M as addParent, F as autoPlural, P as clamp, $ as debounce, R as fetchAdvanced, D as getSelectorMap, O as getUnsafeWindow, z as initOnSelector, L as insertAfter, w as interceptEvent, k as interceptWindowEvent, I as mapRange, G as onSelector, A as openInNewTab, W as pauseFor, N as preloadImages, j as randRange, U as removeOnSelector };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sv443-network/userutils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.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",
|