1(function () { 2 'use strict'; 3 if (!window.ZKFormsCore || !window.zkFormsConfig) return; 4 5 var core = window.ZKFormsCore; 6 var cfg = window.zkFormsConfig; 7 var processedSignatures = new Set(); 8 var BUILTIN_EXCLUDE_SELECTORS = ['#loginform', '#lostpasswordform', '#resetpassform']; 9 10 function sourceOf(form) { 11 if (form && form.id === 'registerform') return 'wordpress-registration'; 12 var c = ' ' + String(form.className || '') + ' '; 13 if (c.indexOf(' wpcf7-form ') !== -1 || form.closest('.wpcf7')) return 'cf7'; 14 if (c.indexOf(' wpforms-form ') !== -1 || form.closest('.wpforms-container')) return 'wpforms'; 15 if (c.indexOf(' elementor-form ') !== -1 || form.closest('.elementor-form-fields-wrapper')) return 'elementor'; 16 if (c.indexOf(' gform_wrapper ') !== -1 || form.closest('.gform_wrapper')) return 'gravity'; 17 if (c.indexOf(' frm-show-form ') !== -1 || form.closest('.frm_forms')) return 'formidable'; 18 if (c.indexOf(' forminator-custom-form ') !== -1 || form.closest('.forminator-ui')) return 'forminator'; 19 if (c.indexOf(' fluent_form_') !== -1 || form.closest('.fluentform')) return 'fluent'; 20 if (form.closest('.nf-form-cont')) return 'ninja'; 21 return 'generic'; 22 } 23 24 function labelText(input) { 25 var chunks = []; 26 if (input.labels) Array.prototype.forEach.call(input.labels, function (label) { chunks.push(label.textContent || ''); }); 27 var closest = input.closest && input.closest('label'); 28 if (closest) chunks.push(closest.textContent || ''); 29 if (input.getAttribute('aria-label')) chunks.push(input.getAttribute('aria-label')); 30 if (input.placeholder) chunks.push(input.placeholder); 31 return chunks.join(' '); 32 } 33 34 function describeFields(form) { 35 return Array.prototype.map.call(form.querySelectorAll('input, textarea, select'), function (el) { 36 var type = (el.getAttribute('type') || el.tagName || 'text').toLowerCase(); 37 if (el.tagName && el.tagName.toLowerCase() === 'textarea') type = 'textarea'; 38 return { 39 type: type, 40 name: el.getAttribute('name') || '', 41 label: labelText(el), 42 required: !!(el.required || el.getAttribute('aria-required') === 'true') 43 }; 44 }); 45 } 46 47 function describeExistingConsents(form) { 48 return Array.prototype.map.call(form.querySelectorAll('input[type="checkbox"]'), function (el) { 49 return { 50 type: 'checkbox', 51 name: el.getAttribute('name') || '', 52 label: labelText(el), 53 required: !!(el.required || el.getAttribute('aria-required') === 'true'), 54 checked: !!el.checked, 55 element: el 56 }; 57 }); 58 } 59 60 function submitText(form) { 61 var btn = form.querySelector('button[type="submit"], input[type="submit"], button:not([type])'); 62 if (!btn) return ''; 63 return btn.value || btn.textContent || ''; 64 } 65 66 function describeForm(form) { 67 var heading = ''; 68 var labelled = form.getAttribute('aria-label') || ''; 69 var titleEl = form.querySelector('h1,h2,h3,h4,.form-title,.wpforms-title,.gform_title'); 70 if (titleEl) heading = titleEl.textContent || ''; 71 var source = sourceOf(form); 72 var formId = form.getAttribute('data-formid') || form.id || form.getAttribute('name') || ''; 73 if (source === 'ninja') { 74 var nfContainer = form.closest('.nf-form-cont'); 75 if (nfContainer && nfContainer.getAttribute('data-form-id')) formId = nfContainer.getAttribute('data-form-id'); 76 } 77 return { 78 source: source, 79 id: formId, 80 title: [labelled, heading].join(' '), 81 action: form.getAttribute('action') || '', 82 submitText: submitText(form), 83 fields: describeFields(form) 84 }; 85 } 86 87 function selectorMatches(form) { 88 var result = { forced: false, excluded: false }; 89 BUILTIN_EXCLUDE_SELECTORS.forEach(function (selector) { 90 try { if (form.matches(selector) || form.closest(selector)) result.excluded = true; } catch (e) {} 91 }); 92 (cfg.forceSelectors || []).forEach(function (selector) { 93 try { if (form.matches(selector) || form.closest(selector)) result.forced = true; } catch (e) {} 94 });
95 (cfg.excludeSelectors || []).forEach(function (selector) { 96 try { if (form.matches(selector) || form.closest(selector)) result.excluded = true; } catch (e) {} 97 }); 98 return result; 99 } 100 101 function applyDefaultBasis(profile) { 102 if (profile.purpose === 'contact' && cfg.defaultBasis === 'contract' && !profile.sensitiveRisk) { 103 profile.basis = 'contract'; 104 profile.requiresPdConsent = false; 105 profile.reason = 'admin-default-contract'; 106 } 107 return profile; 108 } 109 110 function normalizeUrl(url) { 111 try { 112 var u = new URL(url, window.location.href); 113 u.hash = ''; 114 u.hostname = u.hostname.toLowerCase(); 115 u.pathname = u.pathname === '/' ? '/' : u.pathname.replace(/\/+$/, '') + '/'; 116 return u.toString(); 117 } catch (e) { return ''; } 118 } 119 120 function existingHrefSet(form) { 121 var set = new Set(); 122 Array.prototype.forEach.call(form.querySelectorAll('a[href]'), function (a) { 123 var n = normalizeUrl(a.href); 124 if (n) set.add(n); 125 }); 126 return set; 127 } 128 129 function legalLinksFor(profile) { 130 var defs = [ 131 {url: cfg.privacyPolicyUrl, label: 'ÐолиÑика обÑабоÑки пеÑÑоналÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ ', kind: 'policy'}, 132 {url: cfg.privacyNoticeUrl, label: 'ÐолиÑика конÑиденÑиалÑноÑÑи', kind: 'notice'}, 133 {url: cfg.consentUrl, label: 'СоглаÑие на обÑабоÑÐºÑ Ð¿ÐµÑÑоналÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ ', kind: 'consent'} 134 ]; 135 var seen = new Set(); 136 return defs.filter(function (item) { 137 if (!item.url || (item.kind === 'consent' && profile.basis !== 'consent')) return false; 138 var n = normalizeUrl(item.url); 139 if (!n || seen.has(n)) return false; 140 seen.add(n); return true; 141 }); 142 } 143 144 function insertNearSubmit(form, node) { 145 var submit = form.querySelector('button[type="submit"], input[type="submit"], button:not([type])'); 146 if (submit && submit.parentNode) submit.parentNode.insertBefore(node, submit); 147 else form.appendChild(node); 148 } 149 150 function createLinks(profile, form) { 151 var links = legalLinksFor(profile); 152 var existing = existingHrefSet(form); 153 var wrap = document.createElement('div'); 154 wrap.className = 'zk-form-legal-links'; 155 links.forEach(function (item) { 156 var n = normalizeUrl(item.url); 157 if (existing.has(n)) return; 158 if (wrap.childNodes.length) wrap.appendChild(document.createTextNode(' · ')); 159 var a = document.createElement('a'); 160 a.href = item.url; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.textContent = item.label; 161 wrap.appendChild(a); 162 }); 163 return wrap.childNodes.length ? wrap : null; 164 } 165 166 function markExistingConsent(stateEntry, kind, makeRequired) { 167 if (!stateEntry || !stateEntry.field || !stateEntry.field.element) return; 168 var input = stateEntry.field.element; 169 if (makeRequired) { 170 input.required = true; 171 input.setAttribute('aria-required', 'true'); 172 } 173 if (core.shouldClearPrecheckedConsent(stateEntry)) input.checked = false; 174 input.setAttribute('data-zk-consent-kind', kind); 175 input.setAttribute('data-zk-existing-consent', '1'); 176 } 177 178 function upgradeExistingConsent(stateEntry, kind) { 179 markExistingConsent(stateEntry, kind, true); 180 } 181 182 function normalizePolicyCombined(stateEntry) { 183 if (!stateEntry || !stateEntry.combinedPolicy || !stateEntry.field || !stateEntry.field.element) return; 184 var input = stateEntry.field.element; 185 var label = input.closest('label'); 186 if (!label && input.id) label = document.querySelector('label[for="' + CSS.escape(input.id) + '"]'); 187 if (!label) return; 188 Array.prototype.slice.call(label.childNodes).forEach(function (child) { 189 if (child !== input) label.removeChild(child); 190 }); 191 var span = document.createElement('span'); 192 span.textContent = cfg.formConsentText || 'Я ÑоглаÑен на обÑабоÑÐºÑ Ð¿ÐµÑÑоналÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ .'; 193 label.appendChild(span); 194 label.setAttribute('data-zk-normalized-policy-consent', '1'); 195 } 196 197 function checkboxDefinition(kind) { 198 if (kind === 'marketing') return {name:'zk_marketing_consent', text:cfg.marketingConsentText}; 199 if (kind === 'spread') return {name:'zk_spread_consent', text:cfg.spreadConsentText}; 200 return {name:'zk_pd_consent', text:cfg.formConsentText}; 201 } 202 203 function addCheckbox(block, kind) { 204 var def = checkboxDefinition(kind); 205 var label = document.createElement('label'); 206 label.className = 'zk-form-consent zk-form-consent--' + kind; 207 var input = document.createElement('input'); 208 input.type = 'checkbox'; input.name = def.name; input.value = '1'; input.required = true; 209 input.setAttribute('aria-required', 'true'); input.setAttribute('data-zk-consent-kind', kind); 210 var span = document.createElement('span'); 211 span.textContent = def.text || ''; 212 label.appendChild(input); label.appendChild(span); block.appendChild(label); 213 } 214 215 function randomConsentId() { 216 var bytes = new Uint8Array(16); 217 if (window.crypto && window.crypto.getRandomValues) window.crypto.getRandomValues(bytes); 218 else for (var i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256); 219 return Array.prototype.map.call(bytes, function (b) { return b.toString(16).padStart(2, '0'); }).join(''); 220 } 221 222 function ensureHiddenMeta(form, profile) { 223 var values = { 224 zk_consent_id: randomConsentId(), 225 zk_policy_version: cfg.policyVersion || '1.0', 226 zk_form_basis: profile.basis || 'none' 227 };
228 Object.keys(values).forEach(function (name) { 229 if (form.querySelector('input[name="' + name + '"]')) return; 230 var input = document.createElement('input'); input.type = 'hidden'; input.name = name; input.value = values[name]; 231 form.appendChild(input); 232 }); 233 } 234 235 function buildComplianceBlock(form, profile, state) { 236 var block = document.createElement('div'); 237 block.className = 'zk-form-compliance'; 238 block.setAttribute('data-zk-created', '1'); 239 if (profile.requiresPdConsent && ['valid','optional'].indexOf(state.pd.state) === -1) addCheckbox(block, 'pd'); 240 if (profile.requiresMarketingConsent && ['valid','optional'].indexOf(state.marketing.state) === -1) addCheckbox(block, 'marketing'); 241 if (profile.requiresSpreadConsent && ['valid','optional'].indexOf(state.spread.state) === -1) addCheckbox(block, 'spread'); 242 var links = createLinks(profile, form); 243 if (links) block.appendChild(links); 244 return block; 245 } 246 247 function appendMissingLegalNotice(form, profile) { 248 if (form.querySelector('.zk-form-compliance .zk-form-legal-links, .zk-form-legal-notice')) return; 249 var links = createLinks(profile, form); 250 if (!links) return; 251 links.classList.add('zk-form-legal-notice'); 252 insertNearSubmit(form, links); 253 } 254 255 function ensureError(form, input) { 256 var old = form.querySelector('.zk-form-error'); 257 if (old) old.remove(); 258 var err = document.createElement('div'); 259 err.className = 'zk-form-error'; err.setAttribute('role','alert'); 260 err.textContent = 'ÐÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ подÑвеÑдиÑÑ ÑÑебÑемое ÑоглаÑие пеÑед оÑпÑавкой ÑоÑмÑ.'; 261 if (input && input.closest('label')) input.closest('label').insertAdjacentElement('afterend', err); 262 else insertNearSubmit(form, err); 263 } 264 265 function syncExistingConsentProxies(form) { 266 if (!form) return; 267 var fields = Array.prototype.map.call(form.querySelectorAll('[data-zk-existing-consent="1"][data-zk-consent-kind]'), function (input) { 268 return { 269 kind: input.getAttribute('data-zk-consent-kind') || '', 270 name: input.getAttribute('name') || '', 271 checked: !!input.checked 272 }; 273 }); 274 var payload = core.existingConsentProxyPayload(fields); 275 var technical = {pd:'zk_pd_consent', marketing:'zk_marketing_consent', spread:'zk_spread_consent'}; 276 Object.keys(technical).forEach(function (kind) { 277 var name = technical[kind]; 278 var proxy = form.querySelector('input[data-zk-consent-proxy="' + kind + '"]'); 279 if (!Object.prototype.hasOwnProperty.call(payload, name)) { 280 if (proxy) proxy.remove(); 281 return; 282 } 283 if (!proxy) { 284 proxy = document.createElement('input'); 285 proxy.type = 'hidden'; 286 proxy.name = name; 287 proxy.setAttribute('data-zk-consent-proxy', kind); 288 form.appendChild(proxy); 289 } 290 proxy.value = payload[name]; 291 }); 292 } 293 294 function syncNinjaExtra(form) { 295 if (!form || sourceOf(form) !== 'ninja') return; 296 var container = form.closest('.nf-form-cont'); 297 var formId = container && container.getAttribute('data-form-id'); 298 var radio = window.nfRadio || (window.Backbone && window.Backbone.Radio); 299 if (!formId || !radio || typeof radio.channel !== 'function') return; 300 var channel = radio.channel('form-' + formId); 301 if (!channel || typeof channel.request !== 'function') return; 302 function checked(kind) { 303 var field = form.querySelector('[data-zk-consent-kind="' + kind + '"]'); 304 return !!(field && field.checked); 305 } 306 function hidden(name) { 307 var input = form.querySelector('input[name="' + name + '"]'); 308 return input ? input.value : ''; 309 } 310 var extra = core.ninjaExtraPayload({pd:checked('pd'),marketing:checked('marketing'),spread:checked('spread')},{ 311 consentId:hidden('zk_consent_id'), policyVersion:hidden('zk_policy_version'), basis:hidden('zk_form_basis') 312 }); 313 Object.keys(extra).forEach(function (key) { channel.request('add:extra', key, extra[key]); }); 314 } 315 316 function inventoryWarnings(form, descriptor, profile, state) { 317 var warnings = []; 318 try { 319 if (descriptor.action) { 320 var actionUrl = new URL(descriptor.action, window.location.href); 321 if (actionUrl.host && actionUrl.host !== window.location.host) warnings.push('external_endpoint'); 322 } 323 } catch (e) {} 324 if (core.hasPrecheckedConsent(state)) warnings.push('prechecked_consent'); 325 if (state.pd.state === 'combined' || state.marketing.state === 'combined') warnings.push('combined_marketing_consent'); 326 if (profile.basis === 'manual' || profile.confidence === 'low')
326warnings.push('manual_classification'); 327 if (profile.sensitiveRisk) warnings.push('sensitive_fields'); 328 if (profile.basis === 'consent' && (cfg.serverValidationSources || []).indexOf(descriptor.source) === -1) warnings.push('no_server_validation'); 329 return warnings.filter(function (value, index, all) { return all.indexOf(value) === index; }); 330 } 331 332 function reportInventory(form, descriptor, profile, state) { 333 if (!cfg.diagnostics || !cfg.inventoryAjaxUrl || !cfg.inventoryNonce || !window.fetch) return; 334 var fieldTypes = descriptor.fields.map(core.detectField).filter(function (value, index, all) { return all.indexOf(value) === index; }); 335 var localSignature = [descriptor.source, descriptor.id, window.location.pathname, fieldTypes.join(','), profile.purpose, profile.basis, state.pd.state].join('|'); 336 if (processedSignatures.has(localSignature)) return; 337 processedSignatures.add(localSignature); 338 var data = new FormData(); 339 data.append('action', 'zk_report_form_inventory'); 340 data.append('nonce', cfg.inventoryNonce); 341 data.append('source', descriptor.source || 'generic'); 342 data.append('form_id', descriptor.id || ''); 343 data.append('page_url', window.location.origin + window.location.pathname); 344 fieldTypes.forEach(function (type) { data.append('field_types[]', type); }); 345 data.append('purpose', profile.purpose || 'service'); 346 data.append('basis', profile.basis || 'none'); 347 data.append('existing_pd', state.pd.state || 'none'); 348 data.append('server_validation', (cfg.serverValidationSources || []).indexOf(descriptor.source) !== -1 ? '1' : '0'); 349 inventoryWarnings(form, descriptor, profile, state).forEach(function (warning) { data.append('warnings[]', warning); }); 350 window.setTimeout(function () { 351 fetch(cfg.inventoryAjaxUrl, {method:'POST', credentials:'same-origin', body:data}).catch(function () {}); 352 }, 250); 353 } 354 355 function diagnostic(form, descriptor, profile, state) { 356 if (!cfg.diagnostics || form.querySelector('.zk-form-diagnostic')) return; 357 var box = document.createElement('div'); box.className = 'zk-form-diagnostic'; 358 var lines = [ 359 'ÐаконнÑе кÑки: ÑоÑма обнаÑÑжена', 360 'ÐÑÑоÑник: ' + descriptor.source, 361 'ÐолÑ: ' + descriptor.fields.map(core.detectField).join(', '), 362 'ЦелÑ: ' + profile.purpose, 363 'ÐÑнование: ' + profile.basis, 364 'СоглаÑие ÐÐн: ' + state.pd.state, 365 'СеÑвеÑÐ½Ð°Ñ Ð¿ÑовеÑка: ' + ((cfg.serverValidationSources || []).indexOf(descriptor.source) !== -1 ? 'да' : 'не подÑвеÑждена') 366 ]; 367 lines.forEach(function (line) { var div = document.createElement('div'); div.textContent = line; box.appendChild(div); }); 368 form.insertAdjacentElement('beforebegin', box); 369 } 370 371 function processForm(form) { 372 if (!form || form.nodeType !== 1 || form.tagName.toLowerCase() !== 'form') return; 373 if (core.processedFormIntact({ 374 processed: form.dataset.zkFormProcessed === '1', 375 basis: form.dataset.zkFormBasis || '', 376 hasConsentKind: !!form.querySelector('[data-zk-consent-kind]'), 377 hasMeta: !!form.querySelector('input[name="zk_consent_id"]') 378 })) return; 379 var descriptor = describeForm(form); 380 var profile = applyDefaultBasis(core.classify(descriptor)); 381 var matches = selectorMatches(form); 382 var state = core.detectExistingConsent(describeExistingConsents(form)); 383 diagnostic(form, descriptor, profile, state); 384 reportInventory(form, descriptor, profile, state); 385 if (!core.shouldProcess(matches, profile, {fallbackEnabled: !!cfg.fallbackEnabled})) return; 386 387 ['pd','marketing','spread'].forEach(function (kind) { 388 if (state[kind].state === 'optional') upgradeExistingConsent(state[kind], kind); 389 else if (state[kind].state === 'valid') markExistingConsent(state[kind], kind, false); 390 }); 391 if (state.pd.combinedPolicy) { 392 upgradeExistingConsent(state.pd, 'pd'); 393 normalizePolicyCombined(state.pd); 394 state.pd.state = 'valid'; 395 } 396 397 var needsBlock = (profile.requiresPdConsent && state.pd.state !== 'valid') || 398 (profile.requiresMarketingConsent && state.marketing.state !== 'valid') || 399 (profile.requiresSpreadConsent && state.spread.state !== 'valid'); 400 401 if (needsBlock && !form.querySelector('.zk-form-compliance')) { 402 var block = buildComplianceBlock(form, profile, state); 403 insertNearSubmit(form, block); 404 } else { 405 appendMissingLegalNotice(form, profile); 406 } 407 408 ensureHiddenMeta(form, profile); 409 syncExistingConsentProxies(form); 410 syncNinjaExtra(form); 411 form.dataset.zkFormProcessed = '1'; 412 form.dataset.zkFormSource = descriptor.source; 413 form.dataset.zkFormBasis = profile.basis; 414 } 415 416 function validateBeforeSubmit(event) { 417 var form = event.target; 418 if (!form || form.tagName.toLowerCase() !== 'form') return; 419 processForm(form); 420 syncExistingConsentProxies(form); 421 syncNinjaExtra(form); 422 var required = form.querySelectorAll('[data-zk-consent-kind][required]'); 423 for (var i = 0; i < required.length; i++) { 424 if (!required[i].checked) { 425 event.preventDefault(); event.stopImmediatePropagation(); 426 ensureError(form, required[i]); required[i].focus(); return; 427 } 428 } 429 var err = form.querySelector('.zk-form-error'); if (err) err.remove(); 430 } 431 432 function scan(root) { 433 if (!root || !root.querySelectorAll) return; 434 if (root.tagName && root.tagName.toLowerCase() === 'form') process
434Form(root); 435 Array.prototype.forEach.call(root.querySelectorAll('form'), processForm); 436 } 437 438 function init() { 439 scan(document); 440 document.addEventListener('submit', validateBeforeSubmit, true); 441 document.addEventListener('change', function (event) { 442 var target = event.target; 443 if (!target || !target.matches || !target.matches('[data-zk-consent-kind]')) return; 444 var form = target.closest('form'); 445 if (form) { 446 syncExistingConsentProxies(form); 447 syncNinjaExtra(form); 448 } 449 }, true); 450 if (window.MutationObserver) { 451 new MutationObserver(function (mutations) { 452 mutations.forEach(function (m) { 453 var targetForm = m.target && m.target.closest && m.target.closest('form'); 454 if (targetForm) processForm(targetForm); 455 Array.prototype.forEach.call(m.addedNodes || [], function (node) { 456 if (node.nodeType !== 1) return; 457 var ownerForm = node.closest && node.closest('form'); 458 if (ownerForm) processForm(ownerForm); 459 scan(node); 460 }); 461 }); 462 }).observe(document.documentElement, {childList:true, subtree:true}); 463 } 464 } 465 466 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); 467 else init(); 468}());
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.