| @@ -99,8 +99,12 @@ | ||
| 99 | 99 | started = true; |
| 100 | 100 | TRIGGERS.forEach(function (name) { |
| 101 | 101 | window.removeEventListener(name, start, { passive: true, capture: true }); |
| 102 | 102 | }); |
| 103 | + // Marks the start, before any delayed script is put back. The Elementor | |
| 104 | + // entrance-animation reveal listens for it to settle the widgets the | |
| 105 | + // visitor has already seen. | |
| 106 | + document.dispatchEvent(new Event('xspeed:replaying')); | |
| 103 | 107 | var nav = window.performance && performance.getEntriesByType && performance.getEntriesByType('navigation')[0]; |
| 104 | 108 | if (nav && nav.domContentLoadedEventStart > 0) dclFired = true; |
| 105 | 109 | |
| 106 | 110 | // pageLoaded: the replay starts after load, the usual case ("late"). |
| @@ -216,8 +220,48 @@ | ||
| 216 | 220 | var currentOnload = pageOnload; |
| 217 | 221 | var currentRsc = pageRsc; |
| 218 | 222 | var jq = window.jQuery; |
| 219 | 223 | var ended; |
| 224 | + | |
| 225 | + // jQuery ready. When jQuery ran before the replay and is already ready, | |
| 226 | + // jQuery(fn) and $(document).ready(fn) run fn on the next timer, which | |
| 227 | + // can come before a later delayed script has arrived. On a real page | |
| 228 | + // ready waits for DOMContentLoaded, so every deferred script has run | |
| 229 | + // first. Elementor's frontend calls init from ready, and Elementor Pro, a | |
| 230 | + // later script, listens for the event init sends: run early, Pro missed | |
| 231 | + // it and its sticky header and motion effects never started. So while | |
| 232 | + // the replay runs, ready only queues, and the queue goes to jQuery's own | |
| 233 | + // ready with the synthetic DOMContentLoaded. jQuery(fn) goes through | |
| 234 | + // jQuery.fn.ready, so one wrapper covers both forms. | |
| 235 | + var heldReady = []; | |
| 236 | + var pageReady; | |
| 237 | + var ourReady; | |
| 238 | + try { | |
| 239 | + if (jq && jq.fn && jq.isReady && jq.fn.ready) { | |
| 240 | + pageReady = jq.fn.ready; | |
| 241 | + ourReady = jq.fn.ready = function (fn) { | |
| 242 | + // Only while the queue is open: once released, a call that still | |
| 243 | + // reaches us (through a wrapper put on top) goes straight through. | |
| 244 | + if (ourReady) { | |
| 245 | + heldReady.push(fn); | |
| 246 | + return this; | |
| 247 | + } | |
| 248 | + return pageReady.apply(this, arguments); | |
| 249 | + }; | |
| 250 | + } | |
| 251 | + } catch (e) {} | |
| 252 | + // Puts jQuery's ready back (unless something wrapped it after us) and | |
| 253 | + // hands it the queue, in order. jQuery runs each on a timer, as usual, | |
| 254 | + // and catches what they throw, so this call itself does not throw. | |
| 255 | + function releaseReady() { | |
| 256 | + if (!ourReady) return; | |
| 257 | + if (jq.fn.ready === ourReady) jq.fn.ready = pageReady; | |
| 258 | + ourReady = 0; | |
| 259 | + heldReady.forEach(function (fn) { | |
| 260 | + pageReady.call(jq(document), fn); | |
| 261 | + }); | |
| 262 | + heldReady = []; | |
| 263 | + } | |
| 220 | 264 | if (pageLoaded && pageOnload) currentOnload = window.onload = function () {}; |
| 221 | 265 | if (pageLoaded && pageRsc) currentRsc = document.onreadystatechange = function () {}; |
| 222 | 266 | |
| 223 | 267 | // The replayed scripts read a fake document.readyState: 'loading' while |
| @@ -373,8 +417,9 @@ | ||
| 373 | 417 | fakeDepth++; |
| 374 | 418 | fireReadyStateChange(); |
| 375 | 419 | } |
| 376 | 420 | firePrivate(document, 'DOMContentLoaded', 1); |
| 421 | + releaseReady(); | |
| 377 | 422 | if (faking) fakeDepth--; |
| 378 | 423 | if (pageLoaded && !faking) fireReadyStateChange(); |
| 379 | 424 | pending = 1; |
| 380 | 425 | var $ = window.jQuery; |
| @@ -402,8 +447,9 @@ | ||
| 402 | 447 | // since been put on top; `live` makes ours inert either way. |
| 403 | 448 | function finish() { |
| 404 | 449 | if (ended) return; |
| 405 | 450 | ended = 1; |
| 451 | + releaseReady(); | |
| 406 | 452 | if (observer) observer.disconnect(); |
| 407 | 453 | if (faking) { |
| 408 | 454 | if (ownReadyState) Object.defineProperty(document, 'readyState', ownReadyState); |
| 409 | 455 | else delete document.readyState; |