powerpagestoolkit 2.5.409 → 2.5.411
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 +86 -24
- package/dist/DOMNodeReference.d.ts +6 -7
- package/dist/bundle.js +64 -57
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,21 +19,36 @@ A TypeScript/JavaScript utility package for seamless DOM manipulation and DataVe
|
|
|
19
19
|
npm install powerpagestoolkit
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
# Core Modules
|
|
23
23
|
|
|
24
|
-
### DOMNodeReference
|
|
24
|
+
- ### DOMNodeReference
|
|
25
25
|
|
|
26
26
|
A powerful class for managing DOM elements with automatic value synchronization and event handling.
|
|
27
27
|
|
|
28
28
|
#### Basic Usage
|
|
29
29
|
|
|
30
|
+
DOMNodeReferences are instantiated with the help of the following factory function
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
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) */
|
|
38
|
+
): Promise<DOMNodeReference | DOMNodeReferenceArray>;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Import the utility function for creating DOMNodeReference(s)
|
|
42
|
+
|
|
30
43
|
```typescript
|
|
31
44
|
import { createRef } from "powerpagestoolkit";
|
|
45
|
+
```
|
|
32
46
|
|
|
33
|
-
|
|
47
|
+
Instantiate one, or multiple instances of a DOMNodeReference
|
|
34
48
|
|
|
49
|
+
```typescript
|
|
35
50
|
// Create a single reference
|
|
36
|
-
const node = await createRef("#myElement");
|
|
51
|
+
const node = await createRef("#myElement", false);
|
|
37
52
|
|
|
38
53
|
// Create multiple references
|
|
39
54
|
const nodes = await createRef(".my-class", true);
|
|
@@ -57,14 +72,16 @@ const nodes = await createRef(".my-class", true);
|
|
|
57
72
|
|
|
58
73
|
```typescript
|
|
59
74
|
// Add event listener with proper 'this' context
|
|
75
|
+
// uses standard eventListener API, and so supports all DOM events
|
|
60
76
|
node.on("change", function (e) {
|
|
61
77
|
console.log("Current value:", this.value);
|
|
62
78
|
});
|
|
63
79
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
console.log("Element ready:", instance.element);
|
|
80
|
+
node.on("click", function (e) {
|
|
81
|
+
console.log(this, " has been clicked");
|
|
67
82
|
});
|
|
83
|
+
|
|
84
|
+
...
|
|
68
85
|
```
|
|
69
86
|
|
|
70
87
|
##### Visibility Control
|
|
@@ -73,63 +90,108 @@ node.onceLoaded((instance) => {
|
|
|
73
90
|
// Basic visibility
|
|
74
91
|
node.hide();
|
|
75
92
|
node.show();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
##### Advanced conditional rendering
|
|
96
|
+
|
|
97
|
+
Out of the box, Microsoft does not provide PowerPages developers the ability to hide or show fields or form elements based on the value of another field. This method allows such configurations
|
|
76
98
|
|
|
77
|
-
|
|
99
|
+
- Method Signature
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
DOMNodeReference.configureConditionalRendering(
|
|
103
|
+
condition: () => boolean,
|
|
104
|
+
dependencies?: Array<DOMNodeReference>,
|
|
105
|
+
clearValuesOnHide: boolean = true
|
|
106
|
+
): DOMNodeReference
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- Method Implementation
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
78
112
|
node.configureConditionalRendering(
|
|
79
113
|
// Function to evaluate wether this node should be visible or not
|
|
80
114
|
function () {
|
|
81
|
-
return otherNode.value === "
|
|
115
|
+
return otherNode.value === "some value";
|
|
82
116
|
},
|
|
83
|
-
[otherNode]
|
|
117
|
+
[otherNode] /* Dependency array | if the values or visibility of these
|
|
118
|
+
change, the function is re-evaluated */,
|
|
119
|
+
true /* should the values in the targeted elements (this.element)
|
|
120
|
+
be cleared if this node is hidden? Default = true */
|
|
84
121
|
);
|
|
85
122
|
```
|
|
86
123
|
|
|
87
124
|
##### Validation and Requirements
|
|
88
125
|
|
|
126
|
+
This utility enhances PowerPages forms by adding dynamic field validation and conditional requirements based on other field values.
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// Core method for setting up validation
|
|
130
|
+
function configureValidationAndRequirements(
|
|
131
|
+
isRequired: () => boolean, // Determines if field is required
|
|
132
|
+
isValid: () => boolean, // Validates field content
|
|
133
|
+
fieldDisplayName: string, // User-facing field name for error messages
|
|
134
|
+
dependencies: DOMNodeReference[] // Fields that trigger validation checks
|
|
135
|
+
): DOMNodeReference; /* instance of this is returned for optional
|
|
136
|
+
method chaining */
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
- Here's a practical example showing how to make a field required only when a "Yes" radio button is selected:
|
|
140
|
+
|
|
89
141
|
```typescript
|
|
90
142
|
node.configureValidationAndRequirements(
|
|
91
|
-
//
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// Function to evaluate if the data in this field is valid
|
|
143
|
+
// Make field required only when "Yes" is checked
|
|
144
|
+
() => dependentNode.yesRadio?.checked ?? false,
|
|
145
|
+
|
|
146
|
+
// Basic validation: ensure field isn't empty
|
|
96
147
|
function () {
|
|
97
148
|
return this.value != null && this.value !== "";
|
|
98
149
|
},
|
|
99
|
-
|
|
100
|
-
|
|
150
|
+
|
|
151
|
+
"Contact Phone", // Shows in error message: "Contact Phone is required"
|
|
152
|
+
|
|
153
|
+
[dependentNode] // Revalidate when dependentNode changes
|
|
101
154
|
);
|
|
102
155
|
```
|
|
103
156
|
|
|
104
157
|
##### Element Manipulation
|
|
105
158
|
|
|
106
159
|
```typescript
|
|
107
|
-
|
|
108
|
-
|
|
160
|
+
/****/ Value management /****/
|
|
161
|
+
|
|
162
|
+
// set a static value
|
|
163
|
+
node.setValue("new value");
|
|
164
|
+
|
|
109
165
|
// or set a value by using some sort of logic
|
|
110
166
|
node.setValue(() => {
|
|
111
167
|
if (true) {
|
|
112
168
|
return "value";
|
|
113
169
|
} else return "default";
|
|
114
170
|
});
|
|
115
|
-
node.updateValue(); // Sync with DOM
|
|
116
171
|
|
|
117
|
-
//
|
|
172
|
+
// Sync with DOM
|
|
173
|
+
node.updateValue();
|
|
174
|
+
|
|
175
|
+
/****/ Content manipulation /****/
|
|
176
|
+
|
|
118
177
|
node.setInnerHTML("<span>New content</span>");
|
|
119
178
|
node.append(childElement);
|
|
120
179
|
node.prepend(headerElement);
|
|
121
180
|
node.after(siblingElement);
|
|
122
181
|
node.before(labelElement);
|
|
123
182
|
|
|
124
|
-
|
|
183
|
+
/****/ Styling /****/
|
|
184
|
+
|
|
125
185
|
node.setStyle({
|
|
126
186
|
display: "block",
|
|
127
187
|
color: "red",
|
|
128
188
|
});
|
|
129
189
|
|
|
130
|
-
|
|
190
|
+
/****/ State management /****/
|
|
191
|
+
|
|
131
192
|
node.disable();
|
|
132
193
|
node.enable();
|
|
194
|
+
|
|
133
195
|
```
|
|
134
196
|
|
|
135
197
|
##### Label and Tooltip Management
|
|
@@ -151,7 +213,7 @@ node.addTooltip(
|
|
|
151
213
|
);
|
|
152
214
|
```
|
|
153
215
|
|
|
154
|
-
### DataVerse API
|
|
216
|
+
- ### DataVerse API
|
|
155
217
|
|
|
156
218
|
Type-safe wrapper for DataVerse API operations.
|
|
157
219
|
|
|
@@ -6,14 +6,12 @@ export default class DOMNodeReference {
|
|
|
6
6
|
/**
|
|
7
7
|
* The value of the element that this node represents
|
|
8
8
|
* stays in syncs with the live DOM elements?.,m via event handler
|
|
9
|
-
* @type {any}
|
|
10
9
|
*/
|
|
11
10
|
value: any;
|
|
12
11
|
/**
|
|
13
12
|
* The element targeted when instantiating DOMNodeReference.
|
|
14
13
|
* Made available in order to perform normal DOM traversal,
|
|
15
14
|
* or access properties not available through this class.
|
|
16
|
-
* @property {HTMLElement | null}
|
|
17
15
|
*/
|
|
18
16
|
element: Element;
|
|
19
17
|
private visibilityController;
|
|
@@ -22,19 +20,17 @@ export default class DOMNodeReference {
|
|
|
22
20
|
* Represents the 'yes' option of a boolean radio field.
|
|
23
21
|
* This property is only available when the parent node
|
|
24
22
|
* is a main field for a boolean radio input.
|
|
25
|
-
* @property {DOMNodeReferenceProxy | null}
|
|
26
23
|
*/
|
|
27
24
|
yesRadio?: DOMNodeReference | null;
|
|
28
25
|
/**
|
|
29
26
|
* Represents the 'no' option of a boolean radio field.
|
|
30
27
|
* This property is only available when the parent node
|
|
31
28
|
* is a main field for a boolean radio input.
|
|
32
|
-
* @property {DOMNodeReferenceProxy | null}
|
|
33
29
|
*/
|
|
34
30
|
noRadio?: DOMNodeReference | null;
|
|
35
31
|
/**
|
|
36
32
|
* Creates an instance of DOMNodeReference.
|
|
37
|
-
* @param
|
|
33
|
+
* @param target - The CSS selector to find the desired DOM element.
|
|
38
34
|
*/
|
|
39
35
|
/******/ /******/ constructor(target: HTMLElement | string);
|
|
40
36
|
[_init](): Promise<void>;
|
|
@@ -206,10 +202,13 @@ export default class DOMNodeReference {
|
|
|
206
202
|
*/
|
|
207
203
|
configureValidationAndRequirements(isRequired: () => boolean, isValid: () => boolean, fieldDisplayName: string, dependencies: Array<DOMNodeReference>): DOMNodeReference;
|
|
208
204
|
/**
|
|
209
|
-
* Sets up tracking for
|
|
205
|
+
* Sets up tracking for dependencies using both event listeners and mutation observers.
|
|
210
206
|
* @private
|
|
207
|
+
* @param handler - The function to execute when dependencies change
|
|
208
|
+
* @param dependencies - Array of dependent DOM nodes to track
|
|
209
|
+
* @param options - Additional configuration options
|
|
211
210
|
*/
|
|
212
|
-
private
|
|
211
|
+
private _configDependencyTracking;
|
|
213
212
|
/**
|
|
214
213
|
* Sets the required level for the field by adding or removing the "required-field" class on the label.
|
|
215
214
|
*
|
package/dist/bundle.js
CHANGED
|
@@ -237,12 +237,11 @@ var DOMNodeReference = class _DOMNodeReference {
|
|
|
237
237
|
/**
|
|
238
238
|
* The value of the element that this node represents
|
|
239
239
|
* stays in syncs with the live DOM elements?.,m via event handler
|
|
240
|
-
* @type {any}
|
|
241
240
|
*/
|
|
242
241
|
value;
|
|
243
242
|
/**
|
|
244
243
|
* Creates an instance of DOMNodeReference.
|
|
245
|
-
* @param
|
|
244
|
+
* @param target - The CSS selector to find the desired DOM element.
|
|
246
245
|
*/
|
|
247
246
|
/******/
|
|
248
247
|
/******/
|
|
@@ -710,40 +709,16 @@ var DOMNodeReference = class _DOMNodeReference {
|
|
|
710
709
|
);
|
|
711
710
|
return this;
|
|
712
711
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
712
|
+
this._configDependencyTracking(
|
|
713
|
+
() => this.toggleVisibility(condition()),
|
|
714
|
+
dependencies,
|
|
715
|
+
{
|
|
716
|
+
clearValuesOnHide,
|
|
717
|
+
observeVisibility: true,
|
|
718
|
+
trackInputEvents: false,
|
|
719
|
+
trackRadioButtons: false
|
|
718
720
|
}
|
|
719
|
-
|
|
720
|
-
try {
|
|
721
|
-
this.toggleVisibility(condition());
|
|
722
|
-
if (condition() === false && clearValuesOnHide) {
|
|
723
|
-
this.clearValues();
|
|
724
|
-
}
|
|
725
|
-
} catch (error) {
|
|
726
|
-
console.error("Error in change handler:", error);
|
|
727
|
-
}
|
|
728
|
-
};
|
|
729
|
-
node.on("change", handleChange);
|
|
730
|
-
const observer = new MutationObserver(() => {
|
|
731
|
-
try {
|
|
732
|
-
const display = window.getComputedStyle(
|
|
733
|
-
node.visibilityController
|
|
734
|
-
).display;
|
|
735
|
-
this.toggleVisibility(display !== "none" && condition());
|
|
736
|
-
} catch (error) {
|
|
737
|
-
0;
|
|
738
|
-
console.error("Error in mutation observer:", error);
|
|
739
|
-
observer.disconnect();
|
|
740
|
-
}
|
|
741
|
-
});
|
|
742
|
-
observer.observe(node.visibilityController, {
|
|
743
|
-
attributes: true,
|
|
744
|
-
attributeFilter: ["style"]
|
|
745
|
-
});
|
|
746
|
-
});
|
|
721
|
+
);
|
|
747
722
|
return this;
|
|
748
723
|
} catch (error) {
|
|
749
724
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -792,7 +767,10 @@ var DOMNodeReference = class _DOMNodeReference {
|
|
|
792
767
|
Object.assign(newValidator, validatorConfig);
|
|
793
768
|
Page_Validators.push(newValidator);
|
|
794
769
|
this.setRequiredLevel(isRequired());
|
|
795
|
-
this.
|
|
770
|
+
this._configDependencyTracking(
|
|
771
|
+
() => this.setRequiredLevel(isRequired()),
|
|
772
|
+
dependencies
|
|
773
|
+
);
|
|
796
774
|
} catch (error) {
|
|
797
775
|
throw new ValidationConfigError(
|
|
798
776
|
this,
|
|
@@ -802,35 +780,64 @@ var DOMNodeReference = class _DOMNodeReference {
|
|
|
802
780
|
return this;
|
|
803
781
|
}
|
|
804
782
|
/**
|
|
805
|
-
* Sets up tracking for
|
|
783
|
+
* Sets up tracking for dependencies using both event listeners and mutation observers.
|
|
806
784
|
* @private
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
785
|
+
* @param handler - The function to execute when dependencies change
|
|
786
|
+
* @param dependencies - Array of dependent DOM nodes to track
|
|
787
|
+
* @param options - Additional configuration options
|
|
788
|
+
*/
|
|
789
|
+
_configDependencyTracking(handler, dependencies, options = {
|
|
790
|
+
clearValuesOnHide: false,
|
|
791
|
+
observeVisibility: true,
|
|
792
|
+
trackInputEvents: true,
|
|
793
|
+
trackRadioButtons: true
|
|
794
|
+
}) {
|
|
795
|
+
const {
|
|
796
|
+
clearValuesOnHide = false,
|
|
797
|
+
observeVisibility = true,
|
|
798
|
+
trackInputEvents = true,
|
|
799
|
+
trackRadioButtons = true
|
|
800
|
+
} = options;
|
|
801
|
+
if (!dependencies?.length) {
|
|
810
802
|
console.warn(
|
|
811
|
-
`powerpagestoolkit: No dependencies specified for ${this.element.id}. Include all referenced nodes in the dependency array for proper
|
|
803
|
+
`powerpagestoolkit: No dependencies specified for ${this.element.id}. Include all referenced nodes in the dependency array for proper tracking.`
|
|
812
804
|
);
|
|
813
805
|
return;
|
|
814
806
|
}
|
|
815
807
|
dependencies.forEach((dep) => {
|
|
816
|
-
dep
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
808
|
+
if (!dep || !(dep instanceof _DOMNodeReference)) {
|
|
809
|
+
throw new TypeError(
|
|
810
|
+
"Each dependency must be a valid DOMNodeReference instance"
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
const handleChange = () => {
|
|
814
|
+
handler();
|
|
815
|
+
if (clearValuesOnHide && window.getComputedStyle(this.visibilityController).display === "none") {
|
|
816
|
+
this.clearValues();
|
|
824
817
|
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
818
|
+
};
|
|
819
|
+
dep.on("change", handleChange);
|
|
820
|
+
if (trackInputEvents) {
|
|
821
|
+
dep.on("input", handleChange);
|
|
822
|
+
}
|
|
823
|
+
if (observeVisibility) {
|
|
824
|
+
const observer = new MutationObserver(() => {
|
|
825
|
+
const display = window.getComputedStyle(
|
|
826
|
+
dep.visibilityController
|
|
827
|
+
).display;
|
|
828
|
+
if (display !== "none") {
|
|
829
|
+
handler();
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
observer.observe(dep.visibilityController, {
|
|
833
|
+
attributes: true,
|
|
834
|
+
attributeFilter: ["style"],
|
|
835
|
+
subtree: false
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
if (trackRadioButtons && (dep.yesRadio || dep.noRadio)) {
|
|
832
839
|
[dep.yesRadio, dep.noRadio].forEach((radio) => {
|
|
833
|
-
radio?.on("change",
|
|
840
|
+
radio?.on("change", handleChange);
|
|
834
841
|
});
|
|
835
842
|
}
|
|
836
843
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "powerpagestoolkit",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.411",
|
|
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",
|