`, '') : ``; /* Get the tracking pixels wrapper element */ const wrapper = document.querySelector('#pixels-wrapper'); /* If the wrapper element already exists, append to it. If not, create it with the pixels inside */ if (wrapper) { wrapper.insertAdjacentHTML('beforeend', pixels); } else { document.body.insertAdjacentHTML('beforeend', `
`); } }, /* Tracks events emitted from the timeslots-widget web component */ trackFromEmitted: async (type, event) => { const { reportToWheelhouse, trackWompEvent } = this.helpers; const { scrollLeft, scrollTop } = document.body; let pixel; let provider; let index; let hasTimeslots = 0; const providerCardEl = event.target.closest('.card.provider'); try { if (providerCardEl) { index = Number(providerCardEl.dataset.position); provider = this.state.results.providers[index - 1]; hasTimeslots = providerCardEl.querySelector('timeslots-widget, directory-timeslots') ? 1 : 0; } } catch (err) { console.error('fromEmitted error:\n', err); } switch (type) { case 'phone': if (typeof event.detail === 'string') { await reportToWheelhouse([ { key: "tealium_event", value: "amp_event" }, { key: "event_category", value: "Contact" }, { key: "event_action", value: "Phone" }, { key: "event_label", value: event.detail }, { key: "scroll_x", value: scrollLeft }, { key: "scroll_y", value: scrollTop } ]); /* Internal tracking */ await trackWompEvent({ ec: "Direct Contact", ea: "Phone Click-to-Call", el: event.detail }); if (provider) { await trackWompEvent({ ec: "Provider Click-To-Call", ea: `${provider.Name}, ${index}, timeslots: ${hasTimeslots}`, el: JSON.stringify(provider['@search.features']) }); } /* Telium pixel */ pixel = siteSearch.helpers.createPixel({ event_category: "Direct Contact", event_action: "Phone Click-to-Call", event_label: event.detail, tealium_event: 'womp_directory_event', tealium_event_type: 'event' }); } else { console.error('event.detail value must be a string representing the phone number clicked'); return; } break; case 'timeslot': reportToWheelhouse([ { key: "tealium_event", value: "amp_event" }, { key: "event_category", value: "Schedule Appointment" }, { key: "event_action", value: "Pick a Time" }, { key: "scroll_x", value: scrollLeft }, { key: "scroll_y", value: scrollTop } ]); const action = event.detail?.action; trackWompEvent({ ec: "Directory Journeys", ea: action && action.length ? action : "Provider Directory", el: 'Timeslot Clicks' }); /* Internal tracking */ if (provider) { trackWompEvent({ ec: "Provider Timeslot Click", ea: `${provider.Name}, ${index}, timeslots: ${hasTimeslots}`, el: JSON.stringify(provider['@search.features']) }); } pixel = siteSearch.helpers.createPixel({ event_category: "Directory Journeys", event_action: action && action.length ? action : "Provider Directory", event_label: "Timeslot Clicks", tealium_event: 'womp_directory_event', tealium_event_type: 'event', }); break; default: console.error('Please provide a valid event type [phone, timeslot]'); return; } siteSearch.helpers.trackIt(pixel); }, getGoogleLocation: (elId = "custom-location") => { const value = document.querySelector("#" + elId).value; if (value !== this.state.filters.location) { this.state.updatedLocation = true; } let coords; if (value?.length > 1) { fetch( `https://maps.googleapis.com/maps/api/geocode/json?address=${ value }&key=AIzaSyC9aTi6UWN30wj-e4uJHJ5j0y6szBTQ4BY` ) .then((res) => res.json()) .then((res) => { let validZip = true; if (res.results[0]) { let resultIndex; try { resultIndex = res.results.findIndex(address => address.address_components.findIndex(ac => ac.long_name.toLowerCase().includes('united states') ) > -1 ); } catch (err) { console.error('resultIndex:\n', err); resultIndex = -1; } if (resultIndex > -1) { AMP.setState({locationState: {validZip: 1}}); const geo = res.results[resultIndex].geometry.location; coords = { latitude: geo.lat, longitude: geo.lng, }; console.debug('state:', this.helpers.deepCopy(this.state)); this.state.filters = { ...this.state.filters, coordinates: coords, userProvidedLocation: true, }; document.querySelector("#switch").checked = false; this.handleSubmit(); this.state.filters.location = value; this.state.filters.locationType = "user"; } else { validZip = false; } } else { siteSearch.helpers.getGoogleLocationFallback(); } if (!validZip) { console.error('invalid zip:', validZip); AMP.setState({locationState: {validZip: 0}}); return; } }); } }, getGoogleLocationFallback: (elId = "custom-location") => { const value = document.querySelector("#" + elId).value; if (value !== this.state.filters.location) { this.state.updatedLocation = true; } let coords; if (value?.length > 1) { fetch( `https://maps.googleapis.com/maps/api/geocode/json?components=postal_code%3A${ value }%7Ccountry%3AUS&key=AIzaSyC9aTi6UWN30wj-e4uJHJ5j0y6szBTQ4BY` ) .then((res) => res.json()) .then((res) => { let validZip = true; if (res.results[0]) { let resultIndex; try { resultIndex = res.results.findIndex(address => address.address_components.findIndex(ac => ac.long_name.toLowerCase().includes('united states') ) > -1 ); } catch (err) { console.error('resultIndex bu:\n', err); resultIndex = -1; } if (resultIndex > -1) { AMP.setState({locationState: {validZip: 1}}); const geo = res.results[resultIndex].geometry.location; coords = { latitude: geo.lat, longitude: geo.lng, }; console.debug('state bu:', this.helpers.deepCopy(this.state)); this.state.filters = { ...this.state.filters, coordinates: coords, userProvidedLocation: true, }; document.querySelector("#switch").checked = false; this.handleSubmit(); this.state.filters.location = value; this.state.filters.locationType = "user"; } else { validZip = false; } } else { validZip = false; } if (!validZip) { console.error('invalid bu zip:', validZip); AMP.setState({locationState: {validZip: 0}}); return; } }); } }, /* Scrolls to a specific anchor on the page with a specified offset to account for the fixed nav */ scrollToTarget: (el, headerOffset = 45) => { let offsetPosition = el.getBoundingClientRect().top - headerOffset; window.scrollBy({ top: offsetPosition, behavior: "smooth" }); }, pxInViewport: el => { const bounding = el.getBoundingClientRect(); const offset = bounding.height + bounding.top; return offset < 0 ? 0 : offset; }, waitForGlobal: (key, callback) => { if (window[key]) { callback(); } else { setTimeout(() => { this.helpers.waitForGlobal(key, callback); }, 100); } }, /** * Returns a Promise that resolves once * the required property is available on the object. * Rejects if maxWait occurs. * * @param {String} propName - property name * @param {String} scope - object to test for property * @param {Number} maxWait - ms to wait before rejecting * @param {Number} checkInterval - ms to wait between checks */ waitForProp( propName, scope = window, maxWait = 20000, checkInterval = 150, ) { return new Promise((resolve, reject) => { /* check now, maybe we do not need to wait */ if ( (scope == window && window[propName]) || (scope != window && scope && scope[propName]) ) { resolve(scope[propName]); } const timeout = setTimeout(() => { clearInterval(interval); reject(`could not find ${scope.toString()}['${propName}']`); }, maxWait); const interval = setInterval(() => { if ( (scope == window && window[propName]) || (scope != window && scope && scope[propName]) ) { clearInterval(interval); clearTimeout(timeout); resolve(scope[propName]); } else { return; } }, checkInterval); }); }, showPosition: async (position) => { const { latitude, longitude } = position.coords; await fetch( `https://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&key=AIzaSyC9aTi6UWN30wj-e4uJHJ5j0y6szBTQ4BY` ) .then((res) => res.json()) .then((res) => { const parts = res.results[0].address_components.filter((x) => x.types .join("") .match( /locality|administrative_area_level_1|administrative_area_level_3/gi ) ); const newLoc = `${parts[0].long_name}, ${parts[1].short_name}`; /* LocationLabel.innerHTML = `Location: ${newLoc} `; */ this.state.filters.location = newLoc; /** **/ const zipParts = res.results[0].address_components.filter((x) => x.types .join("") .match( /postal_code/gi ) ); const zip = zipParts[0].long_name; const fullLocation = this.state.filters.location + ' ' + zip; const headerLocationLabel = document.querySelector('#geoLocatorLabel span'); headerLocationLabel.innerHTML = fullLocation; document.querySelector('#geoLocatorInput').value = fullLocation; const dexcareEvent = new CustomEvent('dexcareEvent', { detail: { eventData: { _dexcare: { event_name: 'toggle_location_services', Loc_enabled: 'on', }, }, }, }); dispatchEvent(dexcareEvent); checkLoginStatus(); /** **/ }); this.state.filters = { ...this.state.filters, coordinates: { latitude, longitude, }, locationType: "user", }; this.handleSubmit(); }, handleGeoLocationError: (err) => { console.error('geo:\n', err.message); this.helpers.getGoogleLocation(); const dexcareEvent = new CustomEvent('dexcareEvent', { detail: { eventData: { _dexcare: { event_name: 'toggle_location_services', Loc_enabled: 'disabled', }, }, }, }); dispatchEvent(dexcareEvent); }, formatAddress: (type, data) => { if (!data) return ''; let formattedAddress = ''; if (type == 'infoWindow') { const { City, Region, PostalCode, Address } = data; const regex = new RegExp(`${City}, |${Region},|, ${PostalCode}`, 'gi'); formattedAddress = Address.replace(regex, '').trim(); formattedAddress = `${formattedAddress}No providers found as this location
' : ''}${this.state.description}
`; this.state.description = false; } /** * If we have the testing parameter added for internal testing and the type object is present on the API * response, then we're going to render that content above the search results. */ if (isTest && results.info?.type?.length) { resultsHtml += `${results.info.type.join(', ')}
Showing ${count.toLocaleString()} Results From ${results.geoip.zip}
`; } else if(results.geoip.city !== undefined){ resultsHtml += `Showing ${count.toLocaleString()} Results From ${results.geoip.city}
`; } else if(results.geoip.county !== undefined){ resultsHtml += `Showing ${count.toLocaleString()} Results From ${results.geoip.county}
`; } else if(results.geoip.state !== undefined){ resultsHtml += `Showing ${count.toLocaleString()} Results From ${results.geoip.state}
`; }else { resultsHtml += `Showing ${count.toLocaleString()} Results
`; } } catch (err) { resultsHtml += `Showing ${count.toLocaleString()} Results
`; console.error('resultsCount:\n', err); } } this.state.disclaimerSearch ? resultsHtml += '${descr}
${rating} ${offersVirtual} ${AcceptingClinicVisits} ${isTest && Tier ? `${curr}
`, '') + '${key}: ${searchFeatures[key]?.similarityScore.toFixed(3)}
`, '') + 'Searching for upcoming appointments...