@cocreate/events 1.26.0 → 1.27.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 +18 -0
- package/demo/set-value.html +21 -25
- package/package.json +1 -1
- package/src/index.js +278 -35
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
# [1.27.0](https://github.com/CoCreate-app/CoCreate-events/compare/v1.26.0...v1.27.0) (2025-04-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* console.log() ([2174c1e](https://github.com/CoCreate-app/CoCreate-events/commit/2174c1e0a9fa0b777e073de30aed4f29ec59f8f6))
|
|
7
|
+
* formating ([58b8550](https://github.com/CoCreate-app/CoCreate-events/commit/58b8550c96c30153a94e24ce93b39914eed2fba3))
|
|
8
|
+
* removed console.log() ([f44cb8f](https://github.com/CoCreate-app/CoCreate-events/commit/f44cb8fdfec3b3b1787e830cd1b3bab3a1ef3fa5))
|
|
9
|
+
* renamed prefix-delay to prefix-setTimout ([84e511a](https://github.com/CoCreate-app/CoCreate-events/commit/84e511af8bcb521e5e8e7bc481a6f202fca04930))
|
|
10
|
+
* Selctor === "" returning null ([c49bc35](https://github.com/CoCreate-app/CoCreate-events/commit/c49bc35cd8a8ff9232229ee64d71bc4e32d3d6fc))
|
|
11
|
+
* selectors ([ccb2dee](https://github.com/CoCreate-app/CoCreate-events/commit/ccb2dee2a682bcdf601047f0783c5c44ebcfe5ed))
|
|
12
|
+
* update observer obseve param to type and and attributeName to attributeFilter ([44372d4](https://github.com/CoCreate-app/CoCreate-events/commit/44372d4ceba70360507cd0c94df43f4ee877be99))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* support "*-preventDefault", "*-stopPropagation", "*-stopImmediatePropagation" ([5b10663](https://github.com/CoCreate-app/CoCreate-events/commit/5b106633f425001ca6ec7d65dc0bd00ad6368b64))
|
|
18
|
+
|
|
1
19
|
# [1.26.0](https://github.com/CoCreate-app/CoCreate-events/compare/v1.25.0...v1.26.0) (2025-01-18)
|
|
2
20
|
|
|
3
21
|
|
package/demo/set-value.html
CHANGED
|
@@ -1,31 +1,27 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
<head>
|
|
4
|
+
<title>Value | CoCreateJS</title>
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
<!-- CoCreate Favicon -->
|
|
7
|
+
<link
|
|
8
|
+
rel="icon"
|
|
9
|
+
type="image/png"
|
|
10
|
+
sizes="32x32"
|
|
11
|
+
href="../assets/favicon.ico" />
|
|
12
|
+
<link rel="manifest" href="/manifest.webmanifest" />
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<div click-selector="#testing" click-value="hello, bye" click-key="ty">
|
|
16
|
+
<span id="testing" class="{{ty}}">other content</span>
|
|
17
|
+
</div>
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
value-type="array" />
|
|
19
|
+
<form>
|
|
20
|
+
<input input-selector="#testing2" input-attribute="value" />
|
|
21
|
+
<input id="testing2" />
|
|
22
|
+
</form>
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
<!-- <script src="../../../CoCreateJS/dist/CoCreate.js"></script> -->
|
|
29
|
-
<script src="https://CoCreate.app/dist/CoCreate.js"></script>
|
|
30
|
-
</body>
|
|
24
|
+
<!-- <script src="../../../CoCreateJS/dist/CoCreate.js"></script> -->
|
|
25
|
+
<script src="https://CoCreate.app/dist/CoCreate.js"></script>
|
|
26
|
+
</body>
|
|
31
27
|
</html>
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -63,7 +63,7 @@ const CoCreateEvents = {
|
|
|
63
63
|
const self = this;
|
|
64
64
|
observer.init({
|
|
65
65
|
name: "CoCreateEventName",
|
|
66
|
-
|
|
66
|
+
types: ["addedNodes"],
|
|
67
67
|
selector: `[event-name]`,
|
|
68
68
|
callback: function (mutation) {
|
|
69
69
|
let name = mutation.target.getAttribute("event-name");
|
|
@@ -89,12 +89,12 @@ const CoCreateEvents = {
|
|
|
89
89
|
}
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
let selector = `[${prefix}], [${prefix}-key], [${prefix}-attribute], [${prefix}-value], [${prefix}-action], [${prefix}-selector], [${prefix}-closest], [${prefix}-parent], [${prefix}-next], [${prefix}-previous]`;
|
|
92
|
+
let selector = `[${prefix}], [${prefix}-key], [${prefix}-attribute], [${prefix}-value], [${prefix}-action], [${prefix}-selector], [${prefix}-closest], [${prefix}-parent], [${prefix}-next], [${prefix}-previous], [${prefix}-preventDefault], [${prefix}-stopPropagation], [${prefix}-stopImmediatePropagation]`;
|
|
93
93
|
|
|
94
94
|
observer.init({
|
|
95
95
|
name: "CoCreateEventattributes",
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
types: ["attributes", "addedNodes"],
|
|
97
|
+
attributeFilter: [
|
|
98
98
|
`${prefix}-key`,
|
|
99
99
|
`${prefix}-value`,
|
|
100
100
|
`${prefix}-selector`,
|
|
@@ -102,7 +102,13 @@ const CoCreateEvents = {
|
|
|
102
102
|
`${prefix}-parent`,
|
|
103
103
|
`${prefix}-next`,
|
|
104
104
|
`${prefix}-previous`,
|
|
105
|
-
`${prefix}-events
|
|
105
|
+
`${prefix}-events`,
|
|
106
|
+
`${prefix}-bubbles`,
|
|
107
|
+
`${prefix}-cancelable`,
|
|
108
|
+
`${prefix}-composed`,
|
|
109
|
+
`${prefix}-preventDefault`,
|
|
110
|
+
`${prefix}-stopPropagation`,
|
|
111
|
+
`${prefix}-stopImmediatePropagation`
|
|
106
112
|
],
|
|
107
113
|
selector,
|
|
108
114
|
callback: function (mutation) {
|
|
@@ -125,7 +131,9 @@ const CoCreateEvents = {
|
|
|
125
131
|
this.elements.set(el, prefixes);
|
|
126
132
|
} else if (!prefixes[prefix]) {
|
|
127
133
|
prefixes[prefix] = { events };
|
|
128
|
-
} else
|
|
134
|
+
} else {
|
|
135
|
+
isEventable = false;
|
|
136
|
+
}
|
|
129
137
|
|
|
130
138
|
let customEvents = el.getAttribute(`${prefix}-events`);
|
|
131
139
|
if (customEvents) {
|
|
@@ -140,8 +148,25 @@ const CoCreateEvents = {
|
|
|
140
148
|
prefixes[prefix].events = events;
|
|
141
149
|
isEventable = true;
|
|
142
150
|
}
|
|
151
|
+
|
|
143
152
|
if (!events || !isEventable) continue;
|
|
144
|
-
|
|
153
|
+
|
|
154
|
+
// let originalSelector = ""; // i think we need to extract the selector and remove the operators
|
|
155
|
+
// if (originalSelector) {
|
|
156
|
+
// observer.init({
|
|
157
|
+
// types: ["addedNodes"],
|
|
158
|
+
// callback: function (mutation) {
|
|
159
|
+
// const els = el.queryElements();
|
|
160
|
+
// if (els && els.includes(mutation.target)) {
|
|
161
|
+
// self.__updateElements();
|
|
162
|
+
// }
|
|
163
|
+
// }
|
|
164
|
+
// });
|
|
165
|
+
// }
|
|
166
|
+
|
|
167
|
+
if (events.includes("onload")) {
|
|
168
|
+
this.__updateElements(el, prefix);
|
|
169
|
+
}
|
|
145
170
|
|
|
146
171
|
if (events.includes("observer")) {
|
|
147
172
|
let target;
|
|
@@ -163,7 +188,7 @@ const CoCreateEvents = {
|
|
|
163
188
|
}
|
|
164
189
|
}
|
|
165
190
|
|
|
166
|
-
let
|
|
191
|
+
let attributeFilter = (
|
|
167
192
|
el.getAttribute(`${prefix}-attributes`) || ""
|
|
168
193
|
)
|
|
169
194
|
.split(/\s*,\s*/)
|
|
@@ -176,7 +201,7 @@ const CoCreateEvents = {
|
|
|
176
201
|
.filter((item) => item);
|
|
177
202
|
|
|
178
203
|
let observerConfig = {
|
|
179
|
-
|
|
204
|
+
types: observeAttribute,
|
|
180
205
|
callback: function (mutation) {
|
|
181
206
|
self.__updateElements(el, prefix, mutation.target);
|
|
182
207
|
}
|
|
@@ -186,20 +211,19 @@ const CoCreateEvents = {
|
|
|
186
211
|
if (
|
|
187
212
|
target &&
|
|
188
213
|
!observeAttribute.length &&
|
|
189
|
-
!
|
|
214
|
+
!attributeFilter.length
|
|
190
215
|
) {
|
|
191
|
-
observerConfig.
|
|
216
|
+
observerConfig.types.push("addedNodes");
|
|
192
217
|
}
|
|
193
218
|
observerConfig.target = target;
|
|
194
219
|
}
|
|
195
220
|
|
|
196
|
-
if (
|
|
197
|
-
observerConfig.
|
|
198
|
-
observerConfig.
|
|
221
|
+
if (attributeFilter.length) {
|
|
222
|
+
observerConfig.types.push("attributes");
|
|
223
|
+
observerConfig.attributeFilter = attributeFilter;
|
|
199
224
|
}
|
|
200
225
|
|
|
201
|
-
if (observerConfig.
|
|
202
|
-
observer.init(observerConfig);
|
|
226
|
+
if (observerConfig.types.length) observer.init(observerConfig);
|
|
203
227
|
}
|
|
204
228
|
|
|
205
229
|
if (events.includes("resize")) {
|
|
@@ -270,19 +294,40 @@ const CoCreateEvents = {
|
|
|
270
294
|
}
|
|
271
295
|
|
|
272
296
|
for (let i = 0; i < events.length; i++) {
|
|
297
|
+
// Skip specific lifecycle events
|
|
273
298
|
if (
|
|
274
|
-
events[i]
|
|
275
|
-
events[i]
|
|
276
|
-
events[i]
|
|
277
|
-
events[i]
|
|
299
|
+
events[i] === "onload" ||
|
|
300
|
+
events[i] === "observer" ||
|
|
301
|
+
events[i] === "intersection" ||
|
|
302
|
+
events[i] === "resize"
|
|
278
303
|
) {
|
|
279
|
-
|
|
280
|
-
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Remove any existing event listener
|
|
308
|
+
el.removeEventListener(events[i], eventFunction);
|
|
309
|
+
|
|
310
|
+
// Initialize an empty options object
|
|
311
|
+
const options = {};
|
|
312
|
+
|
|
313
|
+
// Attributes to check dynamically
|
|
314
|
+
const attributes = ["bubbles", "cancelable", "composed"];
|
|
315
|
+
|
|
316
|
+
for (let j = 0; j < attributes.length; j++) {
|
|
317
|
+
const attrValue = el.getAttribute(
|
|
318
|
+
`${events[i]}-${attributes[j]}`
|
|
319
|
+
);
|
|
320
|
+
if (attrValue !== null) {
|
|
321
|
+
options[attributes[j]] = attrValue !== "false";
|
|
322
|
+
}
|
|
281
323
|
}
|
|
324
|
+
|
|
325
|
+
// Add the new event listener with the dynamically constructed options
|
|
326
|
+
el.addEventListener(events[i], eventFunction, options);
|
|
282
327
|
}
|
|
283
328
|
|
|
284
329
|
function eventFunction(event) {
|
|
285
|
-
// TODO: apply debounce
|
|
330
|
+
// TODO: apply debounce.
|
|
286
331
|
// let debounce;
|
|
287
332
|
// clearTimeout(debounce);
|
|
288
333
|
// debounce = setTimeout(function() {
|
|
@@ -300,6 +345,25 @@ const CoCreateEvents = {
|
|
|
300
345
|
if (attribute.includes(prefix)) return;
|
|
301
346
|
// if (target.closest(`[actions*="${prefix}"]`))
|
|
302
347
|
// return;
|
|
348
|
+
|
|
349
|
+
// Define the lifecycle attributes (matching JavaScript event methods)
|
|
350
|
+
const lifecycleAttributes = [
|
|
351
|
+
"preventDefault",
|
|
352
|
+
"stopPropagation",
|
|
353
|
+
"stopImmediatePropagation"
|
|
354
|
+
];
|
|
355
|
+
|
|
356
|
+
// Handle lifecycle attributes dynamically
|
|
357
|
+
for (let i = 0; i < lifecycleAttributes.length; i++) {
|
|
358
|
+
const attr = `${prefix}-${lifecycleAttributes[i]}`; // Add prefix dynamically
|
|
359
|
+
const attrValue = target.getAttribute(attr); // Directly get the attribute value
|
|
360
|
+
|
|
361
|
+
// If attribute exists and is not explicitly "false", apply the corresponding event method
|
|
362
|
+
if (attrValue !== null && attrValue !== "false") {
|
|
363
|
+
event[lifecycleAttributes[i]]();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
303
367
|
self.__updateElements(
|
|
304
368
|
target,
|
|
305
369
|
prefix,
|
|
@@ -341,7 +405,26 @@ const CoCreateEvents = {
|
|
|
341
405
|
}
|
|
342
406
|
|
|
343
407
|
for (let element of elements) {
|
|
344
|
-
|
|
408
|
+
// const requestAnimationFrameAttr = element.getAttribute(
|
|
409
|
+
// `${prefix}-requestAnimationFrame`
|
|
410
|
+
// );
|
|
411
|
+
|
|
412
|
+
// if (
|
|
413
|
+
// requestAnimationFrameAttr !== null &&
|
|
414
|
+
// requestAnimationFrameAttr !== "false"
|
|
415
|
+
// ) {
|
|
416
|
+
// // Double requestAnimationFrame
|
|
417
|
+
// await new Promise((resolve) => {
|
|
418
|
+
// requestAnimationFrame(() => {
|
|
419
|
+
// requestAnimationFrame(() => {
|
|
420
|
+
// resolve();
|
|
421
|
+
// });
|
|
422
|
+
// });
|
|
423
|
+
// });
|
|
424
|
+
// }
|
|
425
|
+
|
|
426
|
+
// TODO: Handle setInterval logic
|
|
427
|
+
let delay = element.getAttribute(`${prefix}-setTimeout`);
|
|
345
428
|
|
|
346
429
|
if (delay) {
|
|
347
430
|
delay = parseInt(delay, 10) || 0;
|
|
@@ -431,13 +514,15 @@ const CoCreateEvents = {
|
|
|
431
514
|
let elseCondition = element.getAttribute(`${prefix}-else`);
|
|
432
515
|
|
|
433
516
|
let ifValue = element.getAttribute(`${prefix}-if-value`);
|
|
434
|
-
if (
|
|
435
|
-
ifValue
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
517
|
+
if (ifCondition) {
|
|
518
|
+
if (!ifValue && ifValue !== "")
|
|
519
|
+
ifValue = (await element.getValue()) || values;
|
|
520
|
+
//values // await element.getValue()
|
|
521
|
+
else if (ifValue || ifValue === "") ifValue = [ifValue];
|
|
522
|
+
else ifValue = values;
|
|
523
|
+
|
|
524
|
+
if (!Array.isArray(ifValue)) ifValue = [ifValue];
|
|
525
|
+
}
|
|
441
526
|
|
|
442
527
|
//TODO: improved resize toggling of values
|
|
443
528
|
// let hasCondition = this.elements2.get(element)
|
|
@@ -485,7 +570,11 @@ const CoCreateEvents = {
|
|
|
485
570
|
prefix,
|
|
486
571
|
selector: params
|
|
487
572
|
});
|
|
488
|
-
|
|
573
|
+
|
|
574
|
+
if (targetElements === false) {
|
|
575
|
+
targetElements = [element];
|
|
576
|
+
}
|
|
577
|
+
|
|
489
578
|
let action = element.getAttribute(`${prefix}-action`);
|
|
490
579
|
for (let i = 0; i < targetElements.length; i++) {
|
|
491
580
|
if (action) {
|
|
@@ -520,7 +609,7 @@ const CoCreateEvents = {
|
|
|
520
609
|
}
|
|
521
610
|
}
|
|
522
611
|
|
|
523
|
-
|
|
612
|
+
el.dispatchEvent(
|
|
524
613
|
new CustomEvent(`${prefix}End`, {
|
|
525
614
|
detail: {}
|
|
526
615
|
})
|
|
@@ -565,7 +654,7 @@ const CoCreateEvents = {
|
|
|
565
654
|
// let value = values[0]
|
|
566
655
|
replaceKey(prefix, element, key, values);
|
|
567
656
|
} else {
|
|
568
|
-
//
|
|
657
|
+
// TODO: if html in iframe
|
|
569
658
|
let domTextEditor;
|
|
570
659
|
if (element.parentElement) {
|
|
571
660
|
domTextEditor =
|
|
@@ -628,7 +717,7 @@ const CoCreateEvents = {
|
|
|
628
717
|
element.classList.add(newValue);
|
|
629
718
|
}
|
|
630
719
|
} else if (attrName === "value") {
|
|
631
|
-
element.setValue(newValue);
|
|
720
|
+
element.setValue(newValue, false);
|
|
632
721
|
} else if (
|
|
633
722
|
["$click", "$focus", "$blur", "$save", "$read"].includes(
|
|
634
723
|
attrName
|
|
@@ -871,6 +960,160 @@ function parseNumberCondition(condition) {
|
|
|
871
960
|
: condition;
|
|
872
961
|
}
|
|
873
962
|
|
|
963
|
+
// Helper function for delay using Promises
|
|
964
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Waits for a specific element property to meet a readiness condition,
|
|
968
|
+
* based on retry attributes defined on the element.
|
|
969
|
+
* Incorporates optional exponential backoff for retry delays.
|
|
970
|
+
* Returns a Promise that resolves to true if the condition is met within
|
|
971
|
+
* the allowed attempts, and false otherwise.
|
|
972
|
+
*
|
|
973
|
+
* @param {HTMLElement} element The element with the onload-retry-* attributes.
|
|
974
|
+
* @returns {Promise<boolean>} A Promise resolving to true if ready, false if timed out.
|
|
975
|
+
*/
|
|
976
|
+
async function checkElementReadinessWithBackoff(element) {
|
|
977
|
+
const propertyName = element.getAttribute("onload-retry-property");
|
|
978
|
+
|
|
979
|
+
if (!propertyName) {
|
|
980
|
+
return true; // No retry needed
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// --- Retry Parameters ---
|
|
984
|
+
const maxAttempts =
|
|
985
|
+
parseInt(element.getAttribute("onload-retry-attempts") || "3", 10) || 3;
|
|
986
|
+
// Initial delay (used for the first wait and as the base for backoff)
|
|
987
|
+
const initialDelayMs =
|
|
988
|
+
parseInt(element.getAttribute("onload-retry-delay") || "100", 10) ||
|
|
989
|
+
100;
|
|
990
|
+
// Exponential backoff factor (e.g., 2 for doubling). <= 1 means fixed delay.
|
|
991
|
+
// Default to 1 (no backoff) if missing or invalid.
|
|
992
|
+
const backoffFactor =
|
|
993
|
+
parseFloat(
|
|
994
|
+
element.getAttribute("onload-retry-backoff-factor") || "1"
|
|
995
|
+
) || 1;
|
|
996
|
+
// Optional maximum delay cap. Use Infinity if missing, invalid, or <= 0.
|
|
997
|
+
const maxDelayMs = parseInt(
|
|
998
|
+
element.getAttribute("onload-retry-max-delay") || "0",
|
|
999
|
+
10
|
|
1000
|
+
);
|
|
1001
|
+
const effectiveMaxDelay =
|
|
1002
|
+
maxDelayMs && maxDelayMs > 0 ? maxDelayMs : Infinity;
|
|
1003
|
+
|
|
1004
|
+
console.log(
|
|
1005
|
+
`Checking readiness for property "${propertyName}" on element ${
|
|
1006
|
+
element.id || ""
|
|
1007
|
+
}. Max attempts: ${maxAttempts}, Initial Delay: ${initialDelayMs}ms, Backoff Factor: ${backoffFactor}, Max Delay: ${
|
|
1008
|
+
effectiveMaxDelay === Infinity ? "None" : effectiveMaxDelay + "ms"
|
|
1009
|
+
}.`
|
|
1010
|
+
);
|
|
1011
|
+
|
|
1012
|
+
// Initialize the delay to be used for the *first* wait.
|
|
1013
|
+
let currentDelay = initialDelayMs;
|
|
1014
|
+
|
|
1015
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1016
|
+
console.log(
|
|
1017
|
+
`Attempt ${attempt}/${maxAttempts}: Checking "${propertyName}"...`
|
|
1018
|
+
);
|
|
1019
|
+
try {
|
|
1020
|
+
const propertyValue = element[propertyName];
|
|
1021
|
+
// Example check: Adjust condition as needed
|
|
1022
|
+
if (propertyValue !== undefined && propertyValue > 0) {
|
|
1023
|
+
console.log(
|
|
1024
|
+
`Property "${propertyName}" ready on attempt ${attempt}. Value: ${propertyValue}`
|
|
1025
|
+
);
|
|
1026
|
+
return true; // Condition met
|
|
1027
|
+
}
|
|
1028
|
+
} catch (error) {
|
|
1029
|
+
console.error(
|
|
1030
|
+
`Error accessing property "${propertyName}" on attempt ${attempt}:`,
|
|
1031
|
+
error
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// If condition not met and more attempts remain:
|
|
1036
|
+
if (attempt < maxAttempts) {
|
|
1037
|
+
// Determine the actual delay for this wait, applying the cap
|
|
1038
|
+
const delayForThisWait = Math.min(currentDelay, effectiveMaxDelay);
|
|
1039
|
+
|
|
1040
|
+
console.log(
|
|
1041
|
+
`Waiting ${Math.round(
|
|
1042
|
+
delayForThisWait
|
|
1043
|
+
)}ms before next attempt...`
|
|
1044
|
+
);
|
|
1045
|
+
await delay(delayForThisWait);
|
|
1046
|
+
|
|
1047
|
+
// Calculate the delay for the *next* potential wait, only if backoff is active
|
|
1048
|
+
if (backoffFactor > 1) {
|
|
1049
|
+
currentDelay = currentDelay * backoffFactor;
|
|
1050
|
+
// Note: We apply the cap just before the actual delay,
|
|
1051
|
+
// but the base 'currentDelay' keeps growing exponentially.
|
|
1052
|
+
// Alternatively, you could cap 'currentDelay' itself here:
|
|
1053
|
+
// currentDelay = Math.min(currentDelay * backoffFactor, effectiveMaxDelay);
|
|
1054
|
+
// Let's stick to capping just before delay() for now.
|
|
1055
|
+
}
|
|
1056
|
+
// If backoffFactor <= 1, currentDelay remains initialDelayMs (implicitly handled by initialization)
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
// If loop finishes without condition being met
|
|
1061
|
+
console.warn(
|
|
1062
|
+
`Readiness check failed for property "${propertyName}" on element ${
|
|
1063
|
+
element.id || ""
|
|
1064
|
+
} after ${maxAttempts} attempts.`
|
|
1065
|
+
);
|
|
1066
|
+
return false; // Timed out
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
// --- Example Usage (calling code doesn't change) ---
|
|
1070
|
+
|
|
1071
|
+
async function handleElementProcessingWithBackoff(element) {
|
|
1072
|
+
// Call the function that now supports backoff
|
|
1073
|
+
const isReady = await checkElementReadinessWithBackoff(element);
|
|
1074
|
+
|
|
1075
|
+
if (isReady) {
|
|
1076
|
+
console.log(
|
|
1077
|
+
`Element ${element.id || ""} is ready. Proceeding with actions.`
|
|
1078
|
+
);
|
|
1079
|
+
// --- Execute subsequent actions ---
|
|
1080
|
+
if (element.hasAttribute("onload-attribute")) {
|
|
1081
|
+
/* ... */
|
|
1082
|
+
}
|
|
1083
|
+
if (element.hasAttribute("onload-next")) {
|
|
1084
|
+
/* ... */
|
|
1085
|
+
}
|
|
1086
|
+
} else {
|
|
1087
|
+
console.warn(
|
|
1088
|
+
`Skipping actions for element ${
|
|
1089
|
+
element.id || ""
|
|
1090
|
+
} because readiness check failed.`
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// --- Example Elements ---
|
|
1096
|
+
|
|
1097
|
+
// With Backoff (Delays: 100, 200, 400, 800 - capped)
|
|
1098
|
+
// <span id="elem1" onload-retry-property="scrollWidth"
|
|
1099
|
+
// onload-retry-attempts="5" onload-retry-delay="100"
|
|
1100
|
+
// onload-retry-backoff-factor="2" onload-retry-max-delay="500">
|
|
1101
|
+
// Content 1
|
|
1102
|
+
// </span>
|
|
1103
|
+
// Waits would be: 100ms, 200ms, 400ms, 500ms (capped)
|
|
1104
|
+
|
|
1105
|
+
// No Backoff (factor missing/invalid/<=1)
|
|
1106
|
+
// <span id="elem2" onload-retry-property="clientHeight"
|
|
1107
|
+
// onload-retry-attempts="4" onload-retry-delay="300">
|
|
1108
|
+
// Content 2
|
|
1109
|
+
// </span>
|
|
1110
|
+
// Waits would be: 300ms, 300ms, 300ms
|
|
1111
|
+
|
|
1112
|
+
// const element1 = document.getElementById('elem1');
|
|
1113
|
+
// if (element1) handleElementProcessingWithBackoff(element1);
|
|
1114
|
+
// const element2 = document.getElementById('elem2');
|
|
1115
|
+
// if (element2) handleElementProcessingWithBackoff(element2);
|
|
1116
|
+
|
|
874
1117
|
CoCreateEvents.init();
|
|
875
1118
|
|
|
876
1119
|
export default CoCreateEvents;
|