@sv443-network/userutils 0.1.4 → 0.3.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 +6 -12
- package/README.md +220 -35
- package/dist/index.d.mts +39 -11
- package/dist/index.d.ts +39 -11
- package/dist/index.js +17 -15
- package/dist/index.mjs +2 -2
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,22 +1,16 @@
|
|
|
1
1
|
# @sv443-network/userutils
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.3.0
|
|
4
4
|
|
|
5
|
-
###
|
|
6
|
-
|
|
7
|
-
- a1e8dec: please just work thanks
|
|
8
|
-
|
|
9
|
-
## 0.1.3
|
|
10
|
-
|
|
11
|
-
### Patch Changes
|
|
5
|
+
### Minor Changes
|
|
12
6
|
|
|
13
|
-
-
|
|
7
|
+
- 07ec443: add getSelectorMap() to return all currently registered selectors
|
|
14
8
|
|
|
15
|
-
## 0.
|
|
9
|
+
## 0.2.0
|
|
16
10
|
|
|
17
|
-
###
|
|
11
|
+
### Minor Changes
|
|
18
12
|
|
|
19
|
-
-
|
|
13
|
+
- 0cf2254: add onSelector() to call a listener once a selector is found in the DOM
|
|
20
14
|
|
|
21
15
|
## 0.1.1
|
|
22
16
|
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ Contains builtin TypeScript declarations.
|
|
|
8
8
|
- [Installation](#installation)
|
|
9
9
|
- [Features](#features)
|
|
10
10
|
- [onSelector()](#onselector) - call a listener once a selector is found in the DOM
|
|
11
|
+
- [initOnSelector()](#initonselector) - needs to be called once to be able to use `onSelector()`
|
|
12
|
+
- [getSelectorMap()](#getselectormap) - returns all currently registered selectors, listeners and options
|
|
11
13
|
- [autoPlural()](#autoplural) - automatically pluralize a string
|
|
12
14
|
- [clamp()](#clamp) - clamp a number between a min and max value
|
|
13
15
|
- [pauseFor()](#pausefor) - pause the execution of a function for a given amount of time
|
|
@@ -54,16 +56,129 @@ If you like using this library, please consider [supporting development](https:/
|
|
|
54
56
|
## Features:
|
|
55
57
|
|
|
56
58
|
### onSelector()
|
|
57
|
-
|
|
59
|
+
Usage:
|
|
60
|
+
```ts
|
|
61
|
+
onSelector<TElement = HTMLElement>(selector: string, options: {
|
|
62
|
+
listener: (elements: TElement | NodeListOf<TElement>) => void,
|
|
63
|
+
all?: boolean,
|
|
64
|
+
continuous?: boolean,
|
|
65
|
+
}): void
|
|
66
|
+
```
|
|
58
67
|
|
|
59
68
|
Registers a listener to be called whenever the element(s) behind a selector is/are found in the DOM.
|
|
60
|
-
|
|
69
|
+
If the selector already exists, the listener will be called immediately.
|
|
70
|
+
|
|
71
|
+
If `all` is set to `true`, querySelectorAll() will be used instead and the listener will return a NodeList of matching elements.
|
|
72
|
+
This will also include elements that were already found in a previous listener call.
|
|
73
|
+
If set to `false` (default), querySelector() will be used and only the first matching element will be returned.
|
|
74
|
+
|
|
75
|
+
If `continuous` is set to `true`, the listener will not be deregistered after it was called once (defaults to false).
|
|
76
|
+
|
|
77
|
+
When using TypeScript, the generic `TElement` can be used to specify the type of the element(s) that the listener will return.
|
|
61
78
|
|
|
62
|
-
|
|
79
|
+
⚠️ In order to use this function, [`initOnSelector()`](#initonselector) has to be called as soon as possible.
|
|
80
|
+
This initialization function has to be called after `DOMContentLoaded` is fired (or immediately if `@run-at document-end` is set).
|
|
81
|
+
|
|
82
|
+
Calling onSelector() before `DOMContentLoaded` is fired will not throw an error, but it also won't trigger listeners until the DOM is accessible.
|
|
83
|
+
|
|
84
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
85
|
+
|
|
63
86
|
```ts
|
|
64
|
-
|
|
87
|
+
document.addEventListener("DOMContentLoaded", initOnSelector);
|
|
88
|
+
|
|
89
|
+
// Continuously checks if `div` elements are added to the DOM, then returns all of them (even previously detected ones) in a NodeList
|
|
90
|
+
onSelector<HTMLDivElement>("div", {
|
|
91
|
+
listener: (elements) => {
|
|
92
|
+
console.log("Elements found:", elements); // type = NodeListOf<HTMLDivElement>
|
|
93
|
+
},
|
|
94
|
+
all: true,
|
|
95
|
+
continuous: true,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Checks if an input element with a value attribute of "5" is added to the DOM, then returns it and deregisters the listener
|
|
99
|
+
onSelector<HTMLInputElement>("input[value=\"5\"]", {
|
|
100
|
+
listener: (element) => {
|
|
101
|
+
console.log("Element found:", element); // type = HTMLInputElement
|
|
102
|
+
},
|
|
103
|
+
});
|
|
65
104
|
```
|
|
66
105
|
|
|
106
|
+
</details>
|
|
107
|
+
|
|
108
|
+
<br>
|
|
109
|
+
|
|
110
|
+
### initOnSelector()
|
|
111
|
+
Usage:
|
|
112
|
+
```ts
|
|
113
|
+
initOnSelector(options?: {
|
|
114
|
+
attributes?: boolean,
|
|
115
|
+
characterData?: boolean,
|
|
116
|
+
}): void
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Initializes the MutationObserver that is used by [`onSelector()`](#onselector) to check for the registered selectors whenever a DOM change occurs on the `<body>`
|
|
120
|
+
By default, this only checks if elements are added or removed (at any depth).
|
|
121
|
+
|
|
122
|
+
Set `attributes` to `true` to also check for attribute changes on every single descendant of the `<body>` (defaults to false).
|
|
123
|
+
Set `characterData` to `true` to also check for character data changes on every single descendant of the `<body>` (defaults to false).
|
|
124
|
+
|
|
125
|
+
⚠️ Using these extra options can have a performance impact on larger sites or sites with a constantly changing DOM.
|
|
126
|
+
|
|
127
|
+
⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
|
|
128
|
+
|
|
129
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
133
|
+
initOnSelector({
|
|
134
|
+
attributes: true,
|
|
135
|
+
characterData: true,
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
</details>
|
|
141
|
+
|
|
142
|
+
<br>
|
|
143
|
+
|
|
144
|
+
### getSelectorMap()
|
|
145
|
+
Usage: `getSelectorMap(): Map<string, OnSelectorOptions[]>`
|
|
146
|
+
|
|
147
|
+
Returns a Map of all currently registered selectors and their options, including listener function.
|
|
148
|
+
Since multiple listeners can be registered for the same selector, the value of the Map is an array of `OnSelectorOptions` objects.
|
|
149
|
+
|
|
150
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
document.addEventListener("DOMContentLoaded", initOnSelector);
|
|
154
|
+
|
|
155
|
+
onSelector<HTMLDivElement>("div", {
|
|
156
|
+
listener: (elements) => void 0,
|
|
157
|
+
all: true,
|
|
158
|
+
continuous: true,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
onSelector<HTMLDivElement>("div", {
|
|
162
|
+
listener: (elements) => void 0,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const selectorMap = getSelectorMap();
|
|
166
|
+
// Map(1) {
|
|
167
|
+
// "div" => [
|
|
168
|
+
// {
|
|
169
|
+
// listener: (elements) => void 0,
|
|
170
|
+
// all: true,
|
|
171
|
+
// continuous: true,
|
|
172
|
+
// },
|
|
173
|
+
// {
|
|
174
|
+
// listener: (elements) => void 0,
|
|
175
|
+
// },
|
|
176
|
+
// ]
|
|
177
|
+
// }
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
</details>
|
|
181
|
+
|
|
67
182
|
<br>
|
|
68
183
|
|
|
69
184
|
### autoPlural()
|
|
@@ -72,7 +187,8 @@ Usage: `autoPlural(str: string, num: number | Array | NodeList): string`
|
|
|
72
187
|
Automatically pluralizes a string if the given number is not 1.
|
|
73
188
|
If an array or NodeList is passed, the length of it will be used.
|
|
74
189
|
|
|
75
|
-
Example
|
|
190
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
191
|
+
|
|
76
192
|
```ts
|
|
77
193
|
autoPlural("apple", 0); // "apples"
|
|
78
194
|
autoPlural("apple", 1); // "apple"
|
|
@@ -80,8 +196,13 @@ autoPlural("apple", 2); // "apples"
|
|
|
80
196
|
|
|
81
197
|
autoPlural("apple", [1]); // "apple"
|
|
82
198
|
autoPlural("apple", [1, 2]); // "apples"
|
|
199
|
+
|
|
200
|
+
const items = [1, 2, 3, 4, "foo", "bar"];
|
|
201
|
+
console.log(`Found ${items.length} ${autoPlural("item", items)}`); // "Found 6 items"
|
|
83
202
|
```
|
|
84
203
|
|
|
204
|
+
</details>
|
|
205
|
+
|
|
85
206
|
<br>
|
|
86
207
|
|
|
87
208
|
### clamp()
|
|
@@ -89,13 +210,17 @@ Usage: `clamp(num: number, min: number, max: number): number`
|
|
|
89
210
|
|
|
90
211
|
Clamps a number between a min and max value.
|
|
91
212
|
|
|
92
|
-
Example
|
|
213
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
214
|
+
|
|
93
215
|
```ts
|
|
94
216
|
clamp(5, 0, 10); // 5
|
|
95
217
|
clamp(-1, 0, 10); // 0
|
|
218
|
+
clamp(7, 0, 10); // 7
|
|
96
219
|
clamp(Infinity, 0, 10); // 10
|
|
97
220
|
```
|
|
98
221
|
|
|
222
|
+
</details>
|
|
223
|
+
|
|
99
224
|
<br>
|
|
100
225
|
|
|
101
226
|
### pauseFor()
|
|
@@ -103,7 +228,8 @@ Usage: `pauseFor(ms: number): Promise<void>`
|
|
|
103
228
|
|
|
104
229
|
Pauses async execution for a given amount of time.
|
|
105
230
|
|
|
106
|
-
Example
|
|
231
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
232
|
+
|
|
107
233
|
```ts
|
|
108
234
|
async function run() {
|
|
109
235
|
console.log("Hello");
|
|
@@ -112,6 +238,8 @@ async function run() {
|
|
|
112
238
|
}
|
|
113
239
|
```
|
|
114
240
|
|
|
241
|
+
</details>
|
|
242
|
+
|
|
115
243
|
<br>
|
|
116
244
|
|
|
117
245
|
### debounce()
|
|
@@ -121,13 +249,16 @@ Debounces a function, meaning that it will only be called once after a given amo
|
|
|
121
249
|
This is very useful for functions that are called repeatedly, like event listeners, to remove extraneous calls.
|
|
122
250
|
The timeout will default to 300ms if left undefined.
|
|
123
251
|
|
|
124
|
-
Example
|
|
252
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
253
|
+
|
|
125
254
|
```ts
|
|
126
255
|
window.addEventListener("resize", debounce((event) => {
|
|
127
256
|
console.log("Window was resized:", event);
|
|
128
257
|
}, 500)); // 500ms timeout
|
|
129
258
|
```
|
|
130
259
|
|
|
260
|
+
</details>
|
|
261
|
+
|
|
131
262
|
<br>
|
|
132
263
|
|
|
133
264
|
### getUnsafeWindow()
|
|
@@ -136,55 +267,76 @@ Usage: `getUnsafeWindow(): Window`
|
|
|
136
267
|
Returns the unsafeWindow object or falls back to the regular window object if the `@grant unsafeWindow` is not given.
|
|
137
268
|
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.
|
|
138
269
|
|
|
139
|
-
Example
|
|
270
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
271
|
+
|
|
140
272
|
```ts
|
|
141
|
-
|
|
273
|
+
// trick the site into thinking the mouse was moved:
|
|
274
|
+
const mouseEvent = new MouseEvent("mousemove", {
|
|
142
275
|
view: getUnsafeWindow(),
|
|
276
|
+
screenY: 69,
|
|
277
|
+
screenX: 420,
|
|
278
|
+
movementX: 10,
|
|
279
|
+
movementY: 0,
|
|
143
280
|
});
|
|
144
281
|
document.body.dispatchEvent(mouseEvent);
|
|
145
282
|
```
|
|
146
283
|
|
|
284
|
+
</details>
|
|
285
|
+
|
|
147
286
|
<br>
|
|
148
287
|
|
|
149
288
|
### insertAfter()
|
|
150
289
|
Usage: `insertAfter(beforeElement: HTMLElement, afterElement: HTMLElement): HTMLElement`
|
|
151
290
|
|
|
152
291
|
Inserts the element passed as `afterElement` as a sibling after the passed `beforeElement`.
|
|
153
|
-
The `afterElement` will be returned.
|
|
292
|
+
The passed `afterElement` will be returned.
|
|
293
|
+
|
|
294
|
+
⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
|
|
154
295
|
|
|
155
|
-
Example
|
|
296
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
297
|
+
|
|
156
298
|
```ts
|
|
299
|
+
// insert a <div> as a sibling next to an element
|
|
157
300
|
const beforeElement = document.querySelector("#before");
|
|
158
301
|
const afterElement = document.createElement("div");
|
|
159
302
|
afterElement.innerText = "After";
|
|
160
303
|
insertAfter(beforeElement, afterElement);
|
|
161
304
|
```
|
|
162
305
|
|
|
306
|
+
</details>
|
|
307
|
+
|
|
163
308
|
<br>
|
|
164
309
|
|
|
165
310
|
### addParent()
|
|
166
311
|
Usage: `addParent(element: HTMLElement, newParent: HTMLElement): HTMLElement`
|
|
167
312
|
|
|
168
313
|
Adds a parent element around the passed `element` and returns the new parent.
|
|
169
|
-
Previously registered event listeners
|
|
314
|
+
Previously registered event listeners are kept intact.
|
|
170
315
|
|
|
171
|
-
|
|
316
|
+
⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
|
|
317
|
+
|
|
318
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
319
|
+
|
|
172
320
|
```ts
|
|
321
|
+
// add an <a> around an element
|
|
173
322
|
const element = document.querySelector("#element");
|
|
174
323
|
const newParent = document.createElement("a");
|
|
175
324
|
newParent.href = "https://example.org/";
|
|
176
325
|
addParent(element, newParent);
|
|
177
326
|
```
|
|
178
327
|
|
|
328
|
+
</details>
|
|
329
|
+
|
|
179
330
|
<br>
|
|
180
331
|
|
|
181
332
|
### addGlobalStyle()
|
|
182
333
|
Usage: `addGlobalStyle(css: string): void`
|
|
183
334
|
|
|
184
335
|
Adds a global style to the page in form of a `<style>` element that's inserted into the `<head>`.
|
|
185
|
-
This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
|
|
336
|
+
⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
|
|
186
337
|
|
|
187
|
-
Example
|
|
338
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
339
|
+
|
|
188
340
|
```ts
|
|
189
341
|
document.addEventListener("DOMContentLoaded", () => {
|
|
190
342
|
addGlobalStyle(`
|
|
@@ -195,43 +347,62 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
195
347
|
});
|
|
196
348
|
```
|
|
197
349
|
|
|
350
|
+
</details>
|
|
351
|
+
|
|
198
352
|
<br>
|
|
199
353
|
|
|
200
354
|
### preloadImages()
|
|
201
|
-
Usage: `preloadImages(
|
|
355
|
+
Usage: `preloadImages(urls: string[], rejects?: boolean): Promise<void>`
|
|
202
356
|
|
|
203
357
|
Preloads images into browser cache by creating an invisible `<img>` element for each URL passed.
|
|
204
358
|
The images will be loaded in parallel and the returned Promise will only resolve once all images have been loaded.
|
|
205
|
-
The resulting PromiseSettledResult array will contain the image elements if resolved, or an ErrorEvent if rejected.
|
|
359
|
+
The resulting PromiseSettledResult array will contain the image elements if resolved, or an ErrorEvent if rejected, but only if `rejects` is set to true.
|
|
206
360
|
|
|
207
|
-
Example
|
|
361
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
362
|
+
|
|
208
363
|
```ts
|
|
209
|
-
preloadImages(
|
|
364
|
+
preloadImages([
|
|
210
365
|
"https://example.org/image1.png",
|
|
211
366
|
"https://example.org/image2.png",
|
|
212
367
|
"https://example.org/image3.png",
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
|
|
368
|
+
], true)
|
|
369
|
+
.then((results) => {
|
|
370
|
+
console.log("Images preloaded. Results:", results);
|
|
371
|
+
});
|
|
216
372
|
```
|
|
217
373
|
|
|
374
|
+
</details>
|
|
375
|
+
|
|
218
376
|
<br>
|
|
219
377
|
|
|
220
378
|
### fetchAdvanced()
|
|
221
|
-
Usage:
|
|
379
|
+
Usage:
|
|
380
|
+
```ts
|
|
381
|
+
fetchAdvanced(url: string, options?: {
|
|
382
|
+
timeout?: number,
|
|
383
|
+
// any other options from fetch() except for signal
|
|
384
|
+
}): Promise<Response>
|
|
385
|
+
```
|
|
222
386
|
|
|
223
387
|
A wrapper around the native `fetch()` function that adds options like a timeout property.
|
|
224
388
|
The timeout will default to 10 seconds if left undefined.
|
|
225
389
|
|
|
226
|
-
Example
|
|
390
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
391
|
+
|
|
227
392
|
```ts
|
|
228
|
-
fetchAdvanced("https://example.org/", {
|
|
393
|
+
fetchAdvanced("https://api.example.org/data", {
|
|
229
394
|
timeout: 5000,
|
|
230
|
-
|
|
231
|
-
|
|
395
|
+
// also accepts any other fetch options like headers:
|
|
396
|
+
headers: {
|
|
397
|
+
"Accept": "application/json",
|
|
398
|
+
},
|
|
399
|
+
}).then(async (response) => {
|
|
400
|
+
console.log("Data:", await response.json());
|
|
232
401
|
});
|
|
233
402
|
```
|
|
234
403
|
|
|
404
|
+
</details>
|
|
405
|
+
|
|
235
406
|
<br>
|
|
236
407
|
|
|
237
408
|
### openInNewTab()
|
|
@@ -241,29 +412,38 @@ Creates an invisible anchor with a `_blank` target and clicks it.
|
|
|
241
412
|
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.
|
|
242
413
|
This function has to be run in relatively quick succession in response to a user interaction event, else the browser might reject it.
|
|
243
414
|
|
|
244
|
-
|
|
415
|
+
⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).
|
|
416
|
+
|
|
417
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
418
|
+
|
|
245
419
|
```ts
|
|
246
|
-
document.querySelector("#button").addEventListener("click", () => {
|
|
420
|
+
document.querySelector("#my-button").addEventListener("click", () => {
|
|
247
421
|
openInNewTab("https://example.org/");
|
|
248
422
|
});
|
|
249
423
|
```
|
|
250
424
|
|
|
425
|
+
</details>
|
|
426
|
+
|
|
251
427
|
<br>
|
|
252
428
|
|
|
253
429
|
### interceptEvent()
|
|
254
430
|
Usage: `interceptEvent(eventObject: EventTarget, eventName: string, predicate: () => boolean): void`
|
|
255
431
|
|
|
256
432
|
Intercepts all events dispatched on the `eventObject` and prevents the listeners from being called as long as the predicate function returns a truthy value.
|
|
257
|
-
|
|
258
|
-
Calling this function will set the `Error.stackTraceLimit` to 1000 to ensure the stack trace is preserved.
|
|
433
|
+
Calling this function will set the `Error.stackTraceLimit` to 1000 (if it's not already higher) to ensure the stack trace is preserved.
|
|
259
434
|
|
|
260
|
-
|
|
435
|
+
⚠️ 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.
|
|
436
|
+
|
|
437
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
438
|
+
|
|
261
439
|
```ts
|
|
262
440
|
interceptEvent(document.body, "click", () => {
|
|
263
|
-
return true; // prevent all click events on the body
|
|
441
|
+
return true; // prevent all click events on the body element
|
|
264
442
|
});
|
|
265
443
|
```
|
|
266
444
|
|
|
445
|
+
</details>
|
|
446
|
+
|
|
267
447
|
<br>
|
|
268
448
|
|
|
269
449
|
### interceptWindowEvent()
|
|
@@ -272,13 +452,18 @@ Usage: `interceptWindowEvent(eventName: string, predicate: () => boolean): void`
|
|
|
272
452
|
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.
|
|
273
453
|
This is essentially the same as [`interceptEvent()`](#interceptevent), but automatically uses the `unsafeWindow` (or falls back to regular `window`).
|
|
274
454
|
|
|
275
|
-
|
|
455
|
+
⚠️ 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.
|
|
456
|
+
|
|
457
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
458
|
+
|
|
276
459
|
```ts
|
|
277
460
|
interceptWindowEvent("beforeunload", () => {
|
|
278
461
|
return true; // prevent the pesky "Are you sure you want to leave this page?" popup
|
|
279
462
|
});
|
|
280
463
|
```
|
|
281
464
|
|
|
465
|
+
</details>
|
|
466
|
+
|
|
282
467
|
|
|
283
468
|
<br><br>
|
|
284
469
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
type
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
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 */
|
|
7
22
|
continuous?: boolean;
|
|
8
23
|
};
|
|
9
24
|
type FetchAdvancedOpts = RequestInit & Partial<{
|
|
25
|
+
/** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
|
|
10
26
|
timeout: number;
|
|
11
27
|
}>;
|
|
12
28
|
|
|
@@ -77,10 +93,22 @@ declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate
|
|
|
77
93
|
* Calls the `listener` as soon as the `selector` exists in the DOM.
|
|
78
94
|
* Listeners are deleted when they are called once, unless `options.continuous` is set.
|
|
79
95
|
* Multiple listeners with the same selector may be registered.
|
|
80
|
-
* @
|
|
96
|
+
* @param selector The selector to listen for
|
|
97
|
+
* @param options Used for switching to `querySelectorAll()` and for calling the listener continuously
|
|
98
|
+
* @template TElem The type of element that the listener will return as its argument (defaults to the generic HTMLElement)
|
|
99
|
+
*/
|
|
100
|
+
declare function onSelector<TElem extends Element = HTMLElement>(selector: string, options: OnSelectorOpts<TElem>): void;
|
|
101
|
+
/**
|
|
102
|
+
* Removes all listeners registered in `onSelector()` that have the given selector
|
|
103
|
+
* @returns Returns true when all listeners with the associated selector were found and removed, false otherwise
|
|
104
|
+
*/
|
|
105
|
+
declare function removeOnSelector(selector: string): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Initializes a MutationObserver that checks for all registered selectors whenever an element is added to or removed from the `<body>`
|
|
108
|
+
* @param opts For fine-tuning when the MutationObserver checks for the selectors
|
|
81
109
|
*/
|
|
82
|
-
declare function
|
|
83
|
-
/**
|
|
84
|
-
declare function
|
|
110
|
+
declare function initOnSelector(opts?: InitOnSelectorOpts): void;
|
|
111
|
+
/** Returns all currently registered selectors, as a map of selector strings to their associated options */
|
|
112
|
+
declare function getSelectorMap(): Map<string, OnSelectorOpts[]>;
|
|
85
113
|
|
|
86
|
-
export { FetchAdvancedOpts,
|
|
114
|
+
export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
type
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
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 */
|
|
7
22
|
continuous?: boolean;
|
|
8
23
|
};
|
|
9
24
|
type FetchAdvancedOpts = RequestInit & Partial<{
|
|
25
|
+
/** Timeout in milliseconds after which the fetch call will be canceled with an AbortController signal */
|
|
10
26
|
timeout: number;
|
|
11
27
|
}>;
|
|
12
28
|
|
|
@@ -77,10 +93,22 @@ declare function interceptWindowEvent(eventName: keyof WindowEventMap, predicate
|
|
|
77
93
|
* Calls the `listener` as soon as the `selector` exists in the DOM.
|
|
78
94
|
* Listeners are deleted when they are called once, unless `options.continuous` is set.
|
|
79
95
|
* Multiple listeners with the same selector may be registered.
|
|
80
|
-
* @
|
|
96
|
+
* @param selector The selector to listen for
|
|
97
|
+
* @param options Used for switching to `querySelectorAll()` and for calling the listener continuously
|
|
98
|
+
* @template TElem The type of element that the listener will return as its argument (defaults to the generic HTMLElement)
|
|
99
|
+
*/
|
|
100
|
+
declare function onSelector<TElem extends Element = HTMLElement>(selector: string, options: OnSelectorOpts<TElem>): void;
|
|
101
|
+
/**
|
|
102
|
+
* Removes all listeners registered in `onSelector()` that have the given selector
|
|
103
|
+
* @returns Returns true when all listeners with the associated selector were found and removed, false otherwise
|
|
104
|
+
*/
|
|
105
|
+
declare function removeOnSelector(selector: string): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Initializes a MutationObserver that checks for all registered selectors whenever an element is added to or removed from the `<body>`
|
|
108
|
+
* @param opts For fine-tuning when the MutationObserver checks for the selectors
|
|
81
109
|
*/
|
|
82
|
-
declare function
|
|
83
|
-
/**
|
|
84
|
-
declare function
|
|
110
|
+
declare function initOnSelector(opts?: InitOnSelectorOpts): void;
|
|
111
|
+
/** Returns all currently registered selectors, as a map of selector strings to their associated options */
|
|
112
|
+
declare function getSelectorMap(): Map<string, OnSelectorOpts[]>;
|
|
85
113
|
|
|
86
|
-
export { FetchAdvancedOpts,
|
|
114
|
+
export { FetchAdvancedOpts, InitOnSelectorOpts, OnSelectorOpts, addGlobalStyle, addParent, autoPlural, clamp, debounce, fetchAdvanced, getSelectorMap, getUnsafeWindow, initOnSelector, insertAfter, interceptEvent, interceptWindowEvent, onSelector, openInNewTab, pauseFor, preloadImages, removeOnSelector };
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var b=Object.defineProperty,y=Object.defineProperties;var g=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?b(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,u=(t,e)=>{for(var n in e||(e={}))v.call(e,n)&&f(t,n,e[n]);if(m)for(var n of m(e))x.call(e,n)&&f(t,n,e[n]);return t},d=(t,e)=>y(t,g(e));var E=(t,e,n)=>new Promise((r,o)=>{var s=a=>{try{l(n.next(a));}catch(p){o(p);}},i=a=>{try{l(n.throw(a));}catch(p){o(p);}},l=a=>a.done?r(a.value):Promise.resolve(a.value).then(s,i);l((n=n.apply(t,e)).next());});function w(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function M(t,e,n){return Math.max(Math.min(t,n),e)}function S(t){return new Promise(e=>{setTimeout(e,t);})}function A(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function h(){try{return unsafeWindow}catch(t){return window}}function _(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function k(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 H(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function I(t,e=!1){let n=t.map(r=>new Promise((o,s)=>{let i=new Image;i.src=r,i.addEventListener("load",()=>o(i)),i.addEventListener("error",l=>e&&s(l));}));return Promise.allSettled(n)}function j(n){return E(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,s=setTimeout(()=>o.abort(),r),i=yield fetch(t,d(u({},e),{signal:o.signal}));return clearTimeout(s),i})}function C(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 O(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 N(t,e){return O(h(),t,e)}var c=new Map;function W(t,e){let n=[];c.has(t)&&(n=c.get(t)),n.push(e),c.set(t,n),T(t,n);}function $(t){return c.delete(t)}function T(t,e){let n=[];if(e.forEach((r,o)=>{try{let s=r.all?document.querySelectorAll(t):document.querySelector(t);s&&(r.listener(s),r.continuous||n.push(o));}catch(s){console.error(`Couldn't call listener for selector '${t}'`,s);}}),n.length>0){let r=e.filter((o,s)=>!n.includes(s));r.length===0?c.delete(t):c.set(t,r);}}function q(t={}){new MutationObserver(()=>{for(let[n,r]of c.entries())T(n,r);}).observe(document.body,d(u({},t),{childList:!0}));}function B(){return c}
|
|
4
4
|
|
|
5
|
-
exports.addGlobalStyle =
|
|
6
|
-
exports.addParent =
|
|
7
|
-
exports.autoPlural =
|
|
8
|
-
exports.clamp =
|
|
5
|
+
exports.addGlobalStyle = H;
|
|
6
|
+
exports.addParent = k;
|
|
7
|
+
exports.autoPlural = w;
|
|
8
|
+
exports.clamp = M;
|
|
9
9
|
exports.debounce = A;
|
|
10
|
-
exports.fetchAdvanced =
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
14
|
-
exports.
|
|
15
|
-
exports.
|
|
16
|
-
exports.
|
|
17
|
-
exports.
|
|
18
|
-
exports.
|
|
19
|
-
exports.
|
|
10
|
+
exports.fetchAdvanced = j;
|
|
11
|
+
exports.getSelectorMap = B;
|
|
12
|
+
exports.getUnsafeWindow = h;
|
|
13
|
+
exports.initOnSelector = q;
|
|
14
|
+
exports.insertAfter = _;
|
|
15
|
+
exports.interceptEvent = O;
|
|
16
|
+
exports.interceptWindowEvent = N;
|
|
17
|
+
exports.onSelector = W;
|
|
18
|
+
exports.openInNewTab = C;
|
|
19
|
+
exports.pauseFor = S;
|
|
20
|
+
exports.preloadImages = I;
|
|
21
|
+
exports.removeOnSelector = $;
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var b=Object.defineProperty,y=Object.defineProperties;var g=Object.getOwnPropertyDescriptors;var m=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var f=(t,e,n)=>e in t?b(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,u=(t,e)=>{for(var n in e||(e={}))v.call(e,n)&&f(t,n,e[n]);if(m)for(var n of m(e))x.call(e,n)&&f(t,n,e[n]);return t},d=(t,e)=>y(t,g(e));var E=(t,e,n)=>new Promise((r,o)=>{var s=a=>{try{l(n.next(a));}catch(p){o(p);}},i=a=>{try{l(n.throw(a));}catch(p){o(p);}},l=a=>a.done?r(a.value):Promise.resolve(a.value).then(s,i);l((n=n.apply(t,e)).next());});function w(t,e){return (Array.isArray(e)||e instanceof NodeList)&&(e=e.length),`${t}${e===1?"":"s"}`}function M(t,e,n){return Math.max(Math.min(t,n),e)}function S(t){return new Promise(e=>{setTimeout(e,t);})}function A(t,e=300){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>t.apply(this,r),e);}}function h(){try{return unsafeWindow}catch(t){return window}}function _(t,e){var n;return (n=t.parentNode)==null||n.insertBefore(e,t.nextSibling),e}function k(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 H(t){let e=document.createElement("style");e.innerHTML=t,document.head.appendChild(e);}function I(t,e=!1){let n=t.map(r=>new Promise((o,s)=>{let i=new Image;i.src=r,i.addEventListener("load",()=>o(i)),i.addEventListener("error",l=>e&&s(l));}));return Promise.allSettled(n)}function j(n){return E(this,arguments,function*(t,e={}){let{timeout:r=1e4}=e,o=new AbortController,s=setTimeout(()=>o.abort(),r),i=yield fetch(t,d(u({},e),{signal:o.signal}));return clearTimeout(s),i})}function C(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 O(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 N(t,e){return O(h(),t,e)}var c=new Map;function W(t,e){let n=[];c.has(t)&&(n=c.get(t)),n.push(e),c.set(t,n),T(t,n);}function $(t){return c.delete(t)}function T(t,e){let n=[];if(e.forEach((r,o)=>{try{let s=r.all?document.querySelectorAll(t):document.querySelector(t);s&&(r.listener(s),r.continuous||n.push(o));}catch(s){console.error(`Couldn't call listener for selector '${t}'`,s);}}),n.length>0){let r=e.filter((o,s)=>!n.includes(s));r.length===0?c.delete(t):c.set(t,r);}}function q(t={}){new MutationObserver(()=>{for(let[n,r]of c.entries())T(n,r);}).observe(document.body,d(u({},t),{childList:!0}));}function B(){return c}
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { H as addGlobalStyle, k as addParent, w as autoPlural, M as clamp, A as debounce, j as fetchAdvanced, B as getSelectorMap, h as getUnsafeWindow, q as initOnSelector, _ as insertAfter, O as interceptEvent, N as interceptWindowEvent, W as onSelector, C as openInNewTab, S as pauseFor, I as preloadImages, $ as removeOnSelector };
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sv443-network/userutils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"lint": "tsc && eslint .",
|
|
10
|
-
"
|
|
11
|
-
"build": "npm run
|
|
12
|
-
"
|
|
10
|
+
"build-common": "tsup lib/index.ts --format cjs,esm --dts --clean --treeshake",
|
|
11
|
+
"build": "npm run build-common -- --minify",
|
|
12
|
+
"dev": "npm run build-common -- --sourcemap --watch",
|
|
13
13
|
"publish-package": "npm run build && changeset publish"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|