powerpagestoolkit 2.6.3 → 2.6.3201

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/README.md CHANGED
@@ -27,31 +27,88 @@ A powerful class for managing DOM elements with automatic value synchronization
27
27
 
28
28
  #### Basic Usage
29
29
 
30
- DOMNodeReferences are instantiated with the help of the following factory function
30
+ DOMNodeReferences are instantiated with the help of the following factory function: `createRef`
31
31
 
32
32
  ```typescript
33
33
  createRef(
34
- target: HTMLElement | string, /* You can target an HTMLElement directly,
35
- or use standard querySelector syntax */
36
- multiple: (() => boolean) | boolean = false /* are you targeting a single
37
- element, or multiple? true = multiple. Default is false (single) */
34
+ target: HTMLElement | string,
35
+ options: {
36
+ multiple: (() => boolean) | boolean = false,
37
+ root: HTMLElement,
38
+ timeout: number
39
+ }
38
40
  ): Promise<DOMNodeReference | DOMNodeReferenceArray>;
39
41
  ```
40
42
 
43
+ createRef takes two main arguments:
44
+
45
+ <table style="width: 100%; border-collapse: collapse;">
46
+ <thead>
47
+ <tr>
48
+ <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Property</th>
49
+ <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Type</th>
50
+ <th style="border: 1px solid #ddd; padding: 8px; text-align: left;">Details</th>
51
+ </tr>
52
+ </thead>
53
+ <tbody>
54
+ <tr>
55
+ <td style="border: 1px solid #ddd; padding: 8px;">target</td>
56
+ <td style="border: 1px solid #ddd; padding: 8px;">
57
+ <pre><code class="language-javascript">string | HTMLElement</code></pre>
58
+ </td>
59
+ <td style="border: 1px solid #ddd; padding: 8px;">
60
+ Use standard <code>querySelector</code> syntax to target an element, or elements in the DOM, or pass in an instance of the element itself to create a reference.
61
+ </td>
62
+ </tr>
63
+ <tr>
64
+ <td style="border: 1px solid #ddd; padding: 8px;">options</td>
65
+ <td style="border: 1px solid #ddd; padding: 8px;">
66
+ <pre><code class="language-javascript">{
67
+ multiple: () => boolean | boolean,
68
+ root: HTMLElement,
69
+ timeout: number
70
+ }</code></pre>
71
+ </td>
72
+ <td style="border: 1px solid #ddd; padding: 8px;">
73
+ Provides advanced configurations for niche scenarios, such as async DOM element loading, returning arrays of elements, or specifying the parent to search within for the target node.
74
+ </td>
75
+ </tr>
76
+ </tbody>
77
+ </table>
78
+
41
79
  Import the utility function for creating DOMNodeReference(s)
42
80
 
43
81
  ```typescript
44
82
  import { createRef } from "powerpagestoolkit";
45
83
  ```
46
84
 
47
- Instantiate one, or multiple instances of a DOMNodeReference
85
+ Instantiate one, or multiple instances of a DOMNodeReference, and optionally configure advanced options
48
86
 
49
- ```typescript
87
+ ```javascript
50
88
  // Create a single reference
51
- const node = await createRef("#myElement", false);
89
+ const node = await createRef("#myElement");
52
90
 
53
91
  // Create multiple references
54
- const nodes = await createRef(".my-class", true);
92
+ const nodes = await createRef(".my-class", { multiple: true });
93
+
94
+ /******************/
95
+ // ADVANCED OPTIONS
96
+ // in the event that you need to be more granular with how you are targeting
97
+ // and retrieving elements, there are additional options
98
+ // If the node you are targeted is not available at the initial execution
99
+ // of the script, set a timeout for 2 seconds
100
+ const node2 = await createRef("#target", { timeout: 2000 });
101
+
102
+ // need to target a node within a specific node? use that node as the root
103
+ const otherElement = document.getElementById("id");
104
+ const node3 = await createRef("#target", { root: otherElement });
105
+
106
+ // implement all options:
107
+ const nodes2 = await createRef("#target", {
108
+ multiple: true,
109
+ timeout: 4000,
110
+ root: otherElement,
111
+ });
55
112
  ```
56
113
 
57
114
  #### Properties
@@ -7,12 +7,16 @@ declare const _updateRadioGroup: unique symbol;
7
7
  declare const _attachVisibilityController: unique symbol;
8
8
  declare const _attachRadioButtons: unique symbol;
9
9
  declare const _bindMethods: unique symbol;
10
+ declare const observers: unique symbol;
11
+ declare const boundEventListeners: unique symbol;
10
12
  export default class DOMNodeReference {
11
13
  target: HTMLElement | string;
14
+ root: HTMLElement;
15
+ private debounceTime;
12
16
  private isLoaded;
13
17
  private defaultDisplay;
14
- private observers;
15
- private boundEventListeners;
18
+ private [observers];
19
+ private [boundEventListeners];
16
20
  /**
17
21
  * The value of the element that this node represents
18
22
  * stays in syncs with the live DOM elements?.,m via event handler
@@ -41,8 +45,10 @@ export default class DOMNodeReference {
41
45
  /**
42
46
  * Creates an instance of DOMNodeReference.
43
47
  * @param target - The CSS selector to find the desired DOM element.
48
+ * @param root - Optionally specify the element within to search for the element targeted by 'target'
49
+ * Defaults to 'document.body'
44
50
  */
45
- /******/ /******/ constructor(target: HTMLElement | string);
51
+ /******/ /******/ constructor(target: HTMLElement | string, root?: HTMLElement, debounceTime?: number);
46
52
  [_init](): Promise<void>;
47
53
  /**
48
54
  * Initializes value synchronization with appropriate event listeners
package/dist/bundle.js CHANGED
@@ -103,35 +103,77 @@ var API = {
103
103
  var API_default = API;
104
104
 
105
105
  // src/waitFor.ts
106
- function waitFor(target, root = document) {
106
+ function waitFor(target, root = document, multiple = false, debounceTime) {
107
107
  return new Promise((resolve, reject) => {
108
- const observer = new MutationObserver(() => {
109
- const observedElement = root.querySelector(target);
110
- if (observedElement) {
108
+ if (multiple) {
109
+ let timeout;
110
+ const observedElements = [];
111
+ const observedSet = /* @__PURE__ */ new Set();
112
+ if (debounceTime < 1) {
113
+ return resolve(
114
+ Array.from(root.querySelectorAll(target))
115
+ );
116
+ }
117
+ const observer = new MutationObserver(() => {
118
+ const found = Array.from(root.querySelectorAll(target));
119
+ found.forEach((element) => {
120
+ if (!observedSet.has(element)) {
121
+ observedSet.add(element);
122
+ observedElements.push(element);
123
+ }
124
+ });
111
125
  clearTimeout(timeout);
126
+ timeout = setTimeout(() => {
127
+ if (observedElements.length > 0) {
128
+ observer.disconnect();
129
+ resolve(observedElements);
130
+ } else {
131
+ reject(
132
+ new Error(
133
+ `No elements found with target: "${target}" within ${debounceTime / 1e3} seconds. If the element you are expected has not loading, consider raising your timeout.`
134
+ )
135
+ );
136
+ }
137
+ }, debounceTime);
138
+ });
139
+ observer.observe(root, {
140
+ childList: true,
141
+ subtree: true,
142
+ attributes: false
143
+ });
144
+ } else {
145
+ const observer = new MutationObserver(() => {
146
+ const observedElement = root.querySelector(target);
147
+ if (observedElement) {
148
+ clearTimeout(timeout);
149
+ observer.disconnect();
150
+ resolve(observedElement);
151
+ }
152
+ });
153
+ const timeout = setTimeout(() => {
112
154
  observer.disconnect();
113
- resolve(observedElement);
155
+ reject(
156
+ new Error(
157
+ `Element not found by target: "${target}" within ${debounceTime / 1e3} second. If the element you are expected has not loading, consider raising your timeout.`
158
+ )
159
+ );
160
+ }, debounceTime);
161
+ if (target instanceof HTMLElement) {
162
+ clearTimeout(timeout);
163
+ return resolve(target);
114
164
  }
115
- });
116
- const timeout = setTimeout(() => {
117
- observer.disconnect();
118
- reject(new Error(`Element not found: ${target} within 5 seconds`));
119
- }, 5e3);
120
- if (target instanceof HTMLElement) {
121
- clearTimeout(timeout);
122
- return resolve(target);
123
- }
124
- const element = root.querySelector(target);
125
- if (element) {
126
- clearTimeout(timeout);
127
- return resolve(element);
165
+ const element = root.querySelector(target);
166
+ if (element) {
167
+ clearTimeout(timeout);
168
+ return resolve(element);
169
+ }
170
+ observer.observe(root, {
171
+ subtree: true,
172
+ attributes: true,
173
+ childList: true
174
+ // Detects added/removed child elements
175
+ });
128
176
  }
129
- observer.observe(document.body, {
130
- subtree: true,
131
- attributes: true,
132
- childList: true
133
- // Detects added/removed child elements
134
- });
135
177
  });
136
178
  }
137
179
 
@@ -237,13 +279,17 @@ var _updateRadioGroup = Symbol("_URG");
237
279
  var _attachVisibilityController = Symbol("_AVC");
238
280
  var _attachRadioButtons = Symbol("_ARB");
239
281
  var _bindMethods = Symbol("_B");
282
+ var observers = Symbol("O");
283
+ var boundEventListeners = Symbol("BEV");
240
284
  var DOMNodeReference = class _DOMNodeReference {
241
285
  // properties initialized in the constructor
242
286
  target;
287
+ root;
288
+ debounceTime;
243
289
  isLoaded;
244
290
  defaultDisplay;
245
- observers = [];
246
- boundEventListeners = [];
291
+ [observers] = [];
292
+ [boundEventListeners] = [];
247
293
  /**
248
294
  * The value of the element that this node represents
249
295
  * stays in syncs with the live DOM elements?.,m via event handler
@@ -252,11 +298,15 @@ var DOMNodeReference = class _DOMNodeReference {
252
298
  /**
253
299
  * Creates an instance of DOMNodeReference.
254
300
  * @param target - The CSS selector to find the desired DOM element.
301
+ * @param root - Optionally specify the element within to search for the element targeted by 'target'
302
+ * Defaults to 'document.body'
255
303
  */
256
304
  /******/
257
305
  /******/
258
- constructor(target) {
306
+ constructor(target, root = document.body, debounceTime = 5e3) {
259
307
  this.target = target;
308
+ this.root = root;
309
+ this.debounceTime = debounceTime;
260
310
  this.isLoaded = false;
261
311
  this.defaultDisplay = "";
262
312
  this.value = null;
@@ -264,8 +314,11 @@ var DOMNodeReference = class _DOMNodeReference {
264
314
  }
265
315
  async [_init]() {
266
316
  try {
267
- const element = await waitFor(this.target);
268
- this.element = element;
317
+ if (this.target instanceof HTMLElement) {
318
+ this.element = this.target;
319
+ } else {
320
+ this.element = await waitFor(this.target, this.root, false, this.debounceTime);
321
+ }
269
322
  if (!this.element) {
270
323
  throw new DOMNodeNotFoundError(this);
271
324
  }
@@ -323,7 +376,7 @@ var DOMNodeReference = class _DOMNodeReference {
323
376
  this.element.addEventListener(eventType, this.updateValue);
324
377
  const _element = this.element;
325
378
  const _updateValue = this.updateValue;
326
- this.boundEventListeners.push({
379
+ this[boundEventListeners].push({
327
380
  element: _element,
328
381
  handler: _updateValue,
329
382
  event: eventType
@@ -343,10 +396,10 @@ var DOMNodeReference = class _DOMNodeReference {
343
396
  if (!parentElement) {
344
397
  throw new Error("Date input must have a parent element");
345
398
  }
346
- const dateNode = await waitFor("[data-date-format]", parentElement);
399
+ const dateNode = await waitFor("[data-date-format]", parentElement, false, 1500);
347
400
  dateNode.addEventListener("select", this.updateValue);
348
401
  const _handler = this.updateValue;
349
- this.boundEventListeners.push({
402
+ this[boundEventListeners].push({
350
403
  element: dateNode,
351
404
  handler: _handler,
352
405
  event: "select"
@@ -435,10 +488,10 @@ var DOMNodeReference = class _DOMNodeReference {
435
488
  }
436
489
  }
437
490
  [_destroy]() {
438
- this.boundEventListeners?.forEach((binding) => {
491
+ this[boundEventListeners]?.forEach((binding) => {
439
492
  binding.element?.removeEventListener(binding.event, binding.handler);
440
493
  });
441
- this.observers?.forEach((observer) => {
494
+ this[observers]?.forEach((observer) => {
442
495
  observer.disconnect();
443
496
  });
444
497
  this.yesRadio?.[_destroy]();
@@ -477,7 +530,7 @@ var DOMNodeReference = class _DOMNodeReference {
477
530
  this.element.addEventListener(eventType, eventHandler.bind(this));
478
531
  const _element = this.element;
479
532
  const _handler = eventHandler;
480
- this.boundEventListeners.push({
533
+ this[boundEventListeners].push({
481
534
  element: _element,
482
535
  handler: _handler,
483
536
  event: eventType
@@ -596,7 +649,7 @@ var DOMNodeReference = class _DOMNodeReference {
596
649
  );
597
650
  if (childInputs.length > 0) {
598
651
  const promises = childInputs.map(async (input) => {
599
- const inputRef = await createDOMNodeReference(input, false);
652
+ const inputRef = await createDOMNodeReference(input, { multiple: false });
600
653
  return inputRef.clearValue();
601
654
  });
602
655
  await Promise.all(promises);
@@ -880,14 +933,14 @@ var DOMNodeReference = class _DOMNodeReference {
880
933
  }
881
934
  };
882
935
  dep.on("change", handleChange);
883
- this.boundEventListeners.push({
936
+ this[boundEventListeners].push({
884
937
  element: dep.element,
885
938
  event: "change",
886
939
  handler: handleChange
887
940
  });
888
941
  if (trackInputEvents) {
889
942
  dep.on("input", handleChange);
890
- this.boundEventListeners.push({
943
+ this[boundEventListeners].push({
891
944
  element: dep.element,
892
945
  event: "input",
893
946
  handler: handleChange
@@ -907,12 +960,12 @@ var DOMNodeReference = class _DOMNodeReference {
907
960
  attributeFilter: ["style"],
908
961
  subtree: false
909
962
  });
910
- this.observers.push(observer);
963
+ this[observers].push(observer);
911
964
  }
912
965
  if (trackRadioButtons && dep.yesRadio && dep.noRadio) {
913
966
  [dep.yesRadio, dep.noRadio].forEach((radio) => {
914
967
  radio.on("change", handleChange);
915
- this.boundEventListeners.push({
968
+ this[boundEventListeners].push({
916
969
  element: radio.element,
917
970
  event: "change",
918
971
  handler: handleChange
@@ -964,12 +1017,17 @@ var DOMNodeReference = class _DOMNodeReference {
964
1017
  subtree: true,
965
1018
  childList: true
966
1019
  });
967
- this.observers.push(observer);
1020
+ this[observers].push(observer);
968
1021
  }
969
1022
  };
970
1023
 
971
1024
  // src/createDOMNodeReferences.ts
972
- async function createDOMNodeReference(target, multiple = false) {
1025
+ async function createDOMNodeReference(target, options = {
1026
+ multiple: false,
1027
+ root: document.body,
1028
+ timeout: 0
1029
+ }) {
1030
+ const { multiple = false, root = document.body, timeout = 0 } = options;
973
1031
  try {
974
1032
  const isMultiple = typeof multiple === "function" ? multiple() : multiple;
975
1033
  if (isMultiple) {
@@ -978,9 +1036,7 @@ async function createDOMNodeReference(target, multiple = false) {
978
1036
  `'target' must be of type 'string' if 'multiple' is set to 'true'. Received type: '${typeof target}'`
979
1037
  );
980
1038
  }
981
- const elements = Array.from(
982
- document.querySelectorAll(target)
983
- );
1039
+ const elements = await waitFor(target, root, true, timeout);
984
1040
  const initializedElements = await Promise.all(
985
1041
  elements.map(async (element) => {
986
1042
  const instance2 = new DOMNodeReference(element);
@@ -990,7 +1046,7 @@ async function createDOMNodeReference(target, multiple = false) {
990
1046
  );
991
1047
  return enhanceArray(initializedElements);
992
1048
  }
993
- const instance = new DOMNodeReference(target);
1049
+ const instance = new DOMNodeReference(target, root, timeout);
994
1050
  await instance[_init]();
995
1051
  return new Proxy(instance, createProxyHandler());
996
1052
  } catch (e) {
@@ -1,9 +1,7 @@
1
1
  import DOMNodeReference from "./DOMNodeReference.js";
2
- /**
3
- * Creates and initializes a DOMNodeReference instance.
4
- * @async
5
- * @param target - The CSS selector for the desired DOM element, or, optionally, the element itself for which to create a DOMNodeReference.
6
- * @param multiple Should this call return an array of instantiated references, or just a single? Defaults to false, returning a single instance
7
- * @returns A promise that resolves to a Proxy of the initialized DOMNodeReference instance.
8
- */
9
- export default function createDOMNodeReference(target: HTMLElement | string, multiple?: (() => boolean) | boolean): Promise<DOMNodeReference | DOMNodeReference[]>;
2
+ export default function createDOMNodeReference(target: HTMLElement | string, options?: {
3
+ multiple?: false | undefined;
4
+ }): Promise<DOMNodeReference>;
5
+ export default function createDOMNodeReference(target: HTMLElement | string, options?: {
6
+ multiple?: true;
7
+ }): Promise<DOMNodeReference[]>;
package/dist/waitFor.d.ts CHANGED
@@ -1,7 +1,2 @@
1
- /**
2
- *
3
- * @param target basic querySelector syntax to select an element
4
- * @param root optional parameter to replace document as the root from which to perform the node search
5
- * @returns
6
- */
7
- export default function waitFor(target: HTMLElement | string, root?: HTMLElement | Document): Promise<HTMLElement>;
1
+ export default function waitFor(target: HTMLElement | string, root: HTMLElement | Document, multiple: false, debounceTime: number): Promise<HTMLElement>;
2
+ export default function waitFor(target: HTMLElement | string, root: HTMLElement | Document, multiple: true, debounceTime: number): Promise<HTMLElement[]>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "powerpagestoolkit",
3
- "version": "2.6.03",
3
+ "version": "2.6.3201",
4
4
  "description": "Reference, manipulate, and engage with Power Pages sites through the nodes in the DOM; use a variety of custom methods that allow customizing your power pages site quicker and easier. ",
5
5
  "main": "./dist/bundle.js",
6
6
  "types": "./dist/index.d.ts",