/*jshint esversion: 6*/ if(window.performance.mark) { window.performance.mark('startJSLoad'); } //FUNCTION TO CONVERT POST DATA OBJECTS function postData(data) { return Object.keys(data).map( function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]); }).join('&'); } //SETUP MEDIA QUERIES IN JS var xsDown = window.matchMedia("(max-width:575px)"); //DO OUR INITAL CHECK FOR LAZY LOADING if(window.performance.mark) { window.performance.mark('startLazyLoad'); } //SETUP INTERSECTION OBSERVER CONFIG const config = { root: null, rootMargin: '300px 100% 300px 100%', //300px above & below | 100% left & right threshold: 0 }; //SETUP INTERSECTION OBSERVER FUNCTION let observer = new IntersectionObserver(function(entries, self) { entries.forEach(entry => { //GET THE ACTUAL ELEMENT AND ITS TAG let elem = entry.target; let type = elem.tagName; //LOAD NO MATTER WHERE THEY ARE if(elem.classList.contains("modal")) { let {Modal} = import('/js/bootstrap/bootstrapesm.js'); } else if(elem.classList.contains("toast")){ (async () => { let {Toast} = await import('/js/bootstrap/bootstrapesm.js'); let toastTrigger = document.getElementById('liveToastBtn'); let toastLiveExample = document.getElementById('liveToast'); if (toastTrigger) { toastTrigger.addEventListener('click', function () { var toast = new Toast(toastLiveExample); toast.show(); }); } })(); } //LAZY LOAD ONLY IF COMING INTO VIEW if (entry.isIntersecting) { if(type == "IMG" && (elem.classList.contains("defer-img") || elem.classList.contains("defer_img"))) { loadIMGTAG(elem); } else if(type == "PICTURE" && (elem.classList.contains("defer-img") || elem.classList.contains("defer_img"))) { loadPICTAG(elem); } else if(elem.classList.contains("defer-img") || elem.classList.contains("defer_img")) { loadIMGCSS(elem); } else if(type == "IFRAME" && (elem.classList.contains("defer-iframe") || elem.classList.contains("defer_iframe"))) { loadIFRAME(elem); } else if(type == "VIDEO" && (elem.classList.contains("defer-video") || elem.classList.contains("defer_video"))) { loadVIDEO(elem); } else if(elem.dataset.bsDismiss && elem.dataset.bsDismiss == "alert"){ let {Alert} = import('/js/bootstrap/bootstrapesm.js'); } else if(elem.dataset.bsToggle && (elem.dataset.bsToggle == "button" || elem.dataset.bsToggle == "buttons")){ let {Button} = import('/js/bootstrap/bootstrapesm.js'); } else if(elem.classList.contains("carousel")) { let {Carousel} = import('/js/bootstrap/bootstrapesm.js'); } else if(elem.dataset.bsToggle && elem.dataset.bsToggle == "collapse"){ let {Collapse} = import('/js/bootstrap/bootstrapesm.js'); } else if(elem.dataset.bsToggle && elem.dataset.bsToggle == "dropdown"){ let {Dropdown} = import('/js/bootstrap/bootstrapesm.js'); } else if(elem.dataset.bsToggle && elem.dataset.bsToggle == "popover"){ (async () => { let {Popover} = await import('/js/bootstrap/bootstrapesm.js'); new Popover(elem); })(); } else if(elem.dataset.bsSpy && elem.dataset.bsSpy == "scroll"){ (async () => { let {ScrollSpy} = await import('/js/bootstrap/bootstrapesm.js'); ScrollSpy.getOrCreateInstance(elem); })(); } else if(elem.dataset.bsToggle && elem.dataset.bsToggle == "tab"){ let {Tab} = import('/js/bootstrap/bootstrapesm.js'); } else if(elem.dataset.bsToggle && elem.dataset.bsToggle == "offcanvas"){ let {Offcanvas} = import('/js/bootstrap/bootstrapesm.js'); } else if(elem.dataset.bsToggle && elem.dataset.bsToggle == "tooltip"){ (async () => { let {Tooltip} = await import('/js/bootstrap/bootstrapesm.js'); new Tooltip(elem); })(); } else if (elem.id == "payment-form") { let promise1 = loadScript('StripeJS',('https://js.stripe.com/v3/')); let promise2 = loadScript('FormValidation',(jsMin === true ? '/js/min/formValidationmin.'+jsFingerprint+'.js':'/js/formValidation.'+jsFingerprint+'.js')); Promise.all([promise1,promise2]).then(function(){ loadScript('FormValidationBS5',(jsMin === true ? '/js/min/Bootstrap5min.'+jsFingerprint+'.js':'/js/Bootstrap5.'+jsFingerprint+'.js')).then(() => { getPaymentForm(elem); }); }); } else if(elem.classList.contains("secureForm") || elem.classList.contains("validateForm")) { if(elem.classList.contains("validateForm")) { loadScript('FormValidation',(jsMin === true ? '/js/min/formValidationmin.'+jsFingerprint+'.js':'/js/formValidation.'+jsFingerprint+'.js')).then(function(){ loadScript('FormValidationBS5',(jsMin === true ? '/js/min/Bootstrap5min.'+jsFingerprint+'.js':'/js/Bootstrap5.'+jsFingerprint+'.js')).then(() => { FormValidation.formValidation( elem, { plugins: { trigger: new FormValidation.plugins.Trigger(), submitButton: new FormValidation.plugins.SubmitButton(), defaultSubmit: new FormValidation.plugins.DefaultSubmit(), bootstrap5: new FormValidation.plugins.Bootstrap5({ rowSelector: '.mb-3', }), declarative: new FormValidation.plugins.Declarative() }, } ); }); }); } if(elem.classList.contains("secureForm")) { let spamStopper = document.createElement('input'); spamStopper.type = 'hidden'; spamStopper.name = 'ts'; spamStopper.value = token; elem.appendChild(spamStopper); } } else if(elem.classList.contains("import_static_map")) { swapStaticMap(elem); } else if(elem.classList.contains("before_after_container")){ loadScript('InfoStarBA',(jsMin === true ? '/js/min/infostar_before_aftermin.'+jsFingerprint+'.js':'/js/infostar_before_after.'+jsFingerprint+'.js')); } else if(elem.classList.contains("datepicker")) { loadScript('Datepicker',(jsMin === true ? '/js/min/flatpickrmin.'+jsFingerprint+'.js':'/js/flatpickr.'+jsFingerprint+'.js')).then(function(){ flatpickr(elem, { dateFormat: 'm/d/Y', allowInput: true, onOpen: function() { loadCss('SiteCSS',(jsMin === true ? '/css/sitemin.'+cssFingerprint+'.css':'/css/site.'+cssFingerprint+'.css')); } }); }); } self.unobserve(elem); } }); }, config); //GET EVERYTHING WE NEED TO LAZY LOAD const elems = document.querySelectorAll(".defer-img, .defer_img, .defer-iframe, .defer_iframe, .defer-video, .defer_video, #payment-form, .import_static_map, .secureForm, .validateForm, .carousel, .modal, .before_after_container, .datepicker, .sticky, [data-bs-dismiss='alert'], [data-bs-toggle='button'], [data-bs-toggle='buttons'], [data-bs-toggle='collapse'], [data-bs-toggle='dropdown'], [data-bs-toggle='offcanvas'], [data-bs-toggle='popover'], [data-bs-spy='scroll'], [data-bs-toggle='tab'], .toast, [data-bs-toggle='tooltip']"); //PASS EVERYTHING TO THE INTERSECTION OBSERVER elems.forEach(elem => { observer.observe(elem); }); if(window.performance.mark) { window.performance.mark('endLazyLoad'); window.performance.measure('lazyLoadMeasure', 'startLazyLoad', 'endLazyLoad'); var importLazyLoadMeasure = window.performance.getEntriesByName('lazyLoadMeasure'); console.log("LazyLoad: "+importLazyLoadMeasure[0].duration+"ms"); } //LAZY LOAD AN IMAGE TAG function loadIMGTAG(elem) { if (xsDown.matches) { if (elem.classList.contains("no-mobile")) { elem.parentNode.removeChild(elem); } else { let src = elem.getAttribute('data-src'); let srcset = elem.getAttribute('data-srcset'); let sizes = elem.getAttribute('data-sizes'); if(src !== null) { elem.src = src; } if(srcset !== null) { elem.srcset = srcset; } if(sizes !== null) { elem.sizes = sizes; } } } else { let src = elem.getAttribute('data-src'); let srcset = elem.getAttribute('data-srcset'); let sizes = elem.getAttribute('data-sizes'); if(src !== null) { elem.src = src; } if(srcset !== null) { elem.srcset = srcset; } if(sizes !== null) { elem.sizes = sizes; } } } //LAZY LOAD A PICTURE TAG function loadPICTAG(elem) { if (xsDown.matches) { if (elem.classList.contains("no-mobile")) { elem.parentNode.removeChild(elem); } else { let sources = elem.querySelectorAll("source"); sources.forEach(source => { let src = source.getAttribute('data-src'); let srcset = source.getAttribute('data-srcset'); let sizes = source.getAttribute('data-sizes'); if(src !== null) { source.src = src; } if(srcset !== null) { source.srcset = srcset; } if(sizes !== null) { source.sizes = sizes; } }); let img = elem.querySelector("img"); let src = img.getAttribute('data-src'); let srcset = img.getAttribute('data-srcset'); let sizes = img.getAttribute('data-sizes'); if(src !== null) { img.src = src; } if(srcset !== null) { img.srcset = srcset; } if(sizes !== null) { img.sizes = sizes; } } } else { let sources = elem.querySelectorAll("source"); sources.forEach(source => { let src = source.getAttribute('data-src'); let srcset = source.getAttribute('data-srcset'); let sizes = source.getAttribute('data-sizes'); if(src !== null) { source.src = src; } if(srcset !== null) { source.srcset = srcset; } if(sizes !== null) { source.sizes = sizes; } }); let img = elem.querySelector("img"); let src = img.getAttribute('data-src'); let srcset = img.getAttribute('data-srcset'); let sizes = img.getAttribute('data-sizes'); if(src !== null) { img.src = src; } if(srcset !== null) { img.srcset = srcset; } if(sizes !== null) { img.sizes = sizes; } } } //LAZY LOAD CSS BACKGROUND IMAGE function loadIMGCSS(elem) { if (xsDown.matches) { if (elem.classList.contains("no-mobile")) { //DO NOTHING } else { elem.classList.remove('defer-img'); } } else { elem.classList.remove('defer-img'); } } //LAZY LOAD IFRAME function loadIFRAME(elem) { if (xsDown.matches) { if (elem.classList.contains("no-mobile")) { elem.parentNode.removeChild(elem); } else { let src = elem.getAttribute('data-src'); elem.src = src; } } else { let src = elem.getAttribute('data-src'); elem.src = src; } } //LAZY LOAD HTML5 VIDEO function loadVIDEO(elem) { //HTML5 VIDEO if(xsDown.matches){ if(elem.classList.contains("no_mobile")){ //DO NOTHING } else { let source = elem.querySelector('source'); let src = source.getAttribute('data-src'); source.src = src; elem.get(0).load(); } } else{ let source = elem.querySelector('source'); let src = source.getAttribute('data-src'); source.src = src; elem.load(); } } //STATIC MAP CLICK EVENT function swapStaticMap(elem){ elem.addEventListener("click",function(event){ let e = event.target; if(e.classList.contains("static_map_swap")) { let embed = e.dataset.embed; elem.innerHTML = ''; } }); } //PAYMENT FORM //STRIPE SPECIFIC FUNCTIONS function stripeTokenHandler(token) { // Insert the token ID into the form so it gets submitted to the server var form = document.getElementById('payment-form'); var hiddenInput = document.createElement('input'); hiddenInput.setAttribute('type', 'hidden'); hiddenInput.setAttribute('name', 'stripeToken'); hiddenInput.setAttribute('value', token.id); form.appendChild(hiddenInput); // Submit the form form.submit(); } function createToken(stripe,card) { stripe.createToken(card).then(function(result) { if (result.error) { // Inform the user if there was an error var errorElement = document.getElementById('card-errors'); errorElement.textContent = result.error.message; } else { // Send the token to your server stripeTokenHandler(result.token); } }); } //SETUP THE PAYMENT FORM function getPaymentForm(elem){ let stripeKey = document.getElementById("payment-form-stripe").value; if(stripeKey == "" || stripeKey == null){ alert("Stripe Keys Not SetPlease Set Up Your Stripe Keys.","warning"); return false; } //LOAD SPAM STOPPER let spamStopper = document.createElement('input'); spamStopper.type = 'hidden'; spamStopper.name = 'ts'; spamStopper.value = token; elem.appendChild(spamStopper); FormValidation.formValidation( elem, { plugins: { trigger: new FormValidation.plugins.Trigger(), submitButton: new FormValidation.plugins.SubmitButton(), bootstrap5: new FormValidation.plugins.Bootstrap5({ rowSelector: '.mb-3', }), declarative: new FormValidation.plugins.Declarative() }, } ).on('core.form.valid',function(){ createToken(stripe,card); }); //STRIPE API var stripe = Stripe(stripeKey); var elements = stripe.elements(); var card = elements.create('card'); card.mount('#card-element'); card.addEventListener('change', function(event) { var displayError = document.getElementById('card-errors'); if (event.error) { displayError.textContent = event.error.message; document.getElementById('payment-submit').disabled = true; document.getElementById('payment-submit').classList.add('disabled'); } else { displayError.textContent = ''; document.getElementById('payment-submit').disabled = false; document.getElementById('payment-submit').classList.remove('disabled'); } }); } //SET UP SEARCH BOX AUTOCOMPLETE let searchBars = document.querySelectorAll('.search_term'); function getAutoComplete() { let data = postData({action:"get_autocomplete"}); let request = new XMLHttpRequest(); request.open('POST','/common/javascript_variables.php',true); request.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8'); request.onload = function() { if (request.status >= 200 && request.status < 400) { let data = JSON.parse(request.responseText); new autoComplete({ selector: '.search_term', minChars: 1, source: function(term,suggest) { term = term.toLowerCase(); var choices = data; var matches = []; for (let i=0; i{ let target = event.target; if(target.classList.contains('sidekick_link')) { let video = target.dataset.video; videoModalBody.innerHTML = video+sidekickModalLinks; } }); videoModal.addEventListener("show.bs.modal",(event)=>{ let btn = event.relatedTarget; if(btn.dataset.sidekick_alt) { sidekickModalLinks = ''; } else { sidekickModalLinks = ''; } document.getElementById("videoModalLabel").innerHTML = btn.dataset.title; videoModalBody.innerHTML = btn.dataset.content+sidekickModalLinks; }); videoModal.addEventListener("hidden.bs.modal",()=>{ document.getElementById("videoModalLabel").innerHTML = ""; videoModalBody.innerHTML = ""; }); } //TRACK ALL CLICKS ON PHONE NUMBERS W/ HREF %PHONE% var bounce = false; // debounce check var telLinks = document.querySelectorAll('a[href^="tel:"]'); telLinks.forEach(function(elem){ elem.addEventListener('click',function(){ // See if CID is set let urlParams = new URLSearchParams(window.location.search); let afterSplit = urlParams.get('cid') !== null ? "cid:" + urlParams.get('cid') : "no_ad_id"; // If everything went well shows split[1], if not then de default message is shown if (!bounce){ var trackerName = ga.getAll()[0].get('name'); ga(trackerName + '.send', 'event', { eventCategory: 'tel:link', eventAction:'click', eventLabel:'phone_num_'+afterSplit, eventValue: 1 }); bounce = true; } }); }); //LOAD CSS IF APPROPRIATE function loadCSS(event) { console.log("loadCSS"); let scrollPosition = window.pageYOffset || document.documentElement.scrollTop; let load = false; if(event.type == "scroll" || event == "load") { if(scrollPosition > 5) { load = true; } } else if(event.type == "click" || event.type == "keydown") { load = true; } if(load === true) { loadCss('SiteCSS',(jsMin === true ? '/css/sitemin.'+cssFingerprint+'.css':'/css/site.'+cssFingerprint+'.css')); window.removeEventListener("scroll",loadCSS); document.removeEventListener("click",loadCSS); document.removeEventListener("keydown",loadCSS); } } //LOAD CSS window.addEventListener("scroll",loadCSS); document.addEventListener("click",loadCSS); document.addEventListener("keydown",loadCSS); loadCSS("load"); if(window.performance.mark) { window.performance.mark('endJSLoad'); window.performance.measure('JSLoadMeasure', 'startJSLoad', 'endJSLoad'); var JSLoadMeasure = window.performance.getEntriesByName('JSLoadMeasure'); console.log("JSLoad: "+JSLoadMeasure[0].duration+"ms\r\nAll JS Loaded/Ran:"+window.performance.now()+"ms"); }