@@ -405,7 +405,26 @@ const CoCreateEvents = {
405405 }
406406
407407 for ( let element of elements ) {
408- let delay = element . getAttribute ( `${ prefix } -delay` ) ;
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` ) ;
409428
410429 if ( delay ) {
411430 delay = parseInt ( delay , 10 ) || 0 ;
@@ -941,6 +960,160 @@ function parseNumberCondition(condition) {
941960 : condition ;
942961}
943962
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+
9441117CoCreateEvents . init ( ) ;
9451118
9461119export default CoCreateEvents ;
0 commit comments