@sv443-network/userutils 4.0.0 → 4.1.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 -0
- package/README.md +54 -0
- package/dist/index.global.js +24 -1
- package/dist/index.js +23 -0
- package/dist/index.mjs +23 -1
- package/dist/lib/dom.d.ts +10 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ View the documentation of previous major releases: [3.0.0](https://github.com/Sv
|
|
|
33
33
|
- [interceptEvent()](#interceptevent) - conditionally intercepts events registered by `addEventListener()` on any given EventTarget object
|
|
34
34
|
- [interceptWindowEvent()](#interceptwindowevent) - conditionally intercepts events registered by `addEventListener()` on the window object
|
|
35
35
|
- [isScrollable()](#isscrollable) - check if an element has a horizontal or vertical scroll bar
|
|
36
|
+
- [observeElementProp()](#observeelementprop) - observe changes to an element's property that can't be observed with MutationObserver
|
|
36
37
|
- [**Math:**](#math)
|
|
37
38
|
- [clamp()](#clamp) - constrain a number between a min and max value
|
|
38
39
|
- [mapRange()](#maprange) - map a number from one range to the same spot in another range
|
|
@@ -675,6 +676,59 @@ console.log("Element has a vertical scroll bar:", vertical);
|
|
|
675
676
|
|
|
676
677
|
</details>
|
|
677
678
|
|
|
679
|
+
<br>
|
|
680
|
+
|
|
681
|
+
### observeElementProp()
|
|
682
|
+
Usage:
|
|
683
|
+
```ts
|
|
684
|
+
observeElementProp(
|
|
685
|
+
element: Element,
|
|
686
|
+
property: string,
|
|
687
|
+
callback: (oldValue: any, newValue: any) => void
|
|
688
|
+
): void
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
This function observes changes to the given property of a given element.
|
|
692
|
+
While regular HTML attributes can be observed using a MutationObserver, this is not always possible for properties that are assigned on the JS object.
|
|
693
|
+
This function shims the setter of the provided property and calls the callback function whenever it is changed through any means.
|
|
694
|
+
|
|
695
|
+
When using TypeScript, the types for `element`, `property` and the arguments for `callback` will be automatically inferred.
|
|
696
|
+
|
|
697
|
+
<details><summary><b>Example - click to view</b></summary>
|
|
698
|
+
|
|
699
|
+
```ts
|
|
700
|
+
import { observeElementProp } from "@sv443-network/userutils";
|
|
701
|
+
|
|
702
|
+
const myInput = document.querySelector("input#my-input");
|
|
703
|
+
|
|
704
|
+
let value = 0;
|
|
705
|
+
|
|
706
|
+
setInterval(() => {
|
|
707
|
+
value += 1;
|
|
708
|
+
myInput.value = String(value);
|
|
709
|
+
}, 1000);
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
const observer = new MutationObserver((mutations) => {
|
|
713
|
+
// will never be called:
|
|
714
|
+
console.log("MutationObserver mutation:", mutations);
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
// one would think this should work, but "value" is a JS object *property*, not a DOM *attribute*
|
|
718
|
+
observer.observe(myInput, {
|
|
719
|
+
attributes: true,
|
|
720
|
+
attributeFilter: ["value"],
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
observeElementProp(myInput, "value", (oldValue, newValue) => {
|
|
725
|
+
// will be called every time the value changes:
|
|
726
|
+
console.log("Value changed from", oldValue, "to", newValue);
|
|
727
|
+
});
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
</details>
|
|
731
|
+
|
|
678
732
|
<br><br>
|
|
679
733
|
|
|
680
734
|
<!-- #SECTION Math -->
|
package/dist/index.global.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// ==UserLibrary==
|
|
10
10
|
// @name UserUtils
|
|
11
11
|
// @description Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, manage persistent user configurations, modify the DOM more easily and more
|
|
12
|
-
// @version 4.
|
|
12
|
+
// @version 4.1.0
|
|
13
13
|
// @license MIT
|
|
14
14
|
// @copyright Sv443 (https://github.com/Sv443)
|
|
15
15
|
|
|
@@ -333,6 +333,28 @@ var UserUtils = (function (exports) {
|
|
|
333
333
|
horizontal: (overflowX === "scroll" || overflowX === "auto") && element.scrollWidth > element.clientWidth
|
|
334
334
|
};
|
|
335
335
|
}
|
|
336
|
+
function observeElementProp(element, property, callback) {
|
|
337
|
+
const elementPrototype = Object.getPrototypeOf(element);
|
|
338
|
+
if (elementPrototype.hasOwnProperty(property)) {
|
|
339
|
+
const descriptor = Object.getOwnPropertyDescriptor(elementPrototype, property);
|
|
340
|
+
Object.defineProperty(element, property, {
|
|
341
|
+
get: function() {
|
|
342
|
+
var _a;
|
|
343
|
+
return (_a = descriptor == null ? void 0 : descriptor.get) == null ? void 0 : _a.apply(this, arguments);
|
|
344
|
+
},
|
|
345
|
+
set: function() {
|
|
346
|
+
var _a;
|
|
347
|
+
const oldValue = this[property];
|
|
348
|
+
(_a = descriptor == null ? void 0 : descriptor.set) == null ? void 0 : _a.apply(this, arguments);
|
|
349
|
+
const newValue = this[property];
|
|
350
|
+
if (typeof callback === "function") {
|
|
351
|
+
callback.bind(this, oldValue, newValue);
|
|
352
|
+
}
|
|
353
|
+
return newValue;
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
336
358
|
|
|
337
359
|
// lib/misc.ts
|
|
338
360
|
function autoPlural(word, num) {
|
|
@@ -585,6 +607,7 @@ var UserUtils = (function (exports) {
|
|
|
585
607
|
exports.interceptWindowEvent = interceptWindowEvent;
|
|
586
608
|
exports.isScrollable = isScrollable;
|
|
587
609
|
exports.mapRange = mapRange;
|
|
610
|
+
exports.observeElementProp = observeElementProp;
|
|
588
611
|
exports.openInNewTab = openInNewTab;
|
|
589
612
|
exports.pauseFor = pauseFor;
|
|
590
613
|
exports.preloadImages = preloadImages;
|
package/dist/index.js
CHANGED
|
@@ -312,6 +312,28 @@ function isScrollable(element) {
|
|
|
312
312
|
horizontal: (overflowX === "scroll" || overflowX === "auto") && element.scrollWidth > element.clientWidth
|
|
313
313
|
};
|
|
314
314
|
}
|
|
315
|
+
function observeElementProp(element, property, callback) {
|
|
316
|
+
const elementPrototype = Object.getPrototypeOf(element);
|
|
317
|
+
if (elementPrototype.hasOwnProperty(property)) {
|
|
318
|
+
const descriptor = Object.getOwnPropertyDescriptor(elementPrototype, property);
|
|
319
|
+
Object.defineProperty(element, property, {
|
|
320
|
+
get: function() {
|
|
321
|
+
var _a;
|
|
322
|
+
return (_a = descriptor == null ? void 0 : descriptor.get) == null ? void 0 : _a.apply(this, arguments);
|
|
323
|
+
},
|
|
324
|
+
set: function() {
|
|
325
|
+
var _a;
|
|
326
|
+
const oldValue = this[property];
|
|
327
|
+
(_a = descriptor == null ? void 0 : descriptor.set) == null ? void 0 : _a.apply(this, arguments);
|
|
328
|
+
const newValue = this[property];
|
|
329
|
+
if (typeof callback === "function") {
|
|
330
|
+
callback.bind(this, oldValue, newValue);
|
|
331
|
+
}
|
|
332
|
+
return newValue;
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
315
337
|
|
|
316
338
|
// lib/misc.ts
|
|
317
339
|
function autoPlural(word, num) {
|
|
@@ -564,6 +586,7 @@ exports.interceptEvent = interceptEvent;
|
|
|
564
586
|
exports.interceptWindowEvent = interceptWindowEvent;
|
|
565
587
|
exports.isScrollable = isScrollable;
|
|
566
588
|
exports.mapRange = mapRange;
|
|
589
|
+
exports.observeElementProp = observeElementProp;
|
|
567
590
|
exports.openInNewTab = openInNewTab;
|
|
568
591
|
exports.pauseFor = pauseFor;
|
|
569
592
|
exports.preloadImages = preloadImages;
|
package/dist/index.mjs
CHANGED
|
@@ -310,6 +310,28 @@ function isScrollable(element) {
|
|
|
310
310
|
horizontal: (overflowX === "scroll" || overflowX === "auto") && element.scrollWidth > element.clientWidth
|
|
311
311
|
};
|
|
312
312
|
}
|
|
313
|
+
function observeElementProp(element, property, callback) {
|
|
314
|
+
const elementPrototype = Object.getPrototypeOf(element);
|
|
315
|
+
if (elementPrototype.hasOwnProperty(property)) {
|
|
316
|
+
const descriptor = Object.getOwnPropertyDescriptor(elementPrototype, property);
|
|
317
|
+
Object.defineProperty(element, property, {
|
|
318
|
+
get: function() {
|
|
319
|
+
var _a;
|
|
320
|
+
return (_a = descriptor == null ? void 0 : descriptor.get) == null ? void 0 : _a.apply(this, arguments);
|
|
321
|
+
},
|
|
322
|
+
set: function() {
|
|
323
|
+
var _a;
|
|
324
|
+
const oldValue = this[property];
|
|
325
|
+
(_a = descriptor == null ? void 0 : descriptor.set) == null ? void 0 : _a.apply(this, arguments);
|
|
326
|
+
const newValue = this[property];
|
|
327
|
+
if (typeof callback === "function") {
|
|
328
|
+
callback.bind(this, oldValue, newValue);
|
|
329
|
+
}
|
|
330
|
+
return newValue;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
313
335
|
|
|
314
336
|
// lib/misc.ts
|
|
315
337
|
function autoPlural(word, num) {
|
|
@@ -545,4 +567,4 @@ tr.getLanguage = () => {
|
|
|
545
567
|
return curLang;
|
|
546
568
|
};
|
|
547
569
|
|
|
548
|
-
export { ConfigManager, SelectorObserver, addGlobalStyle, addParent, autoPlural, clamp, compress, debounce, decompress, fetchAdvanced, getUnsafeWindow, insertAfter, insertValues, interceptEvent, interceptWindowEvent, isScrollable, mapRange, openInNewTab, pauseFor, preloadImages, randRange, randomId, randomItem, randomItemIndex, randomizeArray, takeRandomItem, tr };
|
|
570
|
+
export { ConfigManager, SelectorObserver, addGlobalStyle, addParent, autoPlural, clamp, compress, debounce, decompress, fetchAdvanced, getUnsafeWindow, insertAfter, insertValues, interceptEvent, interceptWindowEvent, isScrollable, mapRange, observeElementProp, openInNewTab, pauseFor, preloadImages, randRange, randomId, randomItem, randomItemIndex, randomizeArray, takeRandomItem, tr };
|
package/dist/lib/dom.d.ts
CHANGED
|
@@ -50,3 +50,13 @@ export declare function isScrollable(element: Element): {
|
|
|
50
50
|
vertical: boolean;
|
|
51
51
|
horizontal: boolean;
|
|
52
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Executes the callback when the passed element's property changes.
|
|
55
|
+
* Contrary to an element's attributes, properties can usually not be observed with a MutationObserver.
|
|
56
|
+
* This function shims the getter and setter of the property to invoke the callback.
|
|
57
|
+
*
|
|
58
|
+
* [Source](https://stackoverflow.com/a/61975440)
|
|
59
|
+
* @param property The name of the property to observe
|
|
60
|
+
* @param callback Callback to execute when the value is changed
|
|
61
|
+
*/
|
|
62
|
+
export declare function observeElementProp<TElem extends Element = HTMLElement, TPropKey extends keyof TElem = keyof TElem>(element: TElem, property: TPropKey, callback: (oldVal: TElem[TPropKey], newVal: TElem[TPropKey]) => void): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sv443-network/userutils",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Library with various utilities for userscripts - register listeners for when CSS selectors exist, intercept events, manage persistent user configurations, modify the DOM more easily and more",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|