1(() => { 2 'use strict'; 3 4 const STORAGE = { 5 firstCode: 'cloudinx_rep_first_code', 6 firstAt: 'cloudinx_rep_first_at', 7 lastCode: 'cloudinx_rep_last_code', 8 lastAt: 'cloudinx_rep_last_at' 9 }; 10 11 const safeGet = key => { 12 try { return window.sessionStorage.getItem(key) || ''; } 13 catch (_error) { return ''; } 14 }; 15 const safeSet = (key, value) => { 16 try { window.sessionStorage.setItem(key, value); } 17 catch (_error) { /* Attribution remains available on the current page only. */ } 18 }; 19 const sanitiseRepCode = value => { 20 const code = String(value || '').trim().toUpperCase(); 21 return /^[A-Z0-9][A-Z0-9_-]{2,31}$/.test(code) ? code : ''; 22 }; 23 const ensureHidden = (form, name, value = '') => { 24 let field = form.querySelector(`input[name="${name}"]`); 25 if (!field) { 26 field = document.createElement('input'); 27 field.type = 'hidden'; 28 field.name = name; 29 form.prepend(field); 30 } 31 field.value = value; 32 return field; 33 }; 34 35 const params = new URLSearchParams(window.location.search); 36 const rawRep = params.get('rep'); 37 const urlRep = sanitiseRepCode(rawRep); 38 const invalidUrlRep = Boolean(rawRep && !urlRep); 39 const now = new Date().toISOString(); 40 41 if (urlRep) { 42 if (!safeGet(STORAGE.firstCode)) { 43 safeSet(STORAGE.firstCode, urlRep); 44 safeSet(STORAGE.firstAt, now); 45 } 46 safeSet(STORAGE.lastCode, urlRep); 47 safeSet(STORAGE.lastAt, now); 48 } 49 50 const firstCode = safeGet(STORAGE.firstCode) || urlRep; 51 const firstAt = safeGet(STORAGE.firstAt) || (urlRep ? now : ''); 52 const lastCode = safeGet(STORAGE.lastCode) || urlRep; 53 const lastAt = safeGet(STORAGE.lastAt) || (urlRep ? now : ''); 54 55 document.querySelectorAll('form[data-cloudinx-form="true"]').forEach(form => { 56 const visibleReference = form.querySelector('[data-rep-reference-input="true"]'); 57 if (visibleReference && !visibleReference.value && lastCode) { 58 visibleReference.value = lastCode; 59 } 60 61 const initialMethod = urlRep ? 'rep_link' : (lastCode ? 'session_rep' : 'unattributed'); 62 const initialValidation = invalidUrlRep 63 ? 'invalid_format' 64 : (lastCode ? 'pending_backend_validation' : 'not_supplied'); 65 66 ensureHidden(form, 'crm_first_touch_rep_code', firstCode); 67 ensureHidden(form, 'crm_last_touch_rep_code', lastCode); 68 ensureHidden(form, 'crm_rep_first_touch_at', firstAt); 69 ensureHidden(form, 'crm_rep_last_touch_at', lastAt); 70 ensureHidden(form, 'crm_rep_attribution_method', initialMethod); 71 ensureHidden(form, 'crm_rep_code_validation_status', initialValidation); 72 ensureHidden(form, 'crm_user_entered_rep_reference', visibleReference?.value.trim() || ''); 73 ensureHidden(form, 'crm_owner_assignment_status', 'pending_crm_routing'); 74 ensureHidden(form, 'crm_owner_assignment_method', 'not_assigned_by_public_form'); 75 76 const syncReference = () => { 77 const manual = visibleReference?.value.trim() || ''; 78 ensureHidden(form, 'crm_user_entered_rep_reference', manual); 79 if (manual && !lastCode) { 80 ensureHidden(form, 'crm_rep_attribution_method', 'user_entered'); 81 ensureHidden(form, 'crm_rep_code_validation_status', 'manual_reference_pending_review'); 82 } 83 }; 84 85 visibleReference?.addEventListener('input', syncReference); 86 form.addEventListener('submit', syncReference); 87 }); 88})();
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.