1/** 2 * Elevent Widget Initializer 3 * 4 * Vanilla JavaScript widget initializer for maximum performance. 5 * Runs immediately without waiting for jQuery or DOM ready. 6 * Also exposes a public API (window.EleventWidgetInitializer) for 7 * re-initialization by the widget observer when DOM content changes. 8 * 9 * This script is enqueued with a dependency on the Elevent widget library, 10 * so window.elevent is guaranteed to be available when this executes. 11 * Retry logic is kept as a safety net for edge cases (e.g., deferred loading). 12 * 13 * @package Elevent 14 */ 15 16(function () { 17 "use strict"; 18 19 /** 20 * Safe performance timing function 21 * Falls back to Date.now() if Performance API is unavailable 22 * @returns {number} Milliseconds since epoch or load start 23 */ 24 function getTimestamp() { 25 if ( 26 typeof window.performance === "object" && 27 typeof window.performance.now === "function" 28 ) { 29 return window.performance.now(); 30 } 31 return Date.now(); 32 } 33 34 function isDebugEnabled() { 35 return ( 36 typeof eleventWidgetConfig !== "undefined" && eleventWidgetConfig.debug 37 ); 38 } 39 40 function pushBenchmarkLog(source, stage, data) { 41 if (!isDebugEnabled()) { 42 return; 43 } 44 45 window.EleventBenchmarkLog = window.EleventBenchmarkLog || []; 46 window.EleventBenchmarkLog.push({ 47 source: source, 48 stage: stage, 49 at: getTimestamp(), 50 isoTime: new Date().toISOString(), 51 data: data || null, 52 }); 53 } 54 55 // Performance tracking 56 var perfData = { 57 scriptStart: getTimestamp(), 58 initStart: null, 59 initEnd: null, 60 }; 61 62 /** 63 * Log performance metrics to console 64 * @param {string} message 65 * @param {object} data 66 */ 67 function logPerformance(message, data) { 68 if (isDebugEnabled()) { 69 data 70 ? console.log("[Elevent Perf] " + message, data) 71 : console.log("[Elevent Perf] " + message); 72 } 73 } 74 75 /** 76 * Log warning to console (if debug enabled) 77 * @param {string} message 78 * @param {object} data 79 */ 80 function warnPerformance(message, data) { 81 if (isDebugEnabled()) { 82 data 83 ? console.warn("[Elevent Perf] " + message, data) 84 : console.warn("[Elevent Perf] " + message); 85 } 86 } 87 88 /** 89 * Log error to console (if debug enabled) 90 * @param {string} message 91 * @param {object} data 92 */ 93 function errorPerformance(message, data) { 94 if (isDebugEnabled()) { 95 data 96 ? console.error("[Elevent Perf] " + message, data) 97 : console.error("[Elevent Perf] " + message); 98 } 99 } 100 101 /** 102 * Report performance metrics (can be extended to send to analytics) 103 */ 104 function reportMetrics() { 105 var metrics = { 106 scriptToInit: perfData.initStart - perfData.scriptStart, 107 initDuration: perfData.initEnd - perfData.initStart, 108 totalTime: perfData.initEnd - perfData.scriptStart, 109 timestamp: new Date().toISOString(), 110 }; 111 112 logPerformance("Widget initialization metrics:", metrics); 113 pushBenchmarkLog("initializer", "metrics", metrics); 114 115 // Store metrics for external access 116 window.EleventPerfMetrics = metrics; 117 118 // Fire custom event for external monitoring 119 if (typeof CustomEvent !== "undefined") { 120 document.dispatchEvent( 121 new CustomEvent("elevent:initialized", { detail: metrics }), 122 ); 123 } 124 } 125 126 /** 127 * Initialize Elevent widgets immediately 128 * @param {string} key Widget key 129 * @returns {boolean} Success status 130 */ 131 function initializeWidget(key) { 132 perfData.initStart = getTimestamp(); 133 pushBenchmarkLog("initializer", "initialize-start", { 134 hasKey: !!key, 135 keyLength: typeof key === "string" ? key.trim().length : 0, 136 eleventAvailable: typeof window.elevent !== "undefined", 137 }); 138 139 // Validate key 140 if (!key || typeof key !== "string" || key.trim().length === 0) { 141 pushBenchmarkLog("initializer", "initialize-skipped-invalid-key"); 142 warnPerformance("No valid widget key provided"); 143 return false; 144 } 145 146 // Check if Elevent library is loaded 147 if (typeof window.elevent === "undefined") { 148 pushBenchmarkLog("initializer", "initialize-deferred-library-missing");
149 logPerformance("Elevent library not yet loaded, deferring..."); 150 return false; 151 } 152 153 // Check if Initialize method exists 154 if (typeof window.elevent.Initialize !== "function") { 155 pushBenchmarkLog("initializer", "initialize-error-missing-method"); 156 errorPerformance("Elevent.Initialize is not a function"); 157 return false; 158 } 159 160 try { 161 var trimmedKey = key.trim(); 162 logPerformance("Initializing with key length: " + trimmedKey.length); 163 164 window.elevent.Initialize(trimmedKey); 165 166 perfData.initEnd = getTimestamp(); 167 pushBenchmarkLog("initializer", "initialize-success", { 168 duration: perfData.initEnd - perfData.initStart, 169 }); 170 logPerformance("Initialization successful"); 171 reportMetrics(); 172 173 // Mark as initialized for other scripts 174 window.EleventEarlyInitialized = true; 175 window.EleventWidgetKey = trimmedKey; 176 177 return true; 178 } catch (error) { 179 perfData.initEnd = getTimestamp(); 180 pushBenchmarkLog("initializer", "initialize-exception", { 181 duration: perfData.initEnd - perfData.initStart, 182 message: error && error.message ? error.message : String(error), 183 }); 184 errorPerformance("Initialization error:", error); 185 return false; 186 } 187 } 188 189 /** 190 * Attempt initialization with retry logic 191 * 192 * The Elevent widget library is declared as a script dependency, so 193 * window.elevent should always be available on the first attempt. 194 * The widget key is always inlined in the page config. 195 * Retries are a safety net for edge cases (deferred loading, caching 196 * plugins reordering scripts, etc.) and use exponential backoff. 197 */ 198 function attemptInitialization() { 199 var config = 200 typeof eleventWidgetConfig !== "undefined" ? eleventWidgetConfig : null; 201 var inlineKey = config && config.widgetKey ? config.widgetKey : null; 202 203 if (!inlineKey) { 204 pushBenchmarkLog("initializer", "attempt-missing-inline-key"); 205 errorPerformance("Widget key not localized in page config"); 206 return; 207 } 208 209 // Cache the trimmed key for use by public API and retries 210 var trimmedKey = inlineKey.trim(); 211 if (trimmedKey.length === 0) { 212 pushBenchmarkLog("initializer", "attempt-empty-inline-key"); 213 errorPerformance("Widget key not localized in page config"); 214 return; 215 } 216 217 pushBenchmarkLog("initializer", "attempt-start", { 218 keyLength: trimmedKey.length, 219 }); 220 221 window.EleventWidgetKey = trimmedKey; 222 223 // Attempt immediate initialization 224 if (initializeWidget(trimmedKey)) { 225 return; // Success â initialized immediately 226 } 227 228 // Library not yet loaded â retry with the cached key 229 retryWithKey(trimmedKey); 230 } 231 232 /** 233 * Retry initialization with exponential backoff 234 * Reuses a known key â no additional network requests. 235 * 236 * @param {string} key Widget key to retry with 237 */ 238 function retryWithKey(key) { 239 var retryCount = 0; 240 var maxRetries = 10; 241 var baseInterval = 50; // ms 242 243 var retryInit = function () { 244 retryCount++; 245 pushBenchmarkLog("initializer", "retry-attempt", { 246 retryCount: retryCount, 247 eleventAvailable: typeof window.elevent !== "undefined", 248 }); 249 250 if (typeof window.elevent !== "undefined") { 251 if (initializeWidget(key)) { 252 warnPerformance( 253 "Initialized after " + 254 retryCount + 255 " retries â check script load order", 256 ); 257 return; 258 } 259 } 260 261 if (retryCount < maxRetries) { 262 // Exponential backoff: 50, 100, 200, 400, 800, 1600, 3200, 6400, 12800ms 263 var delay = baseInterval * Math.pow(2, retryCount - 1); 264 pushBenchmarkLog("initializer", "retry-scheduled", { 265 retryCount: retryCount, 266 delay: delay, 267 }); 268 setTimeout(retryInit, delay); 269 } else { 270 pushBenchmarkLog("initializer", "retry-exhausted", { 271 maxRetries: maxRetries, 272 }); 273 errorPerformance( 274 "Max retries reached, widget initialization failed â Elevent widget script may not have loaded", 275 ); 276 } 277 }; 278
279 setTimeout(retryInit, baseInterval); 280 } 281 282 /** 283 * Public API for widget initialization 284 * 285 * Exposes methods for re-initialization (used by widget-observer.js 286 * when DOM content changes via FacetWP, AJAX, etc.) 287 */ 288 var WidgetInitializer = { 289 /** 290 * Debounce timeout for initialization calls 291 * @type {number|null} 292 */ 293 _initTimeout: null, 294 295 /** 296 * Initialize or re-initialize widgets 297 * 298 * @param {boolean} forceReinit Force re-initialization even if already initialized 299 */ 300 initialize: function (forceReinit) { 301 pushBenchmarkLog("initializer", "public-initialize", { 302 forceReinit: !!forceReinit, 303 alreadyInitialized: !!window.EleventEarlyInitialized, 304 }); 305 306 if ( 307 window.EleventEarlyInitialized && 308 window.EleventWidgetKey && 309 !forceReinit 310 ) { 311 logPerformance("Widgets already initialized, skipping redundant call"); 312 return; 313 } 314 315 // Clear any pending initialization 316 if (this._initTimeout) { 317 clearTimeout(this._initTimeout); 318 } 319 320 // Debounce initialization 321 var self = this; 322 this._initTimeout = setTimeout(function () { 323 self._doInitialize(forceReinit); 324 }, 50); 325 }, 326 327 /** 328 * Perform the actual initialization 329 * 330 * @param {boolean} forceReinit Force re-initialization 331 * @private 332 */ 333 _doInitialize: function (forceReinit) { 334 pushBenchmarkLog("initializer", "do-initialize", { 335 forceReinit: !!forceReinit, 336 eleventAvailable: typeof window.elevent !== "undefined", 337 }); 338 339 if (typeof window.elevent === "undefined") { 340 warnPerformance("Elevent widget script not loaded"); 341 return; 342 } 343 344 var key = window.EleventWidgetKey; 345 346 // Fallback to eleventWidgetConfig if key not yet cached 347 // (can happen during retry window before initializeWidget succeeds) 348 if (!key) { 349 var config = 350 typeof eleventWidgetConfig !== "undefined" 351 ? eleventWidgetConfig 352 : null; 353 key = config && config.widgetKey ? config.widgetKey : null; 354 } 355 356 if (key) { 357 this._initializeWithKey(key, forceReinit); 358 return; 359 } 360 361 // No key available 362 warnPerformance("No widget key available for initialization"); 363 }, 364 365 /** 366 * Initialize with a specific key 367 * 368 * @param {string} key Widget key 369 * @param {boolean} forceReinit Force re-initialization 370 * @private 371 */ 372 _initializeWithKey: function (key, forceReinit) { 373 if (!key) { 374 warnPerformance("No widget key provided"); 375 return; 376 } 377 378 if (typeof key !== "string" || key.trim().length === 0) { 379 errorPerformance("Invalid widget key format:", typeof key); 380 return; 381 } 382 383 if (typeof window.elevent === "undefined") { 384 warnPerformance("Elevent library not available for initialization"); 385 return; 386 } 387 388 if (typeof window.elevent.Initialize !== "function") { 389 errorPerformance("Elevent.Initialize is not a function"); 390 return; 391 } 392 393 if ( 394 window.EleventEarlyInitialized && 395 window.EleventWidgetKey === key && 396 !forceReinit 397 ) { 398 logPerformance("Elevent widgets already initialized with this key"); 399 return; 400 } 401 402 try { 403 var trimmedKey = key.trim(); 404 405 logPerformance( 406 forceReinit 407 ? "Re-initializing Elevent widgets (DOM updated)" 408 : "Initializing Elevent widgets", 409 ); 410 411 window.elevent.Initialize(trimmedKey); 412 window.EleventEarlyInitialized = true; 413 window.EleventWidgetKey = trimmedKey; 414 415 logPerformance("Initialization complete", { 416 reinit: !!forceReinit, 417 }); 418 } catch (error) { 419 window.EleventEarlyInitialized = false; 420 errorPerformance("Error initializing Elevent widgets:", error); 421 } 422 }, 423 424 /** 425 * Get the current widget key 426 * 427 * @return {string|null} Widget key or null 428 */ 429 getWidgetKey: function () { 430 return window.EleventWidgetKey || null; 431 }, 432 433 /** 434 * Check if widgets have been initialized 435 * 436 * @return {boolean} True if initialized 437 */ 438 isInitialized: function () { 439 return !!window.EleventEarlyInitialized; 440 }, 441 }; 442 443 // Export public API 444 window.EleventWidgetInitializer = WidgetInitializer; 445 446 // Execute immediately 447 attemptInitialization(); 448})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.