1(function () { 2 var HIDE_TIMEOUT = 4000; 3 var hideTimerByForm = new WeakMap(); 4 5 function t(key, fallback) { 6 var dict = window.NetworkFormsI18n || {}; 7 var v = dict[key]; 8 return (v != null && String(v) !== '') ? String(v) : fallback; 9 } 10 11 function getAjaxUrl() { 12 if (window.MyForms && window.MyForms.ajaxUrl) return window.MyForms.ajaxUrl; 13 14 if (window.ajaxurl) return window.ajaxurl; 15 16 return '/wp-admin/admin-ajax.php'; 17 } 18 19 function getMessageBox(form) { 20 var root = form.closest('[data-network-form-root]') || form.closest('section') || form.parentElement; 21 if (root) { 22 var box = root.querySelector('[data-form-message]'); 23 if (box) return box; 24 } 25 26 var next = form.nextElementSibling; 27 if (next && next.matches && next.matches('[data-form-message]')) return next; 28 return null; 29 } 30 31 function applyMessageStyles(box) { 32 box.style.marginTop = '10px'; 33 box.style.textAlign = 'center'; 34 box.style.fontSize = '14px'; 35 box.style.display = 'block'; 36 box.style.opacity = '1'; 37 box.style.transition = 'opacity 0.3s ease'; 38 } 39 40 function hideMessage(box) { 41 box.style.opacity = '0'; 42 setTimeout(function () { 43 box.textContent = ''; 44 box.removeAttribute('data-status'); 45 box.style.display = 'none'; 46 }, 300); 47 } 48 49 function setMessage(form, text, ok) { 50 var box = getMessageBox(form); 51 if (!box) return; 52 53 var prevTimer = hideTimerByForm.get(form); 54 if (prevTimer) { 55 clearTimeout(prevTimer); 56 hideTimerByForm.delete(form); 57 } 58 59 applyMessageStyles(box); 60 61 box.textContent = text || ''; 62 box.setAttribute('data-status', ok ? 'ok' : 'err'); 63 64 if (!ok && text) { 65 var contactEmail = form.getAttribute('data-error-contact-email'); 66 if (contactEmail) { 67 var contactLine = document.createElement('div'); 68 contactLine.appendChild(document.createTextNode( 69 (form.getAttribute('data-error-contact-text') || 'or contact us at') + ' ' 70 )); 71 72 var contactLink = document.createElement('a'); 73 contactLink.href = 'mailto:' + contactEmail; 74 contactLink.className = 'affiliate-form__error-contact-link'; 75 contactLink.textContent = contactEmail; 76 contactLine.appendChild(contactLink); 77 78 box.appendChild(contactLine); 79 return; /* keep the mailto link on screen instead of auto-hiding it */ 80 } 81 } 82 83 if (!text) { 84 box.style.display = 'none'; 85 return; 86 } 87 88 var timer = setTimeout(function () { 89 hideMessage(box); 90 hideTimerByForm.delete(form); 91 }, HIDE_TIMEOUT); 92 93 hideTimerByForm.set(form, timer); 94 } 95 96 function setLoading(form, loading) { 97 var btn = form.querySelector('button[type="submit"], input[type="submit"]'); 98 if (!btn) return; 99 100 btn.disabled = !!loading; 101 btn.setAttribute('aria-busy', loading ? 'true' : 'false'); 102 103 var label = btn.tagName === 'INPUT' ? btn.value : btn.textContent; 104 105 if (loading) { 106 btn.dataset._label = label; 107 if (btn.tagName === 'INPUT') btn.value = t('btnSending', 'Sending...'); 108 else btn.textContent = t('btnSending', 'Sending...'); 109 } else if (btn.dataset._label) { 110 if (btn.tagName === 'INPUT') btn.value = btn.dataset._label; 111 else btn.textContent = btn.dataset._label; 112 delete btn.dataset._label; 113 } 114 } 115 116 function getRequired(form) { 117 var formTypeEl = form.querySelector('input[name="form_type"]'); 118 var nonceEl = form.querySelector('input[name="network_forms_nonce"]'); 119 120 return { 121 formType: formTypeEl ? String(formTypeEl.value || '').trim() : '', 122 nonce: nonceEl ? String(nonceEl.value || '') : '' 123 }; 124 } 125 126 function buildFormData(form, formType, nonce) { 127 var fd = new FormData(form); 128 129 fd.set('action', 'network_forms_submit'); 130 fd.set('form_type', formType); 131 fd.set('network_forms_nonce', nonce); 132 return fd; 133 } 134 135 function showSuccessPopup(form) { 136 var popup = document.querySelector('[data-popup="success"]'); 137 if (!popup) return; 138 139 var titleEl = popup.querySelector('.popup__title'); 140 var descEl = popup.querySelector('.popup__description p'); 141 142 if (titleEl) titleEl.textContent = form.getAttribute('data-success-title') || ''; 143 if (descEl) descEl.textContent = form.getAttribute('data-success-text') || ''; 144 145 popup.classList.add('active'); 146 } 147 148 /** 149 * A page coming from the full-page cache carries the nonce of whoever filled 150 * the cache, so a logged-in visitor (or a day-old tab) submits one that does 151 * not verify. This asks the server for a fresh one. 152 */ 153 async function fetchNonce() { 154 try {
155 var res = await fetch(getAjaxUrl() + '?action=network_forms_nonce', { 156 credentials: 'same-origin', 157 cache: 'no-store' 158 }); 159 160 var data = await res.json().catch(function () { return null; }); 161 162 return (data && data.success && data.data && data.data.nonce) ? data.data.nonce : ''; 163 } catch (e) { 164 return ''; 165 } 166 } 167 168 async function post(form, formType, nonce) { 169 var res = await fetch(getAjaxUrl(), { 170 method: 'POST', 171 body: buildFormData(form, formType, nonce), 172 credentials: 'same-origin' 173 }); 174 175 var text = await res.text(); 176 var data = null; 177 178 try { data = JSON.parse(text); } catch (e) { 179 /* A cache, proxy or fatal error answered instead of WordPress. */ 180 console.warn('[network-forms] unexpected response', res.status, text.slice(0, 300)); 181 } 182 183 return { res: res, data: data }; 184 } 185 186 async function submitAjax(form) { 187 var req = getRequired(form); 188 189 if (!req.formType) { 190 setMessage(form, t('errMissingFormType', 'Form configuration error: missing form_type.'), false); 191 return; 192 } 193 if (!req.nonce) { 194 setMessage(form, t('errMissingNonce', 'Form configuration error: missing nonce.'), false); 195 return; 196 } 197 198 setLoading(form, true); 199 setMessage(form, '', true); 200 201 try { 202 var answer = await post(form, req.formType, req.nonce); 203 var data = answer.data; 204 205 /* Stale nonce: take a fresh one and send the application once more. */ 206 if (data && !data.success && data.data && data.data.code === 'invalid_nonce') { 207 var fresh = await fetchNonce(); 208 209 if (fresh) { 210 var field = form.querySelector('input[name="network_forms_nonce"]'); 211 if (field) field.value = fresh; 212 213 answer = await post(form, req.formType, fresh); 214 data = answer.data; 215 } 216 } 217 218 if (!data || !data.success) { 219 var msg = (data && data.data && data.data.message) ? data.data.message : t('errGeneric', 'Error. Please try again.'); 220 setMessage(form, msg, false); 221 return; 222 } 223 224 showSuccessPopup(form); 225 226 Array.prototype.forEach.call(form.elements, function (el) { 227 if (!el || !el.name) return; 228 if (el.type === 'hidden') return; 229 if (el.type === 'checkbox' || el.type === 'radio') el.checked = false; 230 else el.value = ''; 231 }); 232 233 } catch (e) { 234 setMessage(form, t('errNetwork', 'Network error. Please try again.'), false); 235 } finally { 236 setLoading(form, false); 237 } 238 } 239 240 document.addEventListener('submit', function (e) { 241 var form = e.target; 242 if (!(form instanceof HTMLFormElement)) return; 243 if (!form.hasAttribute('data-network-form')) return; 244 245 if (!window.fetch || !window.FormData) return; 246 247 e.preventDefault(); 248 submitAjax(form); 249 }, true); 250})();
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.