1 2;(function() { 3 4function encode(d) { 5 var prm = []; 6 for(var k in d) { 7 var val = d[k]; 8 if(Array.isArray(val)) for(var i=0;i < val.length; ++i){ 9 prm.push(encodeURIComponent(k)+"="+encodeURIComponent(val[i])); 10 } 11 else prm.push(encodeURIComponent(k)+"="+encodeURIComponent(val)); 12 } 13 return prm.join('&'); 14} 15 16function send(data) { 17 18 var xhr = this, u = this.url, t = this.contentType, hdrs = this.headers, 19 d = data || this.data, 20 m = this.method || (t ? 'POST' : 'GET'); 21 if(d) { 22 if(d.constructor === Object) { 23 if(t && /^multipart/.test(t)) { 24 t = new FormData(); for(var k in d) t.append(k,d[k]); d = t; 25 } 26 else d = encode(d); 27 } 28 if(d.constructor === FormData) { t = ''; m = 'POST'; } 29 if(typeof d === "string") { 30 if(/^POST$/i.test(m)){ 31 if(!t) t = "application/x-www-form-urlencoded"; 32 } 33 else { 34 u += (u.indexOf('?') == -1 ? '?' : '&' )+d; 35 d = null; 36 } 37 } 38 } 39 xhr.open(m, u); 40 if(t) xhr.setRequestHeader("Content-Type",t); 41 if(hdrs) for(var h in hdrs) xhr.setRequestHeader(h,hdrs[h]); 42 XMLHttpRequest.prototype.send.call(this,d); 43} 44 45function ajaxComplete(ev) { 46 var s = this.status < 200 || this.status >= 400 ? ev.type : "success"; 47 if(s != "success") { if(this.error) this.error(this, s); } 48 else { if(this.success) this.success(this.response || this.responseText, s, this); } 49 if(this.complete) this.complete(this,s); 50} 51 52function ajax(url, options) { 53 if(typeof url === "object") { options = url; url = null; } 54 else if(options && options.call) { options = { success: options} } 55 var ax = new XMLHttpRequest(); 56 ax.onload = ax.onerror = ax.onabort = ax.ontimeout = ajaxComplete; 57 ax.send = send; 58 for(var k in options) ax[k] = options[k]; 59 60 if(url) ax.url = url; 61 if(ax.paused) delete ax.paused; else if(ax.success||ax.complete) ax.send(); 62 return ax; 63} 64 65window.ajax = ajax; 66 67})(); 68 69;(function() { 70 71var typeMasks = {}, chMap = {}; 72 73function InputMask(elem, mask) { 74 if(typeof(mask) === 'object') { 75 this.showAll = mask.showAll; 76 this.showEmpty = mask.showEmpty; 77 mask = mask.mask; 78 } 79 this.masks = typeMasks[mask] || compile(mask); 80 this.mask = this.masks[0]; 81 this.ts = elem.dataset.thousandSeparator; 82 83 this.clear(); 84 if(elem) { 85 this.target = elem; 86 elem.addEventListener("input", handleInput.bind(this)); 87 elem.addEventListener("focus", handleFocus.bind(this)); 88 if(elem.value) { 89 this.value = elem.value.split(''); 90 this.mask = detectMask(this.masks,this.value); 91 } 92 else if(this.showEmpty) elem.value = this.value.join(''); 93 } 94} 95 96InputMask.prototype = { 97 98 clear:function() { 99 this.value = this.mask.map(function(c) {return c.value || c}); 100 }, 101 nextIndex:function() { 102 var self = this; 103 return this.mask.findIndex(function(m,i) {return m.value == self.value[i]}); 104 }, 105 getValue:function() { 106 var self = this; 107 return this.mask.map(function(m,i) { 108 return (m.test && m.test(self.value[i]) ? self.value[i] : '')} 109 ).join('') ; 110 }, 111 setValue:function(value, index) { 112 var m = this.mask = detectMask(this.masks,value); 113 if(this.ts) m = this.mask = tsMask(m,value,this.ts); 114 this.clear(); 115 var v = this.value, n = 0, p = mv(-1,1,m),pp,i,c,cc,el; 116 for(i=0; i < value.length; ++i) { 117 c = value.charAt(i); 118 if(i == index) pp = p; 119 if(p < m.length &&(cc=m[p].test(c))) { v[p] = (cc===true?c:cc); p = mv(p,1,m); ++n; } 120 } 121 if((el=this.target)) { 122 el.value = n === 0 123 ? (this.showEmpty ? v.join('') : '') 124 : (this.showAll ? v.join('') : v.join('').substring(0,p) ); 125 setPos(el, pp === undefined ? p : pp); 126 } 127 } 128}; 129 130function compile(mask) { 131 var arr = mask.split("|"); 132 for(var i=0; i < arr.length; ++i) { 133 var s = arr[i], msk = [],j,c; 134 for(j=0; j < s.length; ++j) { c=s.charAt(j); msk.push(chMap[c]||c);} 135 arr[i] = msk; 136 } 137 return (typeMasks[mask] = arr); 138} 139 140function detectMask(arr,v) { 141 if(v && arr.length > 1) { 142 var c = v.charAt(0),i,x; 143 for(i=0;i<arr.length;++i) { 144 x = arr[i][0]; 145 if(x.test && x.test(c)) return arr[i]; 146 } 147 } 148 return arr[0]; 149} 150function tsMask(m,value,sep) { 151 let v = value.replaceAll(sep,""), i = v.length; 152 let mask = m.length == 1 ? Array(i).fill(m[0]) : m.slice(0); 153 if(i > mask.length) i = mask.length; 154 while(i > 3) mask.splice(i-=3,0,sep); 155 return mask; 156} 157 158function handleInput(ev) { 159 var el = ev.target, type = ev.inputType; 160 var v = el.value, p = el.selectionEnd, pp; 161 if(type == "deleteContentBackward") { 162 pp = mv(p+1,-1,this.mask); 163 if(pp < p) { 164 v = v.substring(0,pp)+v.substring(p); 165 p = pp; 166 } 167 } 168 else if(type == "deleteContentForward") { 169 pp = mv(p-1,1,this.mask); 170 if(pp > p) { 171 v = v.substring(0,p)+v.substring(pp); 172 } 173 } 174 this.setValue(v,p); 175} 176function handleFocus(ev) { 177 var index = this.nextIndex(); 178 if(index != -1) setPos(ev.target,index); 179} 180function mv(idx,delta,mask) { 181 for(;;) { 182 var p = mask[idx += delta]; 183 if(!p || p.test) return Math.max(0,Math.min(idx,mask.length)); 184 } 185} 186function setPos(el,index) { 187 try { 188 if(el.selectionStart != index || el.selectionEnd != index) { 189 el.selectionStart = el.selectionEnd = index; 190 } 191 } 192 catch(err) { if(el.type != "number") console.error(err); } 193} 194InputMask.register = function(name, mask) { 195 typeMasks[name] = compile(mask); 196}; 197InputMask.map = function(map) { 198 for(var ch in map) { 199 var ex = map[ch]; 200 if(ex.call) ex = { test: ex }; 201 if(! ex.value) ex.value = '\u2002'; 202 chMap[ch] = ex; 203 } 204}; 205window.InputMask = InputMask; 206 207}()); 208 209 210 211 212 213 214 215; (function () { 216 217 function initForm(form) { 218 if (form.dataset.resetOnLoad) form.reset(); 219 220 form.addEventListener("submit", onSubmit); 221 form.addEventListener("input", onInput); 222 form.addEventListener("focusin", onFocusin); 223 form.addEventListener("focusout", onFocusout); 224 225 form.getValue = getValue; 226 form.setValue = setValue; 227 form.initInput = initInput; 228 229 var elms = form.elements, j, el; 230 for (j = 0; j < elms.length; ++j) { 231 if ((el = elms[j]).type != "hidden") form.initInput(el); 232 } 233 if (form.dataset.onCreate) getFunctions(form.dataset.onCreate) 234 .forEach(function (fn) { 235 fn(form); 236 }); 237 } 238 function initInput(el) { 239 checkValue(el); 240 if (el.dataset.inputMask) el.mask = new InputMask(el, el.dataset.inputMask); 241 if (this.noValidate) el.addEventListener("blur", onBlur); 242 } 243 244 function isFunction(s) { return s && s.call; } 245 function getFunctions(lst) { 246 return lst.trim().split(/ *, */g).map(Forms.Util.lookup).filter(isFunction); 247 } 248 249 function checkValue(el) { 250 var p = el.parentNode; 251 if (el.type === "checkbox" || el.type === "radio") { 252 if (el.checked) p.classList.add("has-content"); 253 else p.classList.remove("has-content"); 254 } 255 else if (el.value || el.placeholder) p.classList.add("has-content"); 256 else p.classList.remove("has-content"); 257 258 var tests = el.dataset.validate, msgs = el.form.dataset.customMessages; 259 if (tests || msgs) { 260 el.setCustomValidity(""); 261 setTimeout(function () { 262 if (el.validity.valid) { if (tests) validate(el, tests); } 263 else if (msgs) setCustomMessage(el, msgs); 264 setErr(el); 265 }, 20); 266 } 267 else setErr(el); 268 } 269 function validate(el, tests) { 270 var arr = getFunctions(tests), i; 271 for (i = 0; i < arr.length; ++i) { 272 var msg = arr[i].call(el, el.value); 273 if (typeof (msg) === "string") return el.setCustomValidity(msg); 274 } 275 } 276 function checkValidity(elems, showAll) {
277 var valid = true, i, el, err; 278 for (i = 0; i < elems.length; ++i) { 279 if ((el = elems[i]).validity.valid) continue; 280 if (!showAll) return false; 281 if (valid === true) { 282 if (Forms.Util.scrollIntoView) Forms.Util.scrollIntoView(el); 283 else el.scrollIntoView(); 284 } 285 valid = false; 286 errNode(el).textContent = el.validationMessage; 287 } 288 return valid; 289 } 290 function setCustomMessage(el, gName) { 291 var cust = Forms.messages[gName] || Forms.messages; 292 var state = el.validity, k, msg; 293 for (k in state) { 294 if (state[k] !== true || !(msg = cust[k])) continue; 295 if (typeof (msg) === "object") msg = msg[el.name] || msg["*"]; 296 if (typeof (msg) === "function") msg = msg(el); 297 if (msg) el.setCustomValidity(msg); 298 } 299 } 300 function setErr(el) { 301 var p = el.parentNode, msg = el.validationMessage; 302 if (p) { 303 if (msg) p.classList.add("has-error"); 304 else p.classList.remove("has-error"); 305 } 306 if (el.errNode) el.errNode.textContent = msg; 307 } 308 function errNode(el) { 309 if (el.errNode) return el.errNode; 310 var err = Forms.errNode || "error"; 311 if (typeof (err) === "string") { 312 var cls = err; err = document.createElement("DIV"); err.className = cls; 313 err.onclick = function (ev) { this.remove(); el.errNode = null; }; 314 } 315 else err = err.cloneNode(); 316 el.parentNode.appendChild(err); 317 return (el.errNode = err); 318 } 319 function getValue() { 320 var form = this, elems = form.elements, data = {}, i, v, m; 321 for (i = 0; i < elems.length; ++i) { 322 var el = elems[i]; 323 if (el.type === "checkbox" || el.type === "radio") { 324 if (!el.checked) continue; 325 } 326 if (el.getValue) { 327 el.value = el.getValue(); 328 } 329 else if (el.type === "hidden") { 330 if ((m = /^\{\{(.+)\}\}/.exec(el.value))) { 331 v = Forms.Util.lookup(m[1]); 332 if (v === undefined) continue; 333 el.value = v.call ? v.call(v) : v; 334 } 335 } 336 if (el.name && el.name.charAt(0) !== '$') { 337 data[el.name] = el.mask && el.dataset.maskValue ? 338 el.mask.getValue() : 339 el.value; 340 } 341 } 342 return data; 343 } 344 function setValue(data) { 345 var form = this, elems = form.elements, i; 346 for (i = 0; i < elems.length; ++i) { 347 var el = elems[i], v = data[el.name]; 348 if (v === undefined) continue; 349 setInputValue(el, v); 350 } 351 } 352 function setInputValue(el, v) { 353 try { 354 if (el.type === "checkbox" || el.type === "radio") el.checked = (v != null); 355 else if (el.setValue) el.setValue(v); 356 else el.value = v; 357 358 if (el.type != "hidden") 359 el.dispatchEvent(new Event('input', { bubbles: true, cancelable: true })); 360 if (el.tagName == "SELECT") 361 el.dispatchEvent(new Event('change', { bubbles: true, cancelable: true })); 362 } 363 catch (err) { 364 console.error("setInputValue error for " + el.name, err); 365 } 366 } 367 function onInput(ev) { 368 var inp = ev.target; 369 if (inp.type != "radio") checkValue(inp); 370 else { 371 var lst = (inp.form || [])[inp.name]; 372 if (lst) for (var i = 0; i < lst.length; ++i) checkValue(lst[i]); 373 } 374 if (ev.currentTarget.id === 'fuelFileForm') checkValidityForButton(ev.currentTarget); 375 } 376 function onBlur(ev) { 377 var el = ev.target; 378 if (!el.validity.valid) errNode(el).textContent = el.validationMessage; 379 if (ev.currentTarget.id === 'fuelFileForm') checkValidityForButton(ev.currentTarget); 380 } 381 function onFocusin(ev) { 382 ev.target.parentElement.classList.add("has-focus"); 383 if (ev.currentTarget.id === 'fuelFileForm') checkValidityForButton(ev.currentTarget); 384 } 385 function onFocusout(ev) { 386 ev.target.parentElement.classList.remove("has-focus"); 387 if (ev.currentTarget.id === 'fuelFileForm') checkValidityForButton(ev.currentTarget); 388 } 389 function checkIsValidEmailForSfLeadCreation(email){ 390 const InnerDomain = ['corpay.com','fleetcor.com','comdata.com'] 391 const isExternalEmail = !InnerDomain.some(domain => email?.toLowerCase().endsWith(domain)); 392 const isValidFlow = window.fuelFileSource === 'MANUAL'; 393 const isValidForSFLeadCreation = isExternalEmail && isValidFlow; 394 return isValidForSFLeadCreation; 395 } 396 async function onSubmit(ev) { 397 var form = ev.target, target = form.target, action = form.getAttribute("action"); 398 const sfPath = "/bin/fleetcorcom/sfrec"; 399 400 if (!/^(#|\.)/.test(target) && /^#/.test(action)) return; 401 ev.preventDefault(); 402 403 if (form.noValidate && !checkValidity(form.elements, true)) return false;
404 405 var dst = target == "#" ? form : document.querySelector(target); 406 if (dst.classList.contains("in-progress")) { 407 console.warn("Form submit is 'in-progress', new 'submit' request ignored."); 408 return false; 409 } 410 var data = form.getValue(), btn, i; 411 if (action === sfPath) { 412 data.AppMarketingChannel = window.getMarketingChannel(); 413 data.SourceWebsite = window.generateDomain(); 414 }; 415 416 for (i = 0; i < Forms.beforesubmit.length; ++i) { 417 const result = await Forms.beforesubmit[i].call(dst, form, data); 418 if (result === false) return false; 419 } 420 if (form.dataset.beforeSubmit) { 421 var acts = getFunctions(form.dataset.beforeSubmit); 422 for (i = 0; i < acts.length; ++i) { if (acts[i].call(dst, form, data) === false) return false; } 423 } 424 if (form.model) { 425 if (form.model.beforeSubmit && form.model.beforeSubmit(form, data) === false) return false; 426 form.model.setValue(data, form); 427 } 428 429 if (form.dataset.disableSubmitButton) { 430 btn = form.querySelector("button[type='submit']"); 431 if (btn) btn.setAttribute("disabled", "disabled"); 432 } 433 dst.classList.add("submitted"); 434 dst.classList.add("in-progress"); 435 436 function afterSubmit(resp, status) { 437 dst.classList.remove("in-progress"); 438 if (btn) { 439 btn.removeAttribute("disabled"); 440 } 441 if (status != "success") dst.classList.add("failed"); 442 else { 443 dst.classList.add("success"); 444 if (form.model && form.model.afterSubmit) { 445 form.model.afterSubmit(form, data, resp); 446 } 447 if (form.dataset.afterSubmit) { 448 var acts = getFunctions(form.dataset.afterSubmit); 449 for (i = 0; i < acts.length; ++i) acts[i].call(dst, form, data, resp); 450 } 451 Forms.aftersubmit.forEach(function (act) { act.call(dst, form, data, resp); }); 452 } 453 } 454 455 if(form.id === "fuelFileForm"){ 456 await fuelFileAuditFormSubmit(form); 457 dst.classList.remove("in-progress", "submitted"); 458 if (btn) btn.removeAttribute("disabled"); 459 const email = form?.Email?.value; 460 if(!checkIsValidEmailForSfLeadCreation(email)){ 461 return; 462 } 463 } 464 if (/^#/.test(action)) { 465 var s = action.substring(1), f = Forms.Util.lookup(s); 466 if (f && f.call) { 467 f.call(form, data, afterSubmit); 468 if (form.dataset.autoClear) afterSubmit(null, "success"); 469 } 470 else { 471 console.error("form action not found: " + action, data); 472 afterSubmit(null, "failed"); 473 } 474 } 475 else { 476 var opts = { 477 data: data, 478 method: form.method || "POST", 479 complete: function (resp, status) { 480 if (status != "success") console.error(form.action, resp); 481 afterSubmit(resp, status); 482 } 483 }; 484 485 486 if (form.dataset.enctype == "application/json") { 487 opts.data = JSON.stringify(data); 488 opts.contentType = "application/json;charset=UTF-8"; 489 } 490 491 if (data._headers) { 492 opts.headers = data._headers; 493 console.log("[reCAPTCHA] Applying headers to opts:", opts.headers); 494 delete data._headers; 495 } 496 ajax(action, opts); 497 } 498 return false; 499 } 500 501 window.Forms = { 502 init: initForm, 503 setInputValue: setInputValue, 504 checkValidity: checkValidity, 505 checkValue: checkValue, 506 beforesubmit: [], 507 aftersubmit: [], 508 Util: { 509 lookup: function (nm) { return Forms.Util[nm] || window[nm]; } 510 }, 511 messages: {} 512 }; 513 514})(); 515 516 517 518; (function () { 519 520 window.initLexisNexus = function (ln) { 521 var form = ln.form = ln.company.form, mask = form.dataset.lnMask; 522 var addFunc = ln.addTo || addTo; 523 ln.addTo = function () { }; 524 if (mask) { 525 if (mask.indexOf(new Date().getDay()) == -1) return; 526 } 527 else if (top.lnAllow && top.lnAllow(form) === false) { 528 return; 529 } 530 var check = lnCheck.bind(ln); 531 ln.company.addEventListener("blur", check); 532 ln.company.addEventListener("focus", check); 533 if (ln.zipcode) ln.zipcode.addEventListener("blur", check); 534 535 ln.addTo = addFunc; 536 ln.goNext = goNext; 537 ln.setResults = setResults; 538 createPopup(ln); 539 ln.show = function () { this.popup.style.display = ""; }; 540 ln.hide = function () { this.popup.style.display = "none"; }; 541 ln.selectCompany = selectCompany.bind(ln); 542 }; 543 544 function addTo(data) { 545 this.hide(); 546 var company = this.selected; 547 if (!company) { 548 sessionStorage.removeItem("LN-SELECTED"); 549 return; 550 } 551 data.LexisNexusID = company.businessID; 552 data.FederalTaxID = company.tinInfo.TIN; 553 if (company.phoneInfo && company.phoneInfo.Phone10) { 554 data.BusinessPhone = company.phoneInfo.Phone10; 555 } 556 data.PhysicalStreet = getStreet(company.address); 557 data.PhysicalStateCode = company.address.State; 558 data.PhysicalCity = company.address.City; 559 data.PhysicalPostalCode = company.address.Zip5; 560 data.PhysicalCountryCode = "US"; 561 sessionStorage.setItem("LN-SELECTED", JSON.stringify(company)); 562 } 563 function lnCheck() { 564 var v = this.company.value; 565 var z = this.zipcode ? this.zipcode.value : (this.zipvalue || top.zipCode); 566 if (v == this.value && z == this.zipvalue) { 567 //if(this.companies) this.show(); 568 return; 569 } 570 var self = this; 571 572 function processResponse(text, status) { 573 if (status != "success") { 574 console.error("getLexisNexisData failed!", resp); 575 return; 576 } 577 if (v != self.value || (self.zipcode && self.zipcode.value != self.zipvalue)) { 578 return; 579 } 580 var json = typeof (text) === "string" ? JSON.parse(text) : text; 581 582 self.setResults(json.Data.companies); 583 } 584 this.value = v; 585 this.zipvalue = z; 586 587 if (v.length < 3 || z.length != 5) this.setResults(null);
588 else if (this.responseExample) setTimeout( 589 function () { 590 processResponse(/^the$/i.test(self.value) ? 591 self.responseExample : {}, "success"); 592 }, 593 400 594 ); 595 else { 596 var url = "/api/LexisNexis/BusinessSearch"; // "/bin/e2e/getLexisNexisData"; 597 var data = { 598 Company: v, 599 Zipcode: z, 600 UUID: UUID, 601 Page_Name: 'Lexis Nexus', 602 }; 603 604 var request = { 605 url: url, 606 method: "POST", 607 data: JSON.stringify(data), 608 contentType: "application/json", 609 success: processResponse, 610 headers: { 611 'Jwt-Encoder': 'FEE-LN' 612 } 613 }; 614 if (top.grecaptcha && top.grecaptcha.execute && top.RECAPTCHA_SITE_KEY) { 615 top.grecaptcha.ready(function () { 616 top.grecaptcha.execute(top.RECAPTCHA_SITE_KEY).then(function (token) { 617 request.headers["Recaptcha-Response"] = token; 618 request.headers["Site-Key"] = top.RECAPTCHA_SITE_KEY; 619 ajax(request); 620 }); 621 }); 622 } 623 else 624 //console.error("LN requires 'google recaptcha'"); 625 ajax(request); 626 627 // 06-29:: below is the old code that used recaptcha, but it is not needed for now, @Chirayu 628 // var url = "/bin/e2e/getLexisNexisData?companyName="+encodeURIComponent(v)+"&zipCode="+z; 629 // if(window.UUID) url += "&uuid=" + UUID; 630 // var request = { 631 // url: url, 632 // success: processResponse 633 // }; 634 // if(top.grecaptcha && top.grecaptcha.execute && top.RECAPTCHA_SITE_KEY) top.grecaptcha.execute(top.RECAPTCHA_SITE_KEY).then(function(token){ 635 // request.headers = { 636 // "Recaptcha-Response": token, 637 // "Site-Key": top.RECAPTCHA_SITE_KEY, 638 // }; 639 // ajax(request); 640 641 // }); 642 // else ajax(request); //console.error("LN requires 'google recaptcha'"); 643 } 644 } 645 646 function setResults(companies) { 647 this.companies = companies; 648 var results = this.popup.childNodes[1]; 649 results.innerHTML = ""; 650 651 if (companies) for (var i = 0; i < companies.length; ++i) { 652 var company = companies[i], address = company.address; 653 if (address) { 654 var elem = document.createElement("DIV"); 655 elem.className = "ln-company"; 656 elem.dataset.index = i; 657 elem.innerHTML = [ 658 "<h4>", escapeHTML(company.companyNameInfo.CompanyName), "</h4>", 659 "<div>", 660 getStreet(address), "</div><div>", 661 address.City, ", ", 662 address.State, ", ", 663 address.Zip5, 664 "</div>" 665 ].join(''); 666 elem.addEventListener("click", this.selectCompany); 667 results.appendChild(elem); 668 } 669 } 670 if (companies && companies.length) { 671 setPosition(this.popup.style, this.company); 672 this.show(); 673 } 674 else this.hide(); 675 } 676 function getStreet(addr) { 677 return [ 678 addr.StreetNumber, 679 addr.StreetPreDirection, 680 addr.StreetName, 681 addr.StreetSuffix 682 ].filter(function (e) { return !!e; }).join(' '); 683 } 684 function createPopup(ln) { 685 var popup = ln.popup = document.createElement("DIV"); 686 popup.className = "ln-popup"; 687 popup.style = "position:absolute; display:none"; 688 popup.innerHTML = [ 689 "<div class='ln-header'>We found one or more business(es) based on the info you provided. Is one of these yours?</div>", 690 "<div class='ln-results'></div>", 691 "<div class='ln-footer'><i></i><span></span></div>" 692 ].join(''); 693 setTimeout(function () { 694 popup.lastChild.addEventListener("click", goNext.bind(ln)); 695 }, 50); 696 var p = ln.company.offsetParent || ln.company.parentElement; 697 p.appendChild(popup); 698 } 699 function selectCompany(ev) { 700 var c = this.companies[ev.currentTarget.dataset.index]; 701 var name = c.companyNameInfo.CompanyName; 702 this.selected = c; 703 this.value = name; 704 if (this.setValue) this.setValue(name); else this.company.value = name; 705 this.goNext(); 706 } 707 function goNext() { 708 this.hide(); 709 var form = this.form, company = this.company; 710 for (var i = 0; i < form.elements.length; ++i) { 711 if (form.elements[i] == company) { 712 var next = form.elements[i + 1]; 713 if (next) next.focus(); 714 break; 715 } 716 } 717 } 718 function escapeHTML(s) { 719 return s.replace(/[&<"']/g, m => '&#' + m.charCodeAt(0) + ';'); 720 } 721 function setPosition(s, company) { 722 s.left = company.offsetLeft + "px"; 723 s.width = company.offsetWidth + "px"; 724 s.top = (company.offsetTop + company.offsetHeight) + "px"; 725 } 726 727})(); 728 729 730var isEditor = (top != window && top.location.href.indexOf("editor.html")!=-1); 731 732document.addEventListener("DOMContentLoaded", function() { 733 var frms = document.querySelectorAll(".cmp-form"); 734 for(var i=0; i<frms.length; ++i) Forms.init(frms[i]); 735 736 if(top.location.search.includes("utm_")) document.addEventListener("pointerdown",ev=>{ 737 var a = ev.target, href; 738 if(a.tagName != "A") a = a.parentNode; 739 if(a.tagName != "A" || !(href=a.getAttribute("href"))) return; 740 // ignore external or in-page or phone links or already transformed 741 if(/#|tel:|utm_|\.pdf|\/content\/dam/.test(href) || /^(https?:)\/\//.test(href)) return; 742 var prms = new URLSearchParams(top.location.search), qs = new URLSearchParams(); 743 for(let [k,v] of prms.entries()) { 744 if(k.startsWith("utm_")||/^(MarketingID)$/.test(k)) qs.append(k,v); 745 } 746 a.setAttribute("href", href+(href.includes('?')?'&':'?')+qs.toString()); 747 }); 748}); 749 750InputMask.map({ 751 '#': /[0-9]/, 752 'A': function(c) { return /[a-zA-Z]/.test(c) && c.toUpperCase(); } 753}); 754 755Forms.errNode = "errorfield"; 756 757Forms.messages = { 758 patternMismatch: function(el) { 759 return el.dataset.patternMismatch || 760 "Please match the requested format"+(el.title ? ": "+el.title : ""); 761
762 }, 763 valueMissing: function(el){ 764 return el.dataset.valueMissing || (el.parentNode.querySelector("SPAN") 765 .textContent.replace(/ ?[\*:]/,"")+" is required"); 766 }, 767 rangeUnderflow: function(el) { 768 return el.dataset.rangeUnderflow || 769 "Please match the requested range"+(el.title ? ": "+el.title : ""); 770 } 771}; 772 773Forms.Util.notBlank = function(v) { 774 if(v.length > 0 && v.trim().length === 0) 775 return "value should not be blank"; 776}; 777Forms.Util.smsVisibility = function(form) { 778 var sms = form.querySelector(".sms-opt-group"); 779 if(sms && form.$phoneType) 780 form.$phoneType.addEventListener("change", function(ev){ 781 if(this.value == "Mobile") sms.classList.remove("hidden"); 782 else sms.classList.add("hidden"); 783 }); 784}; 785Forms.Util.validFlag = function(form) { 786 form.addEventListener("input",function(ev){ 787 var el = ev.target, valid = el.validity.valid, cls = el.parentNode.classList; 788 if(valid != cls.contains("valid")) { 789 if(valid) cls.add("valid"); else cls.remove("valid"); 790 } 791 }); 792}; 793Forms.Util.mobileCheck = function(form, data) { 794 if((!form.$phoneType) || form.$phoneType.value == "Mobile") { 795 data.MobileNumber = data.Phone; 796 } 797 else { 798 delete data.SMS_Allowed; 799 } 800}; 801Forms.Util.utmParams = function(form, data) { 802 var prms = new URLSearchParams(top.location.search); 803 if(prms.has("utm_source")) data.UTMSource = prms.get("utm_source"); 804 if(prms.has("utm_medium")) data.UTMMedium = prms.get("utm_medium"); 805 if(prms.has("utm_campaign")) data.UTMCampaign = prms.get("utm_campaign"); 806 if(prms.has("utm_term")) data.UTMTerm = prms.get("utm_term"); 807 if(prms.has("utm_content")) data.UTMContent = prms.get("utm_content"); 808 if(prms.has("MarketingID")) data.MarketingID = prms.get("MarketingID"); 809}; 810 811Forms.beforesubmit.push(function(form, data) { 812 if (!form.action.includes("/bin/fleetcorcom/sfrec")) { 813 return; 814 } 815 816 if (!top.grecaptcha || !top.grecaptcha.execute || !top.RECAPTCHA_SITE_KEY) { 817 console.warn("[reCAPTCHA] Not ready - grecaptcha or site key missing"); 818 return; 819 } 820 821 822 return top.grecaptcha.execute(top.RECAPTCHA_SITE_KEY, { action: "submit" }) 823 .then(function(token) { 824 data._headers = { 825 ...(data._headers || {}), 826 "Recaptcha-Response": token, 827 "Site-Key": top.RECAPTCHA_SITE_KEY 828 }; 829 }) 830 .catch(function(err) { 831 console.error("[reCAPTCHA] Error during execution:", err); 832 return false; // Prevent submit on error 833 }); 834}); 835 836 837 838 839 840 841 842 843 844Forms.Util.applyLexisNexus = function(form) { 845 if(!window.initLexisNexus) return; 846 var ln = window["ln-"+form.name] = { 847 company: form.Company, 848 zipcode: form.PostalCode || form.ZipCode 849 }; 850 initLexisNexus(ln); 851 Forms.beforesubmit.push(function(aForm,data){ 852 if(aForm === form) ln.addTo(data); 853 }); 854}; 855Forms.Util.storeData = function(form,data) { 856 sessionStorage.setItem((form.name||"FORM").toUpperCase(), 857 JSON.stringify(data)); 858}; 859Forms.Util.trackSubmitEvent = 860Forms.Util.analyticsOnSubmit = function(form,data) { 861 if(! top.appEventData) return; 862 var obj = Forms.Util.analyticsData(data, window.analyticsMap); 863 if(data.Company) { 864 obj.bizListed = (data.LexisNexusID !== undefined); 865 if( top.productId) obj.productId = productId; 866 if(!obj.SMS_Allowed) obj.SMS_Allowed = "false"; 867 if(form.$phoneType) { 868 obj.phoneType = form.$phoneType.value || "Not Selected"; 869 } 870 //obj.transactionId = data.UUID; 871 } 872 top.appEventData.push({ 873 event: (form.name ? "form-"+form.name : (form.id||"form"))+"-xhr-submit", 874 form: obj 875 }); 876}; 877Forms.Util.analyticsData = function(data,map) { 878 if(!map) map = { 879 "UUID": "uuid", 880 "Total_Vehicles__c": "vehicles", 881 "NumberOfVehicles": "vehicles", 882 "vehicles": "vehicles_selected", 883 "Company": "company", 884 "LOB": "lob" 885 }; 886 var obj = {}, m; 887 for(var k in data) if((m = map[k]) !== "-") obj[m||k] = data[k]; 888 if(obj.vehicles) { 889 obj.vehicles = Number(obj.vehicles); 890 } 891 if(obj.Email) { 892 Forms.Util.analyticsEmail(obj); 893 } 894 const company = (obj.company || "").toLowerCase(); 895 const lob = (obj.lob || "").toUpperCase(); 896 897 if (company && lob) { 898 const napKeywords = [ 899 "landscap", "plumb", "hvac", "construc", "util", "energ", "excav", "tow", "concret", "recover", "metal", 900 "equip", "roof", "mechan", "system", "heat", "engin", "fenc", "steel", "suppli", "air", "electr", "tire", 901 "restor", "weld", "commerci", "mover", "builder", "ltd", "door", "motor", "drywall", "instal", "floor", 902 "applianc", "power", "secur", "remodel", "window", "lawn", "renov", "repair", "llc", "inc", "corp", 903 "service", "home", "enterpris", "logistic", "auto", "contract", "interior", "farm", "limo", "pest", 904 "paint", "sanitation", "management", "mobile", "build", "rental" 905 ]; 906 907 const natKeywords = [ 908 "truck", "haul", "carrier", "tran", "ship", "distrib", "deliver", "solution", "freight", "fleet",
909 "cargo", "line", "express", "interstate", "nation", "logistic", "expedit", "courier", "transport" 910 ]; 911 912 let keywords = []; 913 914 if (lob === "NAP") { 915 keywords = napKeywords; 916 } else if (lob === "NAT") { 917 keywords = natKeywords; 918 } else { 919 keywords = [...napKeywords, ...natKeywords]; 920 } 921 922 if (company && keywords.length > 0) { 923 const matchFound = keywords.some(k => company.includes(k)); 924 obj.kwGroup = matchFound ? "1" : "0"; 925 } 926 } 927 return obj; 928}; 929 930Forms.Util.analyticsEmail = function(obj) { 931 // To check for the the list of public domains 932 const domainRegex = /^[a-zA-Z0-9._%+-]+@(gmail\.com|yahoo\.com|hotmail\.com|outlook\.com|icloud\.com|aol\.com|comcast\.net|att\.net|live\.com|msn\.com|ymail\.com|sbcglobal\.net|mail\.com|me\.com|bellsouth\.net|protonmail\.com|verizon\.net|rocketmail\.com|gmail\.con|cox\.net)$/; 933 const extractDomainRegex = /(?<=@)([a-zA-Z0-9.-]+)/; 934 var email = obj.Email; 935 if(email) try { 936 var mailType = ""; 937 var mailDomain = ""; 938 mailType = domainRegex.test(email.toLowerCase()) ? "public" : "private"; 939 940 // To extract the domains from the mail id 941 const match = email.match(extractDomainRegex); 942 if (match) { 943 mailDomain = match[0]; 944 } else { 945 console.log("No domain found."); 946 } 947 obj.mailType = mailType; 948 obj.mailDomain= mailDomain; 949 } 950 catch(err) { 951 console.error(err); 952 } 953 954} 955 956Forms.Util.saveUUID = function (form, data, resp) { 957 if(resp.status >=200 && resp.status < 300) { 958 localStorage.setItem('UUIDREC', data.UUID); 959 } 960}; 961 962Forms.Util.analyticsThankYou = function(form,data,resp) { 963 try { 964 var view = 965 resp.status >= 200 && resp.status < 300 ? "Thank You" : "Failed"; 966 var adobe = top.adobe; 967 if(adobe && adobe.target) adobe.target.triggerView(view ); 968 if(top.debug) console.log("triggerView "+view); 969 } 970 catch(err) { 971 if(top.debug) console.error(err); 972 } 973}; 974 975 976function asArray(a) { 977 var b=[],i; 978 if(a) for(i=0; i<a.length; ++i) b.push(a[i]); 979 return b; 980} 981function lookup(obj,s,act){ 982 var i,o,k; 983 while((i = s.indexOf('.')) !=-1) { 984 if((o=obj[k=s.substring(0,i)]) == undefined) { 985 if(act) o = obj[k] = {}; else return; 986 } 987 obj = o; 988 s = s.substring(i+1); 989 } 990 return act ? act(obj,s) : obj[s]; 991} 992function locate(el,s) { 993 if(!s) return el; 994 if(s.charAt(0)=='/') return document.body.querySelector(s.substring(1)); 995 var i,o,ss; 996 while(/^\.\.\//.test(s)) { el = el.parentNode; s = s.substring(3); o = true; } 997 if(s == "+") return el.nextElementSibling; 998 if((i=s.lastIndexOf('/')) !=-1 ) { 999 if(o === true) { ss=s; s=""; } 1000 else { ss = s.substring(i+1); s = s.substring(0,i);} 1001 } 1002 if(s!==""&&s!== ".") el = el.closest(s); 1003 return ss && el ? el.querySelector(ss) : el; 1004} 1005function playVideo(el) { 1006 var video = el.firstChild; 1007 if(el.classList.contains("active") || (video.autoplay && !video.paused)) return; 1008 el.classList.add("active"); 1009 video.play(); video.controls = true; 1010} 1011 1012window.generateGUID = Util.generateGUID = function b(a) { 1013 return a ? (a ^ Math.random() * 16 >> a / 4).toString(16) : ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, b); 1014}; 1015 1016window.getOrCreateUUID = function() { // Using in fuel-file 1017 if (!window.UUID) { 1018 window.UUID = crypto.randomUUID(); 1019 } 1020 return window.UUID; 1021 }; 1022 1023Util.callAction = function(el,ev) { 1024 var a = el.dataset.action, e, cmd; 1025 if(! a) return; 1026 if( ev) ev.stopPropagation(); 1027 e = locate(el,el.dataset.target); 1028 if(a.charAt(0) === ".") 1029 (e||el.parentNode.parentNode).classList.toggle(a.substring(1)); 1030 else { 1031 if(typeof(cmd=e[a])==="function") return cmd.call(e,el); 1032 if((cmd = Util[a])) return cmd.call(Util,e); 1033 if((cmd = window[a]) && cmd.call) cmd(e); 1034 } 1035}; 1036Util.initComponents = function(prnt) { 1037 var elms = prnt.querySelectorAll("[data-component]"),el,i,j,s,ls,a; 1038 var comps = Util.components||Util; 1039 for(i=0;i<elms.length;++i) { 1040 if((s=(el=elms[i]).dataset.component)) { 1041 ls = s.split(","); 1042 for(j=0; j < ls.length; ++j) { 1043 s = ls[j].trim(); 1044 if((a=comps[s]||window[s])&&a.call) try{ a(el); } 1045 catch(err) { console.error(err); } 1046 } 1047 } 1048 else if(el.onmousedown) try{ el.onmousedown({target:el}); } 1049 catch(err) { console.error(err); } 1050 } 1051}; 1052Util.updateDOM = function(el,data) { 1053 var lst = el.querySelectorAll("[data-name]"); 1054 for(var i=0;
1054i<lst.length;++i) { 1055 var e = lst[i], s = e.dataset.name, o = data, j=s.indexOf('.'), t; 1056 if(s.charAt(0)=='/' && j != -1 && (t = lookup(window,s.substring(1,j)))) { 1057 if(t) { o = t.value||t; s = s.substring(j+1); j = s.indexOf('.'); } 1058 } 1059 while(o && j != -1) { 1060 o = o[s.substring(0,j)]; 1061 j = (s = s.substring(j+1)).indexOf('.'); 1062 } 1063 if(o) { 1064 if(e.dataset.format == "html") e.innerHTML = o[s]||""; 1065 else e.textContent = o[s]||""; 1066 } 1067 } 1068}; 1069Util.delayedCall = function(act,dftm ) { 1070 var id = null; 1071 function call(){ id=null; act() } 1072 function cancel(){ id && clearTimeout(id); id = null; } 1073 function F(tm) { 1074 if (!id) id = setTimeout(call, tm*1 || dftm); 1075 } 1076 F.cancel = cancel; 1077 F.schedule = F; 1078 F.now = () => { cancel(); act(); } 1079 F.delay = tm => { id && clearTimeout(id); id = setTimeout(call, tm*1 || dftm); } 1080 F.isPending = () => id; 1081 return F; 1082}; 1083Util.autohide = function(el,hideAct) { 1084 function stop(ev) { ev.stopPropagation(); ev.preventDefault(); } 1085 function hide(ev) { 1086 if(ev && ev.type == "keydown" && ev.key != "Escape") return; 1087 if(hideAct) hideAct(el); else Util.hide(el); 1088 el.removeEventListener("click",stop); 1089 document.removeEventListener("click",hide); 1090 document.removeEventListener("keydown",hide); 1091 } 1092 el.addEventListener("click",stop); 1093 document.addEventListener("click",hide); 1094 document.addEventListener("keydown",hide); 1095 return hide; 1096}; 1097 1098 1099 1100(function() { 1101 1102Util.show = function(el) { 1103 if(el.model) el.model.setValue(true,el); 1104 if(el.show) return el.show(); 1105 el.style.display=""; 1106 var s = el.dataset.animateClass; 1107 if(s) setTimeout(function(){ 1108 if(s.charAt(0)!="!") el.classList.add(s); 1109 else el.classList.remove(s.substring(1)); 1110 },10); 1111}; 1112 1113Util.hide = function(el) { 1114 if(el.model) el.model.setValue(false,el); 1115 if(el.hide) return el.hide(); 1116 var s = el.dataset.animateClass; 1117 if(!s) { el.style.display="none"; return; } 1118 if(s.charAt(0)!="!") el.classList.remove(s); 1119 else el.classList.add(s.substring(1)); 1120 setTimeout(function(){ 1121 el.style.display="none"; 1122 },parseInt(el.dataset.animateDuration)||750); 1123}; 1124 1125Util.hideOrShow = function(el) { 1126 if(el.style.display == "none") Util.show(el); else Util.hide(el); 1127}; 1128 1129Util.menu= function() { 1130 var m = document.getElementById("mobile-menu"); 1131 if(! m) return; 1132 if(document.body.classList.toggle("mobile-menu-active")) 1133 Util.show(m); 1134 else 1135 Util.hide(m); 1136 var b = document.getElementById("mobile-menu-btn"); 1137 if(b) b.classList.toggle("active"); 1138}; 1139 1140})(); 1141(function(){ 1142 1143 1144function Model(v) { 1145 this.views = new Set(); 1146 if(v !== undefined) this.value = v; 1147} 1148Model.prototype.setValue = function(v,vw) { 1149 this.value = v; 1150 this.views.forEach(function(view) { 1151 if(view !== vw) setValue(view,v); 1152 }); 1153}; 1154Model.prototype.add = function(vw) { 1155 this.views.add(vw); 1156 if(typeof(vw)==="object") vw.model = this; 1157}; 1158 1159function setValue(view,v) { 1160 if(typeof(view) === "function") view(v); 1161 else if(view.setValue) view.setValue(v); 1162 else if (view.type !== "radio") view.value = v; 1163} 1164 1165function addView(vw,setval) { 1166 var el = vw.$el||vw; 1167 var m = getModel(el.dataset.name, el, Model); 1168 if(m) m.add(setval||vw); 1169 return m; 1170} 1171function getModel(nm, el, cls) { 1172 if(!nm) return; 1173 var m, g = window; 1174 if((i=nm.lastIndexOf(':')!=-1)){ 1175 var p = locate(el,nm.substring(0,i)); 1176 if(p) g = p.vars || (p.vars={}); 1177 nm = nm.substring(i+1); 1178 } 1179 lookup(g,nm,function(o,k){ 1180 if(!(m = o[k]) && cls) m = o[k] = new cls(); 1181 if(!m) console.log(o,k); 1182 }); 1183 return m; 1184} 1185Model.get = getModel; 1186 1187function tabs(el) { 1188 tabsContent(el); 1189 1190 function change(ev){ 1191 var e = ev.target, index = 0; 1192 if(e === this) return; 1193 while(e.parentNode != this) e = e.parentNode; 1194 while((e = e.previousElementSibling)) ++index; 1195 if(this.dataset.toggle == "true" && index == this.getValue()) index = -1; 1196 (this.model||this).setValue(index); 1197 } 1198 el.addEventListener("click", change); 1199 if(el.dataset.onOver) el.addEventListener("mouseover", change); 1200} 1201 1202function tabsContent(el) { 1203 el.setValue = tabsSetIndex; 1204 el.getValue = tabsGetIndex; 1205 if(el.dataset.name) addView(el); 1206} 1207 1208function state(el) { 1209 if(el.dataset.stateAction && !window.isEditor) { 1210 var act = hideContent.bind(el), m = addView(el,act); 1211 el.container = el.parentNode; 1212 if(m) act(m.value); 1213 } 1214 if(el.dataset.stateClass) addView(el,setState.bind(el)); 1215 if(el.tagName === "SELECT") { 1216 addView(el); 1217 if(el.model) { 1218 el.addEventListener("change",function(){ 1219 this.model.setValue(this.value,this); 1220 }); 1221 el.model.value = el.value; 1222 } 1223 } 1224 if(el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) { 1225 addView(el); 1226 if(el.model) { 1227 function modelValue() { 1228 if(el.dataset.invertValue) return el.checked ? undefined : el.value; 1229 else return el.checked ? el.value : undefined; 1230 }; 1231 el.addEventListener("change",function(){ 1232 this.model.setValue(modelValue(),this); 1233 }); 1234 el.model.value = modelValue(); 1235 } 1236 } 1237} 1238 1239function popup(el) { 1240 if(! el.dataset.name) return; 1241 el.setValue = function(v) { if(v) Util.show(this); else Util.hide(this); }; 1242 el.getValue = function() { return el.style.display !== "none"; }; 1243 addView(el); 1244} 1245 1246function form(el) { 1247 Forms.init(el); 1248 if(el.dataset.name) addView(el); 1249} 1250function text(el) { 1251 addView(el, function(data){Util.updateDOM(el,data);} ); 1252} 1253
1254/////////// 1255function visibleTabs(el){ 1256 var lst = el.children, elems = []; 1257 for(i=0; i < lst.length; ++i) { 1258 if(lst[i].offsetParent) elems.push(lst[i]); 1259 } 1260 return elems; 1261} 1262function tabsSetIndex(index) { 1263 var v = this.getValue(), e; 1264 if(v != index) { 1265 var tabs = visibleTabs(this); 1266 if((e=tabs[v])) e.classList.remove("active"); 1267 if((e=tabs[index])) e.classList.add("active"); 1268 } 1269} 1270 1271function tabsGetIndex(){ 1272 var lst = visibleTabs(this), i; 1273 for(i=0; i < lst.length; ++i) { 1274 if(lst[i].classList.contains("active")) return i; 1275 } 1276} 1277 1278function isEmpty(v) { 1279 if(Array.isArray(v)) return v.length == 0; 1280 for(var k in v) return false; 1281 return true; 1282} 1283 1284function setState(v) { 1285 var d = this.dataset, vv = d.value, cls= d.stateClass; 1286 var el = locate(this,d.target) || this; 1287 if(d.field) v = lookup(v,d.field); 1288 if(cls.charAt(0) == '@') { 1289 var key = cls.substring(1), cmd = el[key] || Util[key] || window[key]; 1290 if(cmd) cmd.call(this,v,el); 1291 } 1292 else { 1293 var active = vv ? v == vv : (typeof(v) === "object" ? !isEmpty(v): v); 1294 if(cls.charAt(0) == "!") { 1295 active = !active; 1296 cls = cls.substring(1); 1297 } 1298 if(active) el.classList.add(cls); else el.classList.remove(cls); 1299 } 1300} 1301function hideContent(v) { 1302 var d = this.dataset, vv = d.value; 1303 var active = vv ? v == vv : (typeof(v) === "object" ? !isEmpty(v): v); 1304 if(d.stateAction == "hide") active = !active; 1305 //console.log(d.name,v,vv,active); 1306 if(this.container) { 1307 if(active) { 1308 this.container.append(this); 1309 this.container.style.display = ""; 1310 } 1311 else { 1312 this.remove(); 1313 this.container.style.display = "none"; 1314 1315 } 1316 } 1317} 1318function action(el) { 1319 if(el.dataset && el.dataset.action) el.addEventListener("click", function(ev){ 1320 if(ev.target !== this && ev.target.parentNode !== this) 1321 Util.callAction(this,ev); 1322 }); 1323} 1324 1325Object.assign(Util.components = {} ,{ 1326 tabs: tabs, 1327 tabsContent: tabsContent, 1328 state: state, 1329 popup: popup, 1330 form: form, 1331 text: text, 1332 action: action, 1333}); 1334 1335window.Model = Model; 1336 1337})(); 1338 1339Forms.Util.lookup = function(nm) { 1340 return Forms.Util[nm] || lookup(window,nm); 1341}; 1342 1343document.addEventListener("DOMContentLoaded", function() { 1344 Util.initComponents(document); 1345 1346 // A #-clicks 1347 document.addEventListener("click",function(ev){ 1348 var a = ev.target; 1349 if(a.tagName==="A") aClick(); 1350 if(a.dataset.action) Util.callAction(a,ev); 1351 if((a=a.parentNode)) { 1352 if(a.tagName==="A") aClick(); 1353 if(a.dataset && a.dataset.action) Util.callAction(a,ev); 1354 } 1355 function aClick() { 1356 var s = a.getAttribute("href"); 1357 if( s==="#") ev.preventDefault(); 1358 if(/^tel:\d$/.test(s)) a.href="tel:"+a.textContent.replace(/[^0-9]/g,""); 1359 } 1360 }); 1361 1362 // Copyright auto-adjust 1363 elem = document.getElementById("cp-year"); 1364 if(elem) elem.innerHTML = new Date().getFullYear(); 1365 1366 window.dispatchEvent(new Event('fleetcor.foundation.loaded')); 1367}); 1368 1369document.addEventListener("DOMContentLoaded", function () { 1370 var referrer = document.referrer; 1371 var currentDomain = window.location.hostname; 1372 if ( 1373 referrer && 1374 !localStorage.getItem('siteRef') && 1375 !(new URL(referrer).hostname === currentDomain) 1376 ) { 1377 localStorage.setItem('siteRef', referrer); 1378 } 1379}); 1380 1381document.addEventListener("DOMContentLoaded", function () { 1382 const form = document.querySelector(".contact-us-form"); 1383 if (!form) return; 1384 1385 let formWrapper = document.querySelector(".contact-us-wrapper"); 1386 1387 if (!formWrapper) { 1388 formWrapper = document.createElement("div"); 1389 formWrapper.classList.add("contact-us-wrapper"); 1390 1391 form.parentNode.insertBefore(formWrapper, form); 1392 formWrapper.appendChild(form); 1393 } 1394 1395 const hiddenField = form.querySelector('input[name="LeadSourceDetail"]'); 1396 if (!hiddenField || !hiddenField.value) return; 1397 1398 // Get first string (before first space) 1399 const firstValue = hiddenField.value.trim().split(" ")[0]; 1400 const cleanedValue = firstValue.replace(/[^a-zA-Z0-9]/g, "") 1401 1402 const uniqueId = `lead-${cleanedValue}-01`; 1403 1404 formWrapper.setAttribute("data-track-click-label", "Lead_form"); 1405 formWrapper.setAttribute("data-lead-form-uid", uniqueId); 1406 1407 const formInfoObj = { 1408 leadLocation: document.location.href, 1409 formType: "Salesforce", 1410 leadType: "contact_us", 1411 leadFormUID: formWrapper.dataset.leadFormUid 1412 }; 1413 1414 const observer = new IntersectionObserver((entries) => {
1415 entries.forEach(entry => { 1416 if (entry.intersectionRatio === 1) { 1417 window.appEventData = window.appEventData || []; 1418 window.appEventData.push({ 1419 event: "form-contact-us-xhr-view", 1420 form: formInfoObj 1421 }); 1422 1423 observer.disconnect(); 1424 } 1425 }); 1426 }, { 1427 threshold: 1.0 1428 }); 1429 1430 observer.observe(form); 1431}); 1432document.addEventListener("DOMContentLoaded", () => { 1433 1434 const showBanner = window.SITE_CONFIG?.showBanner ?? false; 1435 const message = window.SITE_CONFIG?.notificationMsg ?? ""; 1436 1437 if (showBanner && message.trim() !== "") { 1438 injectBanner(message); 1439 adjustFixedElements(); 1440 window.addEventListener("resize", adjustFixedElements); 1441 } 1442 1443}); 1444 1445/** 1446 * Creates and injects the banner 1447 */ 1448function injectBanner(message) { 1449 if (document.getElementById("fixed-notification-bar")) return; 1450 1451 const banner = document.createElement("div"); 1452 banner.id = "fixed-notification-bar"; 1453 banner.className = "notification-bar"; 1454 banner.innerHTML = `<div class="notification-text">${message}</div>`; 1455 1456 document.body.prepend(banner); 1457} 1458 1459/** 1460 * Offsets ONLY fixed-position elements (headers/navs/etc) 1461 * without touching document flow 1462 */ 1463function adjustFixedElements() { 1464 const banner = document.getElementById("fixed-notification-bar"); 1465 if (!banner) return; 1466 1467 const header = document.querySelector("header"); 1468 if (!header) return; 1469 1470 if (getComputedStyle(header).position === "fixed") { 1471 1472 const headerBottom = header.getBoundingClientRect().bottom; 1473 const bannerHeight = banner.offsetHeight; 1474 1475 let extraOffset = 0; 1476 1477 if (document.body.classList.contains("site-caseys")) { 1478 extraOffset = 33; 1479 } 1480 1481 const finalTop = headerBottom + extraOffset; 1482 1483 banner.style.position = "fixed"; 1484 banner.style.top = `${finalTop}px`; 1485 banner.style.left = "0"; 1486 banner.style.width = "100%"; 1487 banner.style.zIndex = "9999"; 1488 1489 if (document.body.classList.contains("site-caseys")) { 1490 document.body.style.paddingTop = 1491 `${finalTop}px`; 1492 } else { 1493 document.body.style.paddingTop = 1494 `${finalTop + bannerHeight}px`; 1495 } 1496 } 1497} 1498 1499 1500 1501 1502document.addEventListener("DOMContentLoaded", function(){ 1503 1504 function checkHash(ev) { 1505 let hash = location.hash, el; 1506 if( hash) switch(hash.substring(1)) { 1507 1508 case "rec": 1509 recOpenBox({}); 1510 break; 1511 1512 case "contact-us-section": 1513 if((el=document.getElementById("contact-us-section")).offsetWidth < 576) { 1514 showContactUs(); 1515 } 1516 break; 1517 } 1518 } 1519 1520 window.addEventListener("hashchange", checkHash); 1521 checkHash(); 1522}); 1523 1524function showContactUs() { 1525 let el = document.getElementById("contact-us-section"); 1526 el.classList.add("active"); 1527 showBackground(); 1528 el.scrollIntoView(); 1529 1530} 1531function hideContactUs() { 1532 document.getElementById("contact-us-section").classList.remove("active"); 1533 hideBackground(); 1534} 1535 1536function showBackground(id="bg-modal") { 1537 let bg = document.getElementById(id); 1538 if(! bg) { 1539 bg = document.createElement("DIV"); 1540 bg.id = id; 1541 bg.style = "position:fixed;z-index:5;left:0;top:0;bottom:0;right:0;"; 1542 bg.className = "bg-multiply"; 1543 document.body.append(bg); 1544 // bg.onclick = ev => hideBackground(); 1545 } 1546 else bg.style.display = ""; 1547} 1548function hideBackground(id="bg-modal") { 1549 let bg = document.getElementById(id); 1550 if( bg) bg.style.display = "none"; 1551 1552} 1553function mobileMenu(el) { 1554 for (let h4 of el.querySelectorAll(".submenu > h4")) { 1555 h4.addEventListener("click",function(ev) { 1556 this.parentNode.classList.toggle("expanded"); 1557 }); 1558 } 1559} 1560function footerLinks(el) { 1561 for (let h4 of el.querySelectorAll(".links-group > h4")) { 1562 h4.addEventListener("click",function(ev) { 1563 this.parentNode.classList.toggle("expanded"); 1564 }); 1565 } 1566} 1567function stopVideo(el) { 1568 if(el) el.addEventListener("change", ev=>{ 1569 for(let v of ev.target.querySelectorAll("video")) { 1570 if(!v.paused) v.pause(); 1571 } 1572 }) 1573} 1574 1575 1576function carousel(el) { 1577 let slides = [...el.children], N = slides.length, w; 1578 if(window.isEditor || N <= 1) return; 1579 1580 let opts = el.dataset, css = !!opts.useSlides, loop =!!opts.loop; 1581 let n = parseInt(opts.value)||0, observer = new ResizeObserver(setHeight); 1582 if(!css) { 1583 el.style.position="relative"; 1584 el.style.overflow="hidden"; 1585 loop = N == 2 && opts.loop != "false";
1586 slides.forEach((sl,i) => { 1587 sl.style.position="absolute"; 1588 sl.style.top = "0"; }); 1589 } 1590 new ResizeObserver(setWidth).observe(el); 1591 1592 setWidth(); 1593 el.style.scrollBehavior='smooth'; 1594 el.style.transition = "height 500ms ease"; 1595 1596 el.setValue = v => goTo(parseInt(v)||0); 1597 el.goNext = ()=>goTo(n+1 >= N && loop ? 0 : n+1, true); 1598 el.goBack = ()=>goTo(n-1 < 0 && loop ? N-1 : n-1, true); 1599 1600 if(opts.name) 1601 Model.get(opts.name,el,Model).add(el); 1602 1603 function moveSlide(i,x) { 1604 let e = slides[i]; 1605 if(x === 0) { delete e.dataset.slideIndex; e.classList.add("active"); } 1606 else { e.dataset.slideIndex = x; e.classList.remove("active"); } 1607 } 1608 function goTo(p,sync) { 1609 if(p < 0 || p >= N ) return; 1610 observer.unobserve(slides[n]); 1611 observer.observe(slides[p]); 1612 if(css) { 1613 for(let m = N/2.0, i=0; i < N; ++i) { 1614 let x = i-p; 1615 if(loop && x && Math.abs(x) > m) x = (x < 0 ? N : -N) + x; 1616 moveSlide(i,x); 1617 } 1618 el.dataset.dir = n == p ? "" : 1619 slides[n].dataset.slideIndex < 0 ? "right" : "left" ; 1620 1621 el.style.setProperty('--_cs-height', el.style.height); 1622 } 1623 else el.scrollLeft = p*w; 1624 n = p; 1625 setHeight(); 1626 1627 el.dataset.value = n; 1628 el.dispatchEvent(new Event('change')); 1629 if(sync == true && el.model) el.model.setValue(n,el); 1630 } 1631 function setWidth() { 1632 if(el.offsetWidth == w) return; 1633 w = el.offsetWidth; 1634 if(css) el.style.setProperty('--_cs-width',w+"px"); 1635 else slides.forEach((sl,i) => { 1636 sl.style.left = (i*w)+'px'; 1637 sl.style.width = w+'px'; 1638 }); 1639 goTo(n); 1640 } 1641 function setHeight() { 1642 let e = slides[n], h = e.offsetHeight; 1643 el.style.height = h ? h+'px':""; 1644 } 1645 1646 let cX, dX; 1647 1648 function dragStart(ev) { 1649 ev.preventDefault(); 1650 dX = 0; 1651 cX = (ev.changedTouches ? ev.changedTouches[0] : ev).clientX; 1652 this.ontouchmove = drag; 1653 this.ontouchend = dragStop; 1654 } 1655 function drag(ev) { 1656 ev.preventDefault(); 1657 dX = (ev.changedTouches ? ev.changedTouches[0] : ev).clientX-cX; 1658 if(n==0 && dX > 16) dX = 5; 1659 else if(n+1 == slides.length && dX < -16) dX = -5; 1660 if(Math.abs(dX) > 16) dragStop(); 1661 } 1662 function dragStop(ev) { 1663 this.ontouchmove = this.ontouchend = null; 1664 if(dX == 0) ev.target.click(); 1665 else if(Math.abs(dX) > 16) goTo(n-Math.sign(dX),true); 1666 } 1667 if(opts.dragScroll == "allow") el.ontouchstart = dragStart; 1668} 1669 1670function setCarouselState(n, crsl) { 1671 let cls = this.classList, max = crsl.children.length; 1672 if(n <= 0) cls.add("at-start"); else cls.remove("at-start"); 1673 if(n >= max-1) cls.add("at-end"); else cls.remove("at-end"); 1674} 1675 1676function stickyBtn(btn) { 1677 var sbtn = btn.cloneNode(true); 1678 sbtn.style.position = "fixed"; 1679 document.body.appendChild(sbtn); 1680 btn.style.visibility = "hidden"; 1681 function setPos(){ 1682 var rect = btn.getBoundingClientRect(); 1683 sbtn.style.left = rect.left+"px"; 1684 sbtn.style.top = (document.documentElement.scrollTop+rect.top)+"px"; 1685 } 1686 setPos(); 1687 window.addEventListener("resize",setPos); 1688} 1689 1690function recOpenBox(arg) { 1691 var re = document.getElementById("recengine"); 1692 if(!re) { 1693 re = document.createElement("IFRAME"); 1694 re.id = re.name = "recengine"; 1695 re.style = "border:none;display:none;position:fixed; left:0;top:0;width:100%;height:100%;opacity:0;transition:opacity .5s;z-index:999"; 1696 1697 re.src = location.href.indexOf("/content/") == -1 ? "/rec/" : "/content/comdatatrucking/en/rec.html?wcmmode=disabled"; 1698 document.body.append(re); 1699 } 1700 window.zipCode = arg && arg.zip; 1701 1702 if(arg === false) { 1703 re.style.opacity = 0; 1704 window.location.hash = ""; 1705 setTimeout(() => { 1706 re.style.display ="none"; 1707 document.documentElement.style.overflow =""; 1708 }, 350); 1709 } 1710 else { 1711 re.style.display = "block"; 1712 setTimeout(() => re.style.opacity = 1, 50); 1713 document.documentElement.style.overflow ="hidden"; 1714 try { frames.recengine.run(); } catch(err){} 1715 if(!arg.zip && window.appEventData) appEventData.push({ 1716 event: "form-recengine-step-getstarted", 1717 form: { appStep: "getstarted" }, 1718 }); 1719 } 1720} 1721document.addEventListener("DOMContentLoaded", function(){ 1722 window.addEventListener("hashchange", function(){ 1723 if (window.location.hash == "#rec") recOpenBox({}); 1724 }); 1725 if (window.location.hash == "#rec") recOpenBox({}); 1726}); 1727 1728function checkAppCTAs() { 1729 var srch = location.href.indexOf("/connect-card/") != -1 && location.search; 1730 var links = document.body.getElementsByTagName("A"); 1731 for (var i = 0; i < links.length; ++i) { 1732 var a = links[i], 1733 href = a.href, 1734 idx = href.indexOf("/applications/"); 1735 if (idx != -1) { 1736 var qs = sessionStorage.getItem("qs-" + href.substring(idx)); 1737 if (!qs && srch && href.indexOf("/comdata-alt-funding-1130/") != -1) { 1738 sessionStorage.setItem( 1739 "qs-/app/comdata-alt-funding-1130/", 1740 srch.substring(1) 1741 ); 1742 qs = srch.substring(1); 1743 } 1744 if (qs) { 1745 a.href += "?" + qs; 1746 if (a.textContent.indexOf("APPLY NOW") != -1) { 1747 const uuidMatch = location?.search?.match(/uuid=([^&]*)/); 1748 sessionStorage.setItem(`${uuidMatch[1]}-skipLogin`, 'true'); 1749 a.textContent = "CONTINUE TO APPLICATION"; 1750 a.oncontextmenu = function (ev) { 1751 ev.preventDefault(); 1752 }; 1753 } else if (a.textContent.indexOf("GET") != -1) { 1754 a.remove(); 1755 --i; 1756 } 1757 } 1758 } 1759 } 1760} 1761window.addEventListener("DOMContentLoaded", checkAppCTAs); 1762 1763(function () { 1764 'use strict'; 1765 1766 document.addEventListener('DOMContentLoaded', function () { 1767 const carousels = document.querySelectorAll('.logo-carousel'); 1768
1769 carousels.forEach(function (carousel) { 1770 const track = carousel.querySelector('.logo-carousel__track'); 1771 const prevBtn = carousel.querySelector('.logo-carousel__btn--prev'); 1772 const nextBtn = carousel.querySelector('.logo-carousel__btn--next'); 1773 const slides = carousel.querySelectorAll('.logo-carousel__slide'); 1774 1775 let currentIndex = 0; 1776 let itemsPerView = getItemsPerView(); 1777 1778 // Get items per view based on screen width 1779 function getItemsPerView() { 1780 const width = window.innerWidth; 1781 if (width < 768) return 2; 1782 if (width < 1024) return 3; 1783 return 4; 1784 } 1785 1786 // Update carousel position 1787 function updateCarousel() { 1788 const slideWidth = slides[0].offsetWidth; 1789 track.style.transform = 'translateX(-' + (currentIndex * slideWidth) + 'px)'; 1790 updateButtons(); 1791 } 1792 1793 // Update button states 1794 function updateButtons() { 1795 const maxIndex = Math.max(0, slides.length - itemsPerView); 1796 prevBtn.disabled = currentIndex === 0; 1797 nextBtn.disabled = currentIndex >= maxIndex; 1798 } 1799 1800 // Previous button 1801 prevBtn.addEventListener('click', function () { 1802 if (currentIndex > 0) { 1803 currentIndex--; 1804 updateCarousel(); 1805 } 1806 }); 1807 1808 // Next button 1809 nextBtn.addEventListener('click', function () { 1810 const maxIndex = Math.max(0, slides.length - itemsPerView); 1811 if (currentIndex < maxIndex) { 1812 currentIndex++; 1813 updateCarousel(); 1814 } 1815 }); 1816 1817 // Touch swipe 1818 let touchStartX = 0; 1819 track.addEventListener('touchstart', function (e) { 1820 touchStartX = e.touches[0].clientX; 1821 }); 1822 1823 track.addEventListener('touchend', function (e) { 1824 const touchEndX = e.changedTouches[0].clientX; 1825 const diff = touchStartX - touchEndX; 1826 1827 if (Math.abs(diff) > 50) { 1828 if (diff > 0) nextBtn.click(); 1829 else prevBtn.click(); 1830 } 1831 }); 1832
1833 // Window resize 1834 window.addEventListener('resize', function () { 1835 itemsPerView = getItemsPerView(); 1836 currentIndex = 0; 1837 updateCarousel(); 1838 }); 1839 1840 // Initialize 1841 updateButtons(); 1842 }); 1843 }); 1844})(); 1845// sample for testing: 1846// eslint-disable-next-line max-len 1847// https://www.fuelman.com/applications/fuelman-mixed-fleet-pro-453/?utm_medium=PaidSocial&utm_source=Facebook&utm_campaign=FLMN_RTG_Lead_SUBAPP_2024&utm_term=Facebook_Desktop_Feed&utm_content=120229265480270172 1848// UTM_Campaign: "FLMN_RTG_Lead_SUBAPP_2024" 1849// UTM_Content: "120229265480270172" 1850// UTM_Medium: "PaidSocial" 1851// UTM_Source: "Facebook" 1852// UTM_Term: "Facebook_Desktop_Feed" 1853 1854function updateLeadSource(formData, urlParams) { 1855 const leadSource = urlParams.get('referringurl') 1856 || urlParams.get('source'); 1857 const marketingid = urlParams.get('MarketingID') 1858 || urlParams.get('marketingid'); 1859 const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']; 1860 const utmValues = {}; 1861 1862 utmParams.forEach((param) => { 1863 const value = urlParams.get(param); 1864 if (value) { 1865 utmValues[param] = value; 1866 } 1867 }); 1868 1869 const leadFields = { 1870 Lead_Source_Detail: leadSource, 1871 UTM_Source: utmValues.utm_source, 1872 UTM_Medium: utmValues.utm_medium, 1873 UTM_Campaign: utmValues.utm_campaign, 1874 UTM_Term: utmValues.utm_term, 1875 UTM_Content: utmValues.utm_content, 1876 MarketingID: marketingid, 1877 }; 1878 1879 Object.entries(leadFields).forEach(([key, value]) => { 1880 if (value) { 1881 formData[key] = value; 1882 } 1883 }); 1884} 1885 1886function extractTrackingInfo() { 1887 const siteRef = localStorage.getItem('siteRef') || ''; 1888 const referrer = document.referrer || ''; 1889 1890 let urlParams= new URLSearchParams(); 1891 1892 const isRecPage = /^\/rec(\/|$)/.test(window.location.pathname) || /^#\/?rec(\/|$)/.test(window.location.hash); 1893 if(isRecPage && document.referrer !==''){ 1894 try{ 1895 urlParams= new URL(document.referrer).searchParams; 1896 } 1897 catch (e) { 1898 urlParams = new URLSearchParams(window.location.search); 1899 } 1900 } else { urlParams = new URLSearchParams(window.location.search); } 1901 1902 //const urlParams = new URLSearchParams(window.location.search); 1903 1904 const formData = {}; 1905 updateLeadSource(formData, urlParams); 1906 1907 return { 1908 siteRef: siteRef.toLowerCase(), 1909 referrer: referrer.toLowerCase(), 1910 utm: { 1911 source: (formData.UTM_Source || '').toLowerCase(), 1912 medium: (formData.UTM_Medium || '').toLowerCase(), 1913 campaign: (formData.UTM_Campaign || '').toLowerCase(), 1914 term: (formData.UTM_Term || '').toLowerCase(), 1915 content: (formData.UTM_Content || '').toLowerCase(), 1916 }, 1917 }; 1918} 1919 1920// ----------------------------- 1921// Predefined lists 1922// ----------------------------- 1923const paidSearchDomains = [ 1924 'google.com', 'bing.com', 'yahoo.com', 'duckduckgo.com', 1925 'search.goog', 'googlequicksearchbox', 1926]; 1927 1928const paidSearchMediums = ['gclid=', 'cpc', 'ef_id=', 's_kwcidand']; 1929 1930const paidSocialPatterns = [ 1931 'paid social', 'paid+social', 'paid%252520social', 'paid%2520social', 1932 'paid%20social', 'paidsocial', 'paid_social', 'social', 'social_paid', 1933]; 1934 1935const affiliateRefs = [ 1936 'mastercard.us', 'bankrate.com', 'creditcards.com', 'finder.com', 'nav.com', 1937]; 1938 1939const affiliateUTM = ['sponsored_content', 'affiliate', 'affilate']; 1940 1941const organicSocialRefs = [ 1942 'facebook.com', 'xanga.com', 'cafemom.com', 'yuku.com', 'hi5.com', 'bebo.com', 1943 'ning.com', 'brightkite.com', 'tagged.com', 'mylife.com', 'myyearbook.com', 'classmates.com', 1944 'smugmug.com', 'fotolog.com', 'photobucket.com', 'dailymotion.com', 'imeem.com', 1945 'flickr.com', 'jaiku.com', 'identi.ca', 'zooomr.com', '12seconds.tv', 'vimeo.com', 1946 'youtube.com', 'flixster.com', 'diigo.com', 'mister-wong.com', 'netvibes.com', 1947 'backtype.com', 'slideshare.net', 'plurk.com', 'intensedebate.com', 'disqus.com', 1948 'tumblr.com', 'delicious.com', 'mixx.com', 'yelp.com', 'twine.com', 'stumbleupon.com', 1949 'reddit.com', 'digg.com', 'myspace.com', 'friendfeed.com', 'wordpress.com', 'blogspot.com', 1950 'livejournal.com', 'friendster.com', 'orkut.com', 'plus.google.com', 'twitter.com', 'linkedin.com', 1951]; 1952 1953const referringDomains = [ 1954 'fuelman.com', 'fleetcardsusa.com', 'comdata.com', 'arcobusinesssolutions.
1954com', 1955 'bpbusinessolutions.com', 'cp.corpayone.com', 'caseysfleetcard.com', 1956 '7-elevenfleet.com', 'cefcofleet.com', 'kwiktripfleet.com', 'ultramarfleet.ca', 1957 'primeadvantageplus.com', 'comdataemail.com', 1958]; 1959 1960const allowedPrefixes = ['fum', 'fcu','cdt','arco','cpocp','cas','711','cef','kw','ult','e2e']; 1961 1962// ----------------------------- 1963// Rules based on priority 1964// ----------------------------- 1965const rules = [ 1966 1967 { 1968 name: 'Paid Search', 1969 conditions: ({ ref, utm }) => paidSearchDomains.some((d) => ref.includes(d)) 1970 && paidSearchMediums.some((m) => utm.medium.includes(m?.toLowerCase())), 1971 }, 1972 1973 { 1974 name: 'Display', 1975 conditions: ({ ref, utm }) => utm.medium.includes('display') 1976 || utm.source.includes('steelhouse') || ref.includes('doubleclick.net') 1977 || ref.includes('googlesyndication.com'), 1978 }, 1979 1980 { 1981 name: 'Paid Social', 1982 conditions: ({ utm }) => paidSocialPatterns.some((p) => utm.medium.includes(p?.toLowerCase())), 1983 }, 1984 1985 { 1986 name: 'Affiliates', 1987 conditions: ({ ref, utm }) => affiliateRefs.some((d) => ref.includes(d)) 1988 || affiliateUTM.some((m) => utm.medium.includes(m?.toLowerCase())), 1989 }, 1990 1991 // commented video/programmatic/digital radio/sms 1992 // { name: 'video', conditions: ({ utm }) => utm.medium.includes('video') }, 1993 // { name: 'programmatic', conditions: ({ utm }) => utm.medium.includes('programmatic') }, 1994 // { name: 'digital radio', conditions: ({ utm }) => utm.medium.includes('digital_radio') }, 1995 { name: 'Email', conditions: ({ utm }) => utm.medium.includes('email') }, 1996 // { name: 'sms', conditions: ({ utm }) => utm.medium.includes('sms') }, 1997 { name: 'Direct Mail', conditions: ({ utm }) => utm.medium.includes('directmail') }, 1998 1999 { 2000 name: 'Organic Search', 2001 conditions: ({ ref, utm }) => utm.medium.includes('organic') 2002 || ref.includes('android-app://com.google.android.gm') 2003 || (!utm.medium.includes('id=') 2004 && paidSearchDomains.some((d) => ref.includes(d?.toLowerCase()))), 2005 }, 2006 2007 { 2008 name: 'Organic Social', 2009 conditions: ({ ref }) => organicSocialRefs.some((d) => ref.includes(d?.toLowerCase())), 2010 }, 2011 2012 { 2013 name: 'Sales Rep Triggered (EIC)', 2014 conditions: ({ ref }) => ( 2015 ( 2016 ref.includes('fleetcardapplication.com') 2017 || window.location.hostname.replace(/^www\./, '').toLowerCase() === 'fleetcardapplication.com' 2018 // flt-e2e-qa2.fleetcor.com 2019 || ref.includes('flt-e2e-qa2.fleetcor.com') 2020 || window.location.hostname.replace(/^www\./, '').toLowerCase() === 'flt-e2e-qa2.fleetcor.com' 2021 ) 2022 && window.location.href.toLowerCase().includes('uuid=') 2023 ), 2024 }, 2025 2026 2027 { 2028 name: 'Referring Domains', 2029 conditions: ({ ref }) => { 2030 const r = ref.toLowerCase(); 2031 2032 return referringDomains.some((d) =>{ 2033 if (!r.includes('fleetcor.com')) return r.includes(d); 2034 2035 return allowedPrefixes.some(prefix => 2036 r.includes(`-${prefix}-`) && r.endsWith('.fleetcor.com/') 2037 ); 2038 }) 2039 } 2040 }, 2041 2042 { name: 'Direct', conditions: ({ ref }) => !ref }, 2043 2044 { name: 'Session Timeout', conditions: () => true }, 2045]; 2046 2047// ----------------------------- 2048// Main function 2049// ----------------------------- 2050window.getMarketingChannel = function () { 2051 const { siteRef, referrer, utm } = extractTrackingInfo(); 2052 const ref = siteRef || referrer; 2053 2054 for (const rule of rules) { 2055 if (rule.conditions({ ref, utm })) return rule.name; 2056 } 2057 2058 return 'unknown'; // fallback (should not reach) 2059} 2060 2061window.generateDomain = Util.generateDomain = function () { 2062 return window?.location?.hostname?.replace(/^www\./i, ''); 2063}; 2064/** 2065 * Process Flow Component - Clientlib JS 2066 * (Animations disabled/removed as requested) 2067 */ 2068 2069;(function () { 2070 'use strict'; 2071 2072 function initFAQs() { 2073 var faqComponents = document.querySelectorAll('.comdata-faq'); 2074 faqComponents.forEach(function (faq) { 2075 if (faq._faqInitialized) return; 2076 faq._faqInitialized = true; 2077 2078 var detailsElements = faq.querySelectorAll('details.faq-accordion-item'); 2079 detailsElements.forEach(function (details) { 2080 var summary = details.querySelector('summary.faq-accordion-header'); 2081 var content = details.querySelector('.faq-accordion-content'); 2082 if (!summary || !content) return; 2083 2084 summary.addEventListener('click', function (e) { 2085 e.preventDefault(); // Prevent default instant open/close 2086 2087 if (details.classList.contains('is-animating')) return; 2088 details.classList.add('is-animating'); 2089 2090 var isOpen = details.hasAttribute('open'); 2091 2092 if (!isOpen) { 2093 // Open the details element 2094 details.setAttribute('open', 'true'); 2095 details.classList.add('is-open'); 2096 2097 var scrollHeight = content.scrollHeight; 2098 content.style.maxHeight = '0px'; 2099 2100 // Force a reflow 2101 content.offsetHeight; 2102 2103 content.style.maxHeight = scrollHeight + 'px'; 2104 2105 setTimeout(function () { 2106 content.style.maxHeight = 'none'; 2107 details.classList.remove('is-animating');
2108 // Disable tracking after expand so collapse doesn't fire 2109 summary.setAttribute('data-track-click-enabled', 'false'); 2110 }, 300); // Should match CSS transition duration 2111 } else { 2112 // Close the details element 2113 var scrollHeight = content.scrollHeight; 2114 content.style.maxHeight = scrollHeight + 'px'; 2115 2116 // Force a reflow 2117 content.offsetHeight; 2118 2119 content.style.maxHeight = '0px'; 2120 details.classList.remove('is-open'); 2121 2122 setTimeout(function () { 2123 details.removeAttribute('open'); 2124 content.style.maxHeight = 'none'; 2125 details.classList.remove('is-animating'); 2126 // Re-enable tracking so next expand fires 2127 summary.setAttribute('data-track-click-enabled', 'true'); 2128 }, 300); // Should match CSS transition duration 2129 } 2130 }); 2131 2132 // Set initial class for open state if it has open attribute by default 2133 if (details.hasAttribute('open')) { 2134 details.classList.add('is-open'); 2135 // Already expanded, disable tracking so collapse doesn't fire 2136 summary.setAttribute('data-track-click-enabled', 'false'); 2137 } 2138 }); 2139 }); 2140 } 2141 2142 if (document.readyState === 'loading') { 2143 document.addEventListener('DOMContentLoaded', initFAQs); 2144 } else { 2145 initFAQs(); 2146 } 2147})(); 2148 2149(function () { 2150 "use strict"; 2151 2152 document.addEventListener("DOMContentLoaded", function () { 2153 var heroScrollLinks = document.querySelectorAll(".comdata-fuel-cards-hero .hero-scroll-link"); 2154 2155 heroScrollLinks.forEach(function (link) { 2156 link.addEventListener("click", function (event) { 2157 var targetHref = this.getAttribute("href"); 2158 2159 // Check if the link target is an internal anchor link (e.g. #plans) 2160 if (targetHref && targetHref.startsWith("#")) { 2161 var targetElement = document.querySelector(targetHref); 2162 if (targetElement) { 2163 event.preventDefault(); 2164 targetElement.scrollIntoView({ 2165 behavior: "smooth", 2166 block: "start" 2167 }); 2168 } 2169 } 2170 }); 2171 }); 2172 }); 2173})(); 2174 2175;(function () { 2176 'use strict'; 2177 2178 function initFeatures() { 2179 var components = document.querySelectorAll('.comdata-features'); 2180 components.forEach(function (component) { 2181 if (component._featuresInitialized) return; 2182 component._featuresInitialized = true; 2183 2184 // Touch interaction feedback for swipeable cards 2185 var cards = component.querySelectorAll('.features-card'); 2186 cards.forEach(function (card) { 2187 card.addEventListener('touchstart', function () { 2188 this.classList.add('is-touching'); 2189 }, { passive: true }); 2190 2191 card.addEventListener('touchend', function () { 2192 this.classList.remove('is-touching'); 2193 }, { passive: true }); 2194 }); 2195 }); 2196 } 2197 2198 if (document.readyState === 'loading') { 2199 document.addEventListener('DOMContentLoaded', initFeatures); 2200 } else { 2201 initFeatures(); 2202 } 2203})(); 2204 2205;(function () { 2206 'use strict'; 2207 2208 function initRecommendations() { 2209 var components = document.querySelectorAll('.comdata-recommendation'); 2210 components.forEach(function (component) { 2211 if (component._recommendationInitialized) return; 2212 component._recommendationInitialized = true; 2213 2214 var form = component.querySelector('.recommendation-form'); 2215 var input = component.querySelector('.recommendation-input'); 2216 var inputWrapper = component.querySelector('.recommendation-input-wrapper'); 2217 var submitBtn = component.querySelector('.recommendation-submit-btn'); 2218 2219 if (!form || !input || !inputWrapper || !submitBtn) return; 2220 2221 function isZipValid(zip) { 2222 return /^\d{5}
2222$/.test(zip); 2223 } 2224 2225 function showZipError() { 2226 inputWrapper.classList.add('has-error'); 2227 input.setAttribute('aria-invalid', 'true'); 2228 } 2229 2230 function clearZipError() { 2231 inputWrapper.classList.remove('has-error'); 2232 input.removeAttribute('aria-invalid'); 2233 } 2234 2235 function updateSubmitState() { 2236 var isValidZip = isZipValid(input.value.trim()); 2237 submitBtn.disabled = !isValidZip; 2238 submitBtn.setAttribute('aria-disabled', String(!isValidZip)); 2239 } 2240 2241 // Initial button state 2242 updateSubmitState(); 2243 2244 // Restrict input to digits only 2245 input.addEventListener('input', function () { 2246 // Remove non-digit characters 2247 var cleanValue = this.value.replace(/\D/g, ''); 2248 if (this.value !== cleanValue) { 2249 this.value = cleanValue; 2250 } 2251 2252 // Auto-clear error when user types/modifies the field 2253 clearZipError(); 2254 2255 updateSubmitState(); 2256 }); 2257 2258 // Show error on field exit if user entered an invalid ZIP. 2259 input.addEventListener('blur', function () { 2260 var zipcode = input.value.trim(); 2261 if (zipcode.length > 0 && !isZipValid(zipcode)) { 2262 showZipError(); 2263 return; 2264 } 2265 2266 clearZipError(); 2267 }); 2268 2269 // Prevent non-digits in paste events 2270 input.addEventListener('paste', function (e) { 2271 var clipboard = e.clipboardData || window.clipboardData; 2272 var pasteData = clipboard ? clipboard.getData('text') : ''; 2273 if (/\D/.test(pasteData)) { 2274 e.preventDefault(); 2275 var cleanData = pasteData.replace(/\D/g, '').substring(0, 5); 2276 2277 var start = this.selectionStart; 2278 var end = this.selectionEnd; 2279 var val = this.value; 2280 this.value = val.substring(0, start) + cleanData + val.substring(end); 2281 this.setSelectionRange(start + cleanData.length, start + cleanData.length); 2282 2283 // Trigger input listener to handle error clearing if needed 2284 var event = document.createEvent('Event'); 2285 event.initEvent('input', true, true); 2286 this.dispatchEvent(event); 2287 } 2288 2289 updateSubmitState(); 2290 }); 2291 2292 // Form Submit validation 2293 form.addEventListener('submit', function (e) { 2294 var zipcode = input.value.trim(); 2295 var isValidZip = isZipValid(zipcode); 2296 2297 if (!isValidZip) { 2298 e.preventDefault(); 2299 showZipError(); 2300 input.focus(); 2301 } else { 2302 // Push event to data layer 2303 var eventName = submitBtn.getAttribute('data-analytics-event'); 2304 var appStep = submitBtn.getAttribute('data-analytics-app-step'); 2305 2306 window.dataLayer = window.dataLayer || []; 2307 window.dataLayer.push({ 2308 event: eventName || 'form-recengine-step-getstarted', 2309 form: { 2310 appStep: (appStep || 'getstarted').toLowerCase() 2311 } 2312 }); 2313 // Store in sessionStorage for target redirect pages to read 2314 try { 2315 sessionStorage.setItem('comdata_user_zip', zipcode); 2316 } catch (err) { 2317 console.warn('sessionStorage is not accessible:', err); 2318 } 2319 } 2320 }); 2321 }); 2322 } 2323 2324 if (document.readyState === 'loading') { 2325 document.addEventListener('DOMContentLoaded', initRecommendations); 2326 } else { 2327 initRecommendations(); 2328 } 2329})(); 2330
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.