PageSourceSearch

https://hotelparkdoha.com/wp-content/plugins/simple-cloudflare-tur…/js/integrations/elementor-forms.js?ver=3.0

js hotelparkdoha.com collected 2026-09-24 12:35:38 UTC 25,346 bytes, 590 lines download raw bytes

1// Elementor 4 "Atomic" forms are elements rather than widgets, so they carry no .elementor-form class.
2var CFT_ATOMIC_FORM_SELECTOR = 'form[data-element_type="e-form"]';
3var CFT_ATOMIC_AJAX_ACTION = 'elementor_pro_atomic_forms_send_form';
4
5function cfturnstile_elementor_set_submit(btn, enabled) {
6  if (!btn) return;
7  btn.style.pointerEvents = enabled ? 'auto' : 'none';
8  btn.style.opacity     = enabled ? '1'    : '0.5';
9}
10
11/**
12 * Current Turnstile token for a form, whichever way it is available.
13 */
14function cfturnstile_elementor_token(form) {
15  var widget = form ? form.querySelector('.cf-turnstile') : null;
16  if (!widget) return '';
17  var token = '';
18  if (window.turnstile) {
19    try { token = turnstile.getResponse(widget) || ''; } catch (e) {}
20  }
21  if (!token) {
22    var responseInput = form.querySelector('[name="cf-turnstile-response"]');
23    token = responseInput ? (responseInput.value || '') : '';
24  }
25  return token;
26}
27
28/**
29 * A form belonging to a popup document that has not been moved into a modal yet.
30 *
31 * Elementor Pro caches a popup's markup as an HTML string in its handler's onInit(), then rebuilds
32 * the popup from that string on every open. Anything rendered into the form while it is still
33 * inline gets baked into the cache as dead markup, so these forms are left to the popup/show
34 * handler below.
35 */
36function cfturnstile_elementor_is_unshown_popup(form) {
37  if (!form || !form.closest) return false;
38  return !!form.closest('[data-elementor-type="popup"]') && !form.closest('.elementor-popup-modal');
39}
40
41/**
42 * True when this container is backed by a widget Turnstile still knows about.
43 *
44 * A container rebuilt from Elementor's popup cache carries markup copied from an earlier render
45 * that is no longer a live widget. turnstile.remove() only warns and returns on such a container
46 * (it does not throw, so try/catch does not detect it) while turnstile.render() appends alongside
47 * the copy - which is how a popup ends up with two widgets and two response inputs. getResponse()
48 * does throw for an unknown container, so it is the reliable probe.
49 */
50function cfturnstile_elementor_widget_is_live(widget) {
51  if (!widget || !window.turnstile) return false;
52  try {
53    turnstile.getResponse(widget);
54    return true;
55  } catch (e) {
56    return false;
57  }
58}
59
60function cfturnstile_init_elementor_forms() {
61  var settings = window.cfturnstileElementorSettings || {};
62  var sitekey = settings.sitekey || '';
63  var position = settings.position || 'before';
64  var mode = settings.mode || 'turnstile';
65  var recaptchaSiteKey = settings.recaptchaSiteKey || '';
66  var disableSubmit = settings.disableSubmit || false;
67  var widgetSize = settings.size || 'normal';
68  
69  if (!window._cft_elementor_idx) { window._cft_elementor_idx = 0; }
70  var elementorForms = document.querySelectorAll('.elementor-form:not(.cft-processed)');
71  elementorForms.forEach(function(form) {
72    if (cfturnstile_elementor_is_unshown_popup(form)) { return; }
73
74    var index = window._cft_elementor_idx++;
75    if (form.querySelector('.cf-turnstile') || form.querySelector('.g-recaptcha') || form.querySelector('input[name="cfturnstile_failsafe"]')) {
76      form.classList.add('cft-processed');
77      return;
78    }
79    
80    var submitButton = form.querySelector('button[type="submit"]');
81
82    // Failsafe modes: inject marker and optionally reCAPTCHA widget.
83    if (submitButton && (mode === 'allow' || mode === 'recaptcha')) {
84      var marker = document.createElement('input');
85      marker.type = 'hidden';
86      marker.name = 'cfturnstile_failsafe';
87      marker.value = mode;
88      form.appendChild(marker);
89
90      if (mode === 'recaptcha' && recaptchaSiteKey) {
91        var recaptchaDiv = document.createElement('div');
92        recaptchaDiv.className = 'g-recaptcha';
93        recaptchaDiv.setAttribute('data-sitekey', recaptchaSiteKey);
94        recaptchaDiv.style.cssText = 'display: block; margin: 10px 0 15px 0; width: 100%;';
95
96        if (position === 'after') {
97          submitButton.parentNode.insertBefore(recaptchaDiv, submitButton.nextSibling);
98        } else if (position === 'afterform') {
99          form.appendChild(recaptchaDiv);
100        } else {
101          submitButton.parentNode.insertBefore(recaptchaDiv, submitButton);
102        }
103      }
104
105      form.classList.add('cft-processed');
106      return;
107    }
108
109    if (submitButton && window.turnstile && sitekey) {
110      // Disable submit button if option is enabled
111      if (disableSubmit) {
112        cfturnstile_elementor_set_submit(submitButton, false);
113      }
114
115      var labelEl = null;
116      if (settings.labelEnable && settings.labelText) {
117        labelEl = document.createElement('p');
118        labelEl.className = 'cfturnstile-widget-label';
119        labelEl.style.cssText = 'font-size: 14px; margin: 0 0 6px 0; width: 100%;';
120        if ((settings.appearance || 'always') === 'interaction-only') {
121          labelEl.className += ' cfturnstile-widget-label-interaction';
122          labelEl.style.display = 'none';
123        }
124        var smallEl = document.createElement('small');
125        smallEl.textContent = settings.labelText;
126        labelEl.appendChild(smallEl);
127      }
128
129      var turnstileDiv = document.createElement('div');
130      turnstileDiv.className = 'elementor-turnstile-field cf-turnstile';
131      turnstileDiv.id = 'cf-turnstile-elementor-fallback-' + index;
132      turnstileDiv.style.cssText = 'display: block; margin: 10px 0 15px 0; width: 100%;';
133
134      if (position === 'after') {
135        if (labelEl) submitButton.parentNode.insertBefore(labelEl, submitButton.nextSibling);
136        submitButton.parentNode.insertBefore(turnstileDiv, labelEl ? labelEl.nextSibling : submitButton.nextSibling);
137      } else if (position === 'afterform') {
138        if (labelEl) form.appendChild(labelEl);
139        form.appendChild(turnstileDiv);
140      } else {
141        if (labelEl) submitButton.parentNode.insertBefore(labelEl, submitButton);
142        submitButton.parentNode.insertBefore(turnstileDiv, submitButton);
143      }
144      
145      turnstile.render('#cf-turnstile-elementor-fallback-' + index, {
146        sitekey: sitekey,
147        theme: settings.theme || 'auto',
148        size: widgetSize,
149        appearance: settings.appearance || 'always',
150        callback: function(token) {
151          // Re-enable submit button when Turnstile is complete
152          if (disableSubmit && submitButton) {
153            cfturnstile_elementor_set_submit(submitButton, true);
154          }
155          if (typeof turnstileElementorCallback === 'function') {
156            turnstileElementorCallback(token);
157          }
158        },
159        'error-callback': function() {
160          if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, false); }
161        },
162        'expired-callback': function() {
163          if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, false); }
164        }
165      });
166
167      if (labelEl && labelEl.classList.contains('cfturnstile-widget-label-interaction') && typeof window.cfturnstileInitInteractionLabels === 'function') {
168        window.cfturnstileInitInteractionLabels();
169      }
170
171      form.classList.add('cft-processed');
172    }
173  });
174}
175
176document.addEventListener('DOMContentLoaded', function() {
177  cfturnstile_init_elementor_forms();
178});
179
180// Listen to Elementor frontend init to handle cached elements
181jQuery(window).on('elementor/frontend/init', function() {
182  cfturnstile_init_elementor_forms();
183
184  // Hook into Elementor's widget ready system for forms loaded dynamically (e.g. in popups)
185  if (window.elementorFrontend && elementorFrontend.hooks) {
186    elementorFrontend.hooks.addAction('frontend/element_ready/form.default', function($scope) {
187      cfturnstile_init_elementor_forms();
188    });
189    elementorFrontend.hooks.addAction('frontend/element_ready/login.default', function($scope) {
190      cfturnstile_init_elementor_forms();
191    });
192  }
193});
194
195// Re-render Turnstile only after Elementor reports a submit error (e.g. failed validation)
196function cfturnstile_elementor_rerender(form) {
197  if (!form || !window.turnstile) return;
198  var settings = window.cfturnstileElementorSettings || {};
199  var widget = form.querySelector('.cf-turnstile');
200  if (!widget) return;
201  var submitButton = form.querySelector('button[type="submit"]');
202  var disableSubmit = settings.disableSubmit || false;
203  if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, false); }
204  try { turnstile.remove(widget); } catch (e) {}
205  turnstile.render(widget, {
206    sitekey: settings.sitekey,
207    theme: settings.theme || 'auto',
208    size: settings.size || 'normal',
209    appearance: settings.appearance || 'always',
210    callback: function(token) {
211      if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, true); }
212      if (typeof turnstileElementorCallback === 'function') {
213        turnstileElementorCallback(token);
214      }
215    },
216    'error-callback': function() {
217      if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, false); }
218    },
219    'expired-callback': function() {
220      if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, false); }
221    }
222  });
223}
224
225jQuery(document).on('submit_error submit_success', '.elementor-form', function() {
226  var settings = window.cfturnstileElementorSettings || {};
227  if ((settings.mode || 'turnstile') !== 'turnstile') return;
228  cfturnstile_elementor_rerender(this);
229});
230
231// Block submission until Turnstile is completed (client-side guard).
232// Server-side validation in cfturnstile_elementor_check is the source of truth;
233// this just avoids a wasted round-trip and gives immediate feedback.
234document.addEventListener('submit', function(event) {
235  var form = event.target;
236  if (!form.classList) return;
237  var isClassic = form.classList.contains('elementor-form');
238  var isAtomic = !isClassic && form.matches && form.matches(CFT_ATOMIC_FORM_SELECTOR);
239  if (!isClassic && !isAtomic) return;
240  var settings = window.cfturnstileElementorSettings || {};
241  if ((settings.mode || 'turnstile') !== 'turnstile' || !window.turnstile) return;
242
243  var widget = form.querySelector('.cf-turnstile');
244  if (!widget) return;
245  if (!cfturnstile_elementor_token(form)) {
246    event.preventDefault();
247    event.stopImmediatePropagation();
248    try { widget.scrollIntoView({ behavior: 'smooth', block: 'center' }); } catch (e) {}
249  }
250}, true);
251
252// Handle Elementor popup show events (jQuery event - must use jQuery to listen)
253jQuery(document).on('elementor/popup/show', function(event, id, instance) {
254  setTimeout(function() {
255    // First, inject Turnstile into any unprocessed forms inside the popup
256    cfturnstile_init_elementor_forms();
257
258    var settings = window.cfturnstileElementorSettings || {};
259    var mode = settings.mode || 'turnstile';
260    var disableSubmit = settings.disableSubmit || false;
261    if (mode !== 'turnstile' || !window.turnstile) {
262      return;
263    }
264
265    // Re-render all Turnstile widgets inside popup modals (they need explicit render after DOM insertion)
266    var popupTurnstiles = document.querySelectorAll('.elementor-popup-modal .cf-turnstile');
267    popupTurnstiles.forEach(function(widget) {
268      var failedText = widget.parentNode ? widget.parentNode.querySelector('.cf-turnstile-failed-text') : null;
269      if (failedText) {
270        failedText.style.display = 'none';
271      }
272
273      // Find the form and submit button for this widget
274      var form = widget.closest('.elementor-form');
275      var submitButton = form ? form.querySelector('button[type="submit"]') : null;
276
277      // A widget Turnstile still owns is already rendered, and may hold a solved token that
278      // re-rendering would throw away.
279      if (cfturnstile_elementor_widget_is_live(widget)) {
280        if (disableSubmit && submitButton) {
281          cfturnstile_elementor_set_submit(submitButton, !!cfturnstile_elementor_token(form));
282        }
283        return;
284      }
285
286      // Disable submit button if option is enabled
287      if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, false); }
288
289      // Orphan markup rebuilt from Elementor's popup cache: clear it, or render() appends a second
290      // widget and the form posts two cf-turnstile-response inputs - the first one already spent.
291      try { turnstile.remove(widget); } catch (e) {}
292      widget.innerHTML = '';
293
294      turnstile.render(widget, {
295        sitekey: cfturnstileElementorSettings.sitekey,
296        appearance: cfturnstileElementorSettings.appearance || 'always',
297        callback: function(token) {
298          // Re-enable submit button when Turnstile is complete
299          if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, true); }
300          if (typeof turnstileElementorCallback === 'function') {
301            turnstileElementorCallback(token);
302          }
303        },
304        'error-callback': function() {
305          if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, false); }
306        },
307        'expired-callback': function() {
308          if (disableSubmit && submitButton) { cfturnstile_elementor_set_submit(submitButton, false); }
309        },
310        theme: cfturnstileElementorSettings.theme || 'auto',
311        size: cfturnstileElementorSettings.size || 'normal'
312      });
313    });
314  }, 500);
315});
316
317// Release the widgets of a popup that is closing. Elementor throws the popup DOM away and rebuilds
318// it from its cached string on the next open, so without this the widgets stay registered against
319// detached nodes for the rest of the page life. Deferred so the widget does not blink out of the
320// popup mid exit-animation - removing a detached container works just as well.
321jQuery(document).on('elementor/popup/hide', function(event, id) {
322  var modal = document.getElementById('elementor-popup-modal-' + id);
323  if (!modal || !window.turnstile) return;
324  var widgets = Array.prototype.slice.call(modal.querySelectorAll('.cf-turnstile'));
325  if (!widgets.length) return;
326  setTimeout(function() {
327    widgets.forEach(function(widget) {
328      try { turnstile.remove(widget); } catch (e) {}
329    });
330  }, 1000);
331});
332
333/* ---------------------------------------------------------------------------
334 * Elementor Atomic Forms (Elementor 4 "e-form" elements)
335 *
336 * Atomic forms are submitted by an Alpine handler bound to the form, which posts
337 * a FormData payload built only from the field widgets Elementor itself rendered
338 * (input/textarea/select carrying data-interaction-id). A hidden token input
339 * sitting inside the form is therefore never sent, so the token is appended to
340 * the outgoing request instead - see cfturnstile_atomic_patch_fetch() below.
341 * ------------------------------------------------------------------------ */
342
343function cfturnstile_atomic_submit_button(form) {
344  return form ? form.querySelector('button[type="submit"], input[type="submit"]') : null;
345}
346
347/**
348 * Horizontal alignment of the widget inside its (column flex) wrapper.
349 */
350function cfturnstile_atomic_align(align) {
351  if (align === 'center') return 'center';
352  if (align === 'right') return 'flex-end';
353  return 'flex-start';
354}
355
356/**
357 * Place a node according to the configured widget position. Atomic forms are flex
358 * containers, so the node is inserted as a full width row of its own.
359 */
360function cfturnstile_atomic_insert(form, node, position, submitButton) {
361  if (position === 'afterform' || !submitButton || !submitButton.parentNode) {
362    form.appendChild(node);
363  } else if (position === 'after') {
364    submitButton.parentNode.insertBefore(node, submitButton.nextSibling);
365  } else {
366    submitButton.parentNode.insertBefore(node, submitButton);
367  }
368}
369
370function cfturnstile_atomic_render_options(form) {
371  var settings = window.cfturnstileElementorSettings || {};
372  var disableSubmit = settings.disableSubmit || false;
373  var submitButton = cfturnstile_atomic_submit_button(form);
374  return {
375    sitekey: settings.sitekey,
376    theme: settings.theme || 'auto',
377    size: settings.size || 'normal',
378    appearance: settings.appearance || 'always',
379    action: 'elementor-atomic-form',
380    callback: function(token) {
381      if (disableSubmit) { cfturnstile_elementor_set_submit(submitButton, true); }
382      if (typeof turnstileElementorCallback === 'function') {
383        turnstileElementorCallback(token);
384      }
385    },
386    'error-callback': function() {
387      if (disableSubmit) { cfturnstile_elementor_set_submit(submitButton, false); }
388    },
389    'expired-callback': function() {
390      if (disableSubmit) { cfturnstile_elementor_set_submit(submitButton, false); }
391    }
392  };
393}
394
395function cfturnstile_init_elementor_atomic_forms() {
396  var settings = window.cfturnstileElementorSettings || {};
397  var sitekey = settings.sitekey || '';
398  var position = settings.position || 'before';
399  var mode = settings.mode || 'turnstile';
400  var recaptchaSiteKey = settings.recaptchaSiteKey || '';
401  var disableSubmit = settings.disableSubmit || false;
402
403  if (!window._cft_atomic_idx) { window._cft_atomic_idx = 0; }
404
405  // Elementor re-renders form elements in place (editor edits, popups, Alpine refreshes),
406  // which drops the injected widget. Release those forms so they are processed again.
407  document.querySelectorAll(CFT_ATOMIC_FORM_SELECTOR + '.cft-processed').forEach(function(form) {
408    if (!form.querySelector('.cf-turnstile, .g-recaptcha, input[name="cfturnstile_failsafe"]')) {
409      form.classList.remove('cft-processed');
410    }
411  });
412
413  document.querySelectorAll(CFT_ATOMIC_FORM_SELECTOR + ':not(.cft-processed)').forEach(function(form) {
414    // Same popup caching trap as the classic forms above - wait until the popup is actually shown,
415    // at which point the observer below picks the form up with its atomic render options intact.
416    if (cfturnstile_elementor_is_unshown_popup(form)) { return; }
417
418    if (form.querySelector('.cf-turnstile, .g-recaptcha, input[name="cfturnstile_failsafe"]')) {
419      form.classList.add('cft-processed');
420      return;
421    }
422
423    var submitButton = cfturnstile_atomic_submit_button(form);
424
425    // Failsafe modes: post a marker, and render reCAPTCHA in its place if configured.
426    if (mode === 'allow' || mode === 'recaptcha') {
427      var marker = document.createElement('input');
428      marker.type = 'hidden';
429      marker.name = 'cfturnstile_failsafe';
430      marker.value = mode;
431      form.appendChild(marker);
432
433      if (mode === 'recaptcha' && recaptchaSiteKey) {
434        var recaptchaWrap = document.createElement('div');
435        recaptchaWrap.className = 'cfturnstile-atomic-field';
436        recaptchaWrap.style.cssText = 'display: flex; flex-direction: column; align-items: ' + cfturnstile_atomic_align(settings.align) + '; flex: 0 0 100%; width: 100%; margin: 10px 0 15px 0;';
437        var recaptchaDiv = document.createElement('div');
438        recaptchaDiv.className = 'g-recaptcha';
439        recaptchaDiv.setAttribute('data-sitekey', recaptchaSiteKey);
440        recaptchaWrap.appendChild(recaptchaDiv);
441        cfturnstile_atomic_insert(form, recaptchaWrap, position, submitButton);
442      }
443
444      form.classList.add('cft-processed');
445      return;
446    }
447
448    // The submit button is rendered as a child widget, so it can still be missing on an
449    // early pass. Wait for the next pass rather than injecting into a half built form.
450    if (!submitButton || !window.turnstile || !sitekey) return;
451
452    if (disableSubmit) {
453      cfturnstile_elementor_set_submit(submitButton, false);
454    }
455
456    var index = window._cft_atomic_idx++;
457
458    var wrap = document.createElement('div');
459    wrap.className = 'cfturnstile-atomic-field';
460    wrap.style.cssText = 'display: flex; flex-direction: column; align-items: ' + cfturnstile_atomic_align(settings.align) + '; flex: 0 0 100%; width: 100%; margin: 10px 0 15px 0;';
461
462    if (settings.labelEnable && settings.labelText) {
463      var labelEl = document.createElement('p');
464      labelEl.className = 'cfturnstile-widget-label';
465      labelEl.style.cssText = 'font-size: 14px; margin: 0 0 6px 0;';
466      if ((settings.appearance || 'always') === 'interaction-only') {
467        labelEl.className += ' cfturnstile-widget-label-interaction';
468        labelEl.style.display = 'none';
469      }
470      var smallEl = document.createElement('small');
471      smallEl.textContent = settings.labelText;
472      labelEl.appendChild(smallEl);
473      wrap.appendChild(labelEl);
474    }
475
476    var turnstileDiv = document.createElement('div');
477    turnstileDiv.className = 'elementor-turnstile-field cf-turnstile';
478    turnstileDiv.id = 'cf-turnstile-elementor-atomic-' + index;
479    wrap.appendChild(turnstileDiv);
480
481    cfturnstile_atomic_insert(form, wrap, position, submitButton);
482
483    turnstile.render(turnstileDiv, cfturnstile_atomic_render_options(form));
484
485    if (settings.labelEnable && (settings.appearance || 'always') === 'interaction-only' && typeof window.cfturnstileInitInteractionLabels === 'function') {
486      window.cfturnstileInitInteractionLabels();
487    }
488
489    form.classList.add('cft-processed');
490  });
491}
492
493/**
494 * Reset a widget after its form has been submitted, so a retry gets a fresh token.
495 * Elementor calls form.reset() on success, which empties the token input while the
496 * widget still holds the spent token - the global refresh helper cannot detect that.
497 */
498function cfturnstile_atomic_reset(form) {
499  if (!form || !window.turnstile) return;
500  var widget = form.querySelector('.cf-turnstile');
501  if (!widget) return;
502  var settings = window.cfturnstileElementorSettings || {};
503  if (settings.disableSubmit) {
504    cfturnstile_elementor_set_submit(cfturnstile_atomic_submit_button(form), false);
505  }
506  try { turnstile.reset(widget); } catch (e) {}
507}
508
509/**
510 * Attach the token to the atomic form request.
511 *
512 * Elementor builds the FormData itself and only includes its own field widgets, so
513 * there is no markup based way to get the token to the server. The wrapper only
514 * touches requests carrying the atomic form action and leaves everything else alone.
515 */
516function cfturnstile_atomic_patch_fetch() {
517  if (window._cfturnstileAtomicFetchPatched) return;
518  var originalFetch = window.fetch;
519  if (typeof originalFetch !== 'function') return;
520  window._cfturnstileAtomicFetchPatched = true;
521
522  window.fetch = function(input, init) {
523    var form = null;
524    try {
525      var body = init && init.body;
526      if (body instanceof FormData && body.get('action') === CFT_ATOMIC_AJAX_ACTION) {
527        var formId = body.get('form_id');
528        if (formId && /^[A-Za-z0-9_-]+$/.test(formId)) {
529          form = document.querySelector(CFT_ATOMIC_FORM_SELECTOR + '[data-id="' + formId + '"]');
530        }
531        if (form) {
532          var token = cfturnstile_elementor_token(form);
533          if (token) {
534            body.set('cf-turnstile-response', token);
535          }
536          var failsafe = form.querySelector('input[name="cfturnstile_failsafe"]');
537          if (failsafe && failsafe.value) {
538            body.set('cfturnstile_failsafe', failsafe.value);
539          }
540          var recaptcha = form.querySelector('textarea[name="g-recaptcha-response"], input[name="g-recaptcha-response"]');
541          if (recaptcha && recaptcha.value) {
542            body.set('g-recaptcha-response', recaptcha.value);
543          }
544        }
545      }
546    } catch (e) {}
547
548    // Callers reaching fetch from strict mode code (bundles, ES modules) invoke it bare, so
549    // `this` arrives undefined. Current Chrome tolerates that, but engines that hold fetch to
550    // its WebIDL receiver throw "Illegal invocation" - fall back to the global rather than
551    // making that a property of whether this plugin happens to be active.
552    var request = originalFetch.apply(this || window, arguments);
553
554    if (form) {
555      var reset = function() {
556        // Let Elementor apply its own result handling (including form.reset()) first.
557        setTimeout(function() { cfturnstile_atomic_reset(form); }, 500);
558      };
559      request.then(reset, reset);
560    }
561
562    return request;
563  };
564}
565
566(function() {
567  cfturnstile_atomic_patch_fetch();
568
569  var scheduled = null;
570  function schedule() {
571    if (scheduled) return;
572    scheduled = setTimeout(function() {
573      scheduled = null;
574      cfturnstile_init_elementor_atomic_forms();
575    }, 100);
576  }
577
578  if (document.readyState === 'loading') {
579    document.addEventListener('DOMContentLoaded', schedule);
580  } else {
581    schedule();
582  }
583
584  // Atomic forms are mounted by Elementor's own handler system and can appear or be
585  // re-rendered at any point (popups, editor edits, lazy loaded content), so watch the
586  // document rather than hooking into a specific lifecycle event.
587  if (window.MutationObserver) {
588    new MutationObserver(schedule).observe(document.documentElement, { childList: true, subtree: true });
589  }
590})();

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.