1/** 2 * Shared full-page preparing overlay (checkout, quote edit, sign-in, search, etc.). 3 * Fail-open: missing DOM is created on demand. navigate() always shows this 4 * overlay â it no longer defers to WizSkeletons for skeleton routes. 5 */ 6(function (global) { 7 'use strict'; 8 9 // This file can be printed into an AJAX fragment (WizVariantSwitcher/render.php, 10 // WizQuoteDiscard, WizQuoteResubmit, WizQuoteEndStatusCta) and re-executed when 11 // jQuery .html() inserts the response. Keep the first instance so module state 12 // and the pageshow listener are not duplicated. 13 if (global.WizPreparingOverlay && global.WizPreparingOverlay.__wizOverlayInit) { 14 return; 15 } 16 17 const DEFAULT_ID = 'wiz-preparing-overlay'; 18 const LEGACY_ID = 'wiz-quote-preparing-checkout'; 19 const DEFAULT_LABEL = 'Proceeding to checkout...'; 20 const DEFAULT_NAV_LABEL = 'Loading...'; 21 const ALL_SELECTOR = '#' + DEFAULT_ID + ', #' + LEGACY_ID + ', .wiz-preparing, .wiz-quote-preparing'; 22 let previousOverflow = null; 23 /** 24 * The node show() last opened. More than one widget on a page renders its 25 * own overlay markup (e.g. the header's WizQuoteResubmit plus the page's 26 * own widget), so the document can hold several #wiz-preparing-overlay 27 * elements. getElementById returns whichever comes first in document 28 * order â and show() moves its node to the end of <body>, which flips that 29 * order. Without this handle hide() resolved a *different* node and left 30 * the visible overlay open, freezing the page behind a click-eating 31 * backdrop. 32 */ 33 let activeEl = null; 34 35 function allEls() { 36 return Array.prototype.slice.call(document.querySelectorAll(ALL_SELECTOR)); 37 } 38 39 function getEl() { 40 if (activeEl && activeEl.isConnected) { 41 return activeEl; 42 } 43 const els = allEls(); 44 if (!els.length) { 45 return null; 46 } 47 // Prefer one already open, so a stray second copy never shadows it. 48 for (let i = 0; i < els.length; i += 1) { 49 if (els[i].classList.contains('is-open')) { 50 return els[i]; 51 } 52 } 53 return els[0]; 54 } 55 56 function ensureEl() { 57 let el = getEl(); 58 if (el) { 59 return el; 60 } 61 if (!document.body) { 62 return null; 63 } 64 el = document.createElement('div'); 65 el.id = DEFAULT_ID; 66 el.className = 'wiz-preparing'; 67 el.hidden = true; 68 el.setAttribute('aria-hidden', 'true'); 69 70 const backdrop = document.createElement('div'); 71 backdrop.className = 'wiz-preparing__backdrop'; 72 backdrop.setAttribute('aria-hidden', 'true'); 73 74 const toast = document.createElement('div'); 75 toast.className = 'wiz-preparing__toast'; 76 toast.setAttribute('role', 'status'); 77 toast.setAttribute('aria-live', 'polite'); 78 79 const spinner = document.createElement('span'); 80 spinner.className = 'wiz-preparing__spinner'; 81 spinner.setAttribute('aria-hidden', 'true'); 82 83 const textEl = document.createElement('span'); 84 textEl.className = 'wiz-preparing__text'; 85 textEl.textContent = DEFAULT_NAV_LABEL; 86 87 toast.appendChild(spinner); 88 toast.appendChild(textEl); 89 el.appendChild(backdrop); 90 el.appendChild(toast); 91 document.body.appendChild(el); 92 return el; 93 } 94 95 function portalToBody(el) { 96 if (!el || el.parentNode === document.body) { 97 return; 98 } 99 document.body.appendChild(el); 100 } 101 102 function show(label) { 103 const el = ensureEl(); 104 if (!el) { 105 return false; 106 } 107 if (typeof label === 'string' && label.trim()) { 108 const textEl = el.querySelector('.wiz-preparing__text, .wiz-quote-preparing__text'); 109 if (textEl) { 110 textEl.textContent = label.trim(); 111 } 112 } 113 portalToBody(el); 114 activeEl = el; 115 el.hidden = false; 116 el.setAttribute('aria-hidden', 'false'); 117 el.classList.add('is-open'); 118 if (previousOverflow === null) { 119 previousOverflow = document.body.style.overflow; 120 } 121 document.body.style.overflow = 'hidden'; 122 return true; 123 } 124 125 function hide() { 126 // Close every copy, not just the one getEl() resolves to â a duplicate 127 // left open is nearly invisible (translucent backdrop) but eats clicks.
128 allEls().forEach(function (el) { 129 el.classList.remove('is-open'); 130 el.hidden = true; 131 el.setAttribute('aria-hidden', 'true'); 132 }); 133 activeEl = null; 134 if (previousOverflow !== null) { 135 document.body.style.overflow = previousOverflow; 136 previousOverflow = null; 137 } 138 } 139 140 function navigate(url, label) { 141 const next = (url || '').toString().trim(); 142 if (!next) { 143 return false; 144 } 145 show(label || DEFAULT_NAV_LABEL); 146 global.location.href = next; 147 return true; 148 } 149 150 // bfcache restore: the DOM snapshot was frozen with the overlay up and body 151 // scroll locked. No script re-runs on restore, so clear it here. Gated on 152 // event.persisted so a normal forward load does not fight a show() a widget 153 // legitimately called during page init. 154 if (typeof global.addEventListener === 'function') { 155 global.addEventListener('pageshow', function (event) { 156 if (event && event.persisted) { 157 hide(); 158 } 159 }); 160 } 161 162 global.WizPreparingOverlay = { 163 show: show, 164 hide: hide, 165 navigate: navigate, 166 DEFAULT_LABEL: DEFAULT_LABEL, 167 DEFAULT_NAV_LABEL: DEFAULT_NAV_LABEL, 168 __wizOverlayInit: true, 169 }; 170}(typeof window !== 'undefined' ? window : this));
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.