PageSourceSearch

https://thefamilydentalgroup.com/build-next/assets/store-locator-kQ_yNCG0.js

js thefamilydentalgroup.com collected 2026-09-29 21:38:13 UTC 12,909 bytes, 1 lines download raw bytes

1import{a as m,l as g}from"./gmaps-BylYYdKs.js";import{C as d}from"./filter-combobox-CCYZqGZa.js";const u={noLocations:"Sorry, no locations were found. Please refine your search and try again.",generic:"Sorry, we were unable to find your current location. Please enter a city or ZIP Code and try again."},p="No cities or ZIP Codes were found. Please refine your search and try again.";class f{constructor(e,t){this.root=e,this.config=t,this.stores=t.stores??[];for(const o of this.stores)this.storeById.set(String(o.id),o);this.insuranceOptions=t.insuranceOptions??[],this.practiceTypes=t.practiceTypes??[],this.nearbyStores=this.stores,this.wire(),this.observer=new IntersectionObserver(o=>{if(o[0]?.isIntersecting){this.observer?.disconnect(),this.observer=null;const s=this.q("[data-distance]");s&&(this.current.distance=parseInt(s.value,10),this.updateDistanceLabel()),m().then(()=>this.loadMap())}}),this.observer.observe(e)}root;config;stores;storeById=new Map;insuranceOptions;practiceTypes;nearbyStores;insuranceProvider=null;practiceType=null;current={nearbyCount:null,address:null,location:null,distance:null};google=null;map=null;markers=new Map;services={autocomplete:null,geocoder:null};geocodedPlaces={};geolocationLocation=null;geocodedLocation=null;locationBox=null;practiceTypeBox=null;insuranceBox=null;observer=null;mapLoaded=!1;cleanups=[];destroy(){this.observer?.disconnect(),this.locationBox?.destroy(),this.practiceTypeBox?.destroy(),this.insuranceBox?.destroy();for(const e of this.cleanups)e();this.cleanups=[];for(const e of this.markers.values())e.setMap(null);this.markers.clear()}on(e,t,o){e.addEventListener(t,o),this.cleanups.push(()=>e.removeEventListener(t,o))}q(e){return this.root.querySelector(e)}wire(){const e=this.q("[data-geolocate]");e&&this.on(e,"click",()=>this.updateCurrentLocation());const t=this.q("[data-distance]");t&&this.on(t,"input",()=>{this.current.distance=t.value,t.value===t.max&&(this.current.distance=100),this.updateDistanceLabel(),this.updateStores(!1)});const o=this.q('[data-combobox="location"]');if(o){const i=new d(o);i.shouldOpen=()=>i.input.value.length!==0&&i.open,i.onSearch=n=>{if(this.updateGeoActionVisibility(),n.length===0){i.setOptions([]);return}this.loadLocationPredictions(i,n)},i.onSelect=n=>{this.updateGeoActionVisibility(),this.onLocationSelected(n.value)},this.locationBox=i}const s=this.q('[data-combobox="practice-type"]');s&&(this.practiceTypeBox=this.wireFilterBox(s,this.practiceTypes,i=>{this.practiceType=i,this.updateStores(!0)}));const r=this.q('[data-combobox="insurance"]');r&&(this.insuranceBox=this.wireFilterBox(r,this.insuranceOptions,i=>{this.insuranceProvider=i,this.updateStores(!0)}));for(const i of Array.from(this.root.querySelectorAll("[data-list] li.store-item"))){this.on(i,"mouseenter",()=>{window.outerWidth>768&&this.onStoreItemMouseEnter(i)}),this.on(i,"mouseleave",()=>{window.outerWidth>768&&this.onStoreItemMouseLeave(i)});const n=i.querySelector("[data-show-on-map]");n&&this.on(n,"click",()=>this.onStoreItemMouseEnter(i))}}wireFilterBox(e,t,o){const s=new d(e),r=t.map(i=>({label:String(i.name??""),value:i}));return s.shouldOpen=()=>s.open,s.setOptions(r),s.onSearch=i=>{const n=r.filter(a=>a.label.toLowerCase().includes(i.toLowerCase()));s.setOptions(n)},s.onSelect=i=>{o(i.value),s.setOptions(r)},s.onCleared=()=>o(null),s}updateGeoActionVisibility(){const e=this.q("[data-geolocate]");if(!e||!this.locationBox)return;const t=this.locationBox.input.value.length!==0&&this.locationBox.isOpen();e.style.visibility=t?"hidden":"visible"}async loadMap(){const e=this.q("[data-map-canvas]");if(!(this.mapLoaded||!e||!this.config.apiKey)){this.mapLoaded=!0;try{this.google=await g(this.config.apiKey),this.map=new this.google.maps.Map(e,this.config.mapConfig??{}),this.services.autocomplete=new this.google.maps.places.AutocompleteService,this.services.geocoder=new this.google.maps.Geocoder,this.syncMarkers(),this.resetPosition()}catch{}}}syncMarkers(){if(!this.google||!this.map)return;const e=new Map;for(const t of this.nearbyStores)e.set(String(t.id),t);for(const[t,o]of this.markers)e.has(t)||(o.setVisible(!1),o.setMap(null),this.markers.delete(t));
1for(const[t,o]of e){if(this.markers.has(t))continue;const s=new this.google.maps.Marker({id:t,position:o.position,map:this.map,optimized:!1,title:o.name||void 0});s.setIcon(this.config.iconConfig?.inactive),s.addListener("click",()=>this.markerHoverOver(t)),s.addListener("mouseover",()=>this.markerHoverOver(t)),s.addListener("mouseout",()=>{s.setIcon(this.config.iconConfig?.inactive),s.setZIndex(1)}),this.markers.set(t,s)}}resetPosition(){if(!this.google||!this.map||this.nearbyStores.length===0)return;const e=new this.google.maps.LatLngBounds;for(const t of this.nearbyStores)t.position&&e.extend(t.position);this.map.setCenter(e.getCenter()),this.map.fitBounds(e)}setMarkerActive(e,t){const o=this.markers.get(e);o&&(o.setIcon(this.config.iconConfig?.[t?"active":"inactive"]),o.setZIndex(t?2:1))}markerHoverOver(e){for(const s of this.markers.keys())s!==e&&this.setMarkerActive(s,!1);this.setMarkerActive(e,!0);const t=this.q("[data-list]"),o=t?.querySelector(`li[data-item-id="${e}"]`);if(!(!t||!o)){for(const s of Array.from(t.querySelectorAll("li.hover")))s.classList.remove("hover");o.classList.add("hover"),this.scrollToStoreItem(o,t)}}onStoreItemMouseEnter(e){this.scrollToMap();const t=e.getAttribute("data-item-id");if(!t)return;for(const s of this.markers.keys())this.setMarkerActive(s,s===t);const o=this.markers.get(t);o&&this.map&&this.map.panTo(o.getPosition())}onStoreItemMouseLeave(e){this.scrollToMap();const t=e.getAttribute("data-item-id");t&&this.setMarkerActive(t,!1)}isMobile(){return window.outerWidth<=768}scrollToMap(){const e=this.q("[data-map]");if(this.isMobile()&&e){const t=document.querySelector("#app > header")??document.querySelector("header"),o=e.getBoundingClientRect().y+window.scrollY-(t?.offsetHeight??0);window.scroll({top:o,left:0,behavior:"smooth"})}}scrollToStoreItem(e,t){if(this.isMobile()){const r=document.querySelector("#app > header")??document.querySelector("header"),i=e.getBoundingClientRect().y+window.scrollY-(r?.offsetHeight??0);window.scroll({top:i,left:0,behavior:"smooth"});return}const o=this.q("[data-locator-region]"),s=Math.min(t.scrollHeight,Math.max(0,e.getBoundingClientRect().y+t.scrollTop-t.getBoundingClientRect().y-(o?.clientHeight??0)/2+e.offsetHeight/2));t.scroll({top:s,left:0,behavior:"smooth"})}membershipFilter(e,t){if(!t)return e;const o=new Set((t.stores??[]).map(String));return e.filter(s=>o.has(String(s.id)))}updateStores(e){let t=this.stores;if(t=this.membershipFilter(t,this.insuranceProvider),t=this.membershipFilter(t,this.practiceType),this.current.distance===null||this.current.location===null){this.current.nearbyCount=t.length===this.stores.length?null:t.length,this.current.location=null,this.nearbyStores=t,e&&this.scrollToMap(),this.setSearchError(null),this.render();return}const o=this.q("[data-distance]"),s=5,r=parseInt(o?.max??"50",10);let i=this.current.distance,n=t.map(a=>({...a,distance:this.google.maps.geometry.spherical.computeDistanceBetween(new this.google.maps.LatLng(a.position),new this.google.maps.LatLng(this.current.location))*621371e-9})).sort((a,l)=>(a.distance??0)-(l.distance??0));e&&n.length&&(i=Math.min(Math.max(Math.ceil((n[0].distance??0)/5)*5,s),r).toString()),n=n.filter(a=>Math.ceil(a.distance??0)<=Number(i)),n.length>0?(e&&o&&(this.current.distance=i,o.min=String(i),o.value=String(i),this.updateDistanceLabel()),this.current.nearbyCount=n.length,this.nearbyStores=n,e&&this.scrollToMap(),this.setSearchError(null)):(this.current.nearbyCount=null,this.nearbyStores=this.stores,this.setSearchError(u.noLocations)),this.render()}updateDistanceLabel(){const e=this.q("[data-distance]"),t=this.q("[data-distance-label-row]"),o=this.q("[data-distance-label]");if(!e||!o||!t)return;const s=e.value;o.innerHTML=s+(s===e.max?"+":"")+" miles",e.setAttribute("aria-valuetext",`${o.textContent}`),t.removeAttribute("hidden"),this.updateRangeControlVisibility()}updateRangeControlVisibility(){const e=this.q("[data-range-control]"),t=this.q("[data-distance]");if(!e||!t)return;const o=!!this.current.location&&t.min!==t.max&&!!this.current.nearbyCount;e.style.display=o?"":"none"}setSearchError(e){const t=this.q("[data-search-error]");t&&(e===null?(t.style.display="none",t.innerHTML=""):(t.innerHTML=e,t.style.display=""))}render(){const e=this.q("[data-list]");this.renderListItems(e,this.nearbyStores.map(t=>String(t.id))),this.renderCountLine(e),this.updateRangeControlVisibility(),this.syncMarkers(),this.resetPosition()}renderListItems(e,t){if(!e)return;const o=e.querySelector("ul[data-items]")??e.querySelector("ul");if(!o)return;const s=o.__pool??new Map;for(const n of Array.from(o.querySelectorAll("li.store-item"))){const a=n.getAttribute("data-item-id");a&&!s.has(a)&&s.set(a,n)}o.__pool=s;const r=new Set,i=[];for(const n of t){const a=n.includes("_")?n.split("_")[0]:n;if(r.has(a))continue;r.add(a);const l=s.get(n);l&&i.push(l)}o.replaceChildren(...i)}renderCountLine(e){if(!e)return;const t=e.querySelector("[data-count-line]");if(!t)return;const o=this.current.nearbyCount??0,s=`${o} location${o===1?"":"s"}`;if(!!this.current.nearbyCount&&!!this.current.address&&!!this.current.location&&!!this.current.distance){const i=document.createElement("strong");i.innerHTML=s;const n=document.createElement("span");n.innerHTML=this.current.address??"",t.replaceChildren(i,document.createTextNode(" near "),n)}else if(this.current.nearbyCount){const i=document.createElement("strong");i.innerHTML=s;const n=document.createElement("span");n.textContent=" found",t.replaceChildren(i,n)}else{const i=document.createElement("span");i.innerHTML=this.config.strings?.allStores??"",t.replaceChildren(i)}}async loadLocationPredictions(e,t){if(!((!this.services.autocomplete||!this.google)&&(await this.loadMap(),!this.services.autocomplete)))try{const s=(await new Promise((r,i)=>{this.services.autocomplete.getPlacePredictions({input:t,componentRestrictions:{country:"us"},types:["(regions)"],language:"en",fields:["address_components","geometry","name"]},(n,a)=>{a!==this.google.maps.places.PlacesServiceStatus.OK||!n?i(new Error(a)):r(n)})})).map(r=>{let i=r.description.split(", ").slice(0,-1).join(", ");
1if(Array.isArray(r.types)&&r.types.length){const n=r.types[0];if(n==="postal_code")i=`${r.structured_formatting.main_text} (ZIP Code)`;else if(n==="administrative_area_level_1")return null}return{label:i,value:r}}).filter(r=>r!==null);e.setOptions(s,s.length===0?p:null)}catch{e.setOptions([],p)}}async onLocationSelected(e){const t=e.place_id;if(!Object.prototype.hasOwnProperty.call(this.geocodedPlaces,t)){const{results:o}=await this.services.geocoder.geocode({placeId:t});this.geocodedPlaces[t]=o[0]}this.setCurrentLocationFromGeocodeResult(this.geocodedPlaces[t])}setCurrentLocation(e,t){this.current.location=e,this.current.address=t,this.locationBox?.setSelectedLabel(t),this.updateStores(!0)}setCurrentLocationFromGeocodeResult(e){this.setCurrentLocation({lat:e.geometry.location.lat(),lng:e.geometry.location.lng()},this.getLocationStringFromAddressComponents(e.address_components))}getLocationStringFromAddressComponents(e){const t=[];for(const o of e??[])Array.isArray(o.types)&&(o.types.indexOf("administrative_area_level_1")>-1||o.types.indexOf("locality")>-1)&&t.push(o.short_name);return t.length===2?t.join(", "):null}updateCurrentLocation(){if(this.geolocationLocation!==null){this.setCurrentLocationFromGeocodeResult(this.geolocationLocation);return}if(!navigator.geolocation){this.updateGeocodedLocation();return}navigator.geolocation.getCurrentPosition(e=>{const t={lat:e.coords.latitude,lng:e.coords.longitude};this.loadMap().then(()=>this.services.geocoder.geocode({location:t}).then(o=>{o.results[0]?(this.setSearchError(null),this.geocodedPlaces[o.results[0].place_id]=t,this.geolocationLocation=o.results[0],this.setCurrentLocation(t,this.getLocationStringFromAddressComponents(o.results[0].address_components))):this.updateGeocodedLocation()}).catch(()=>{this.updateGeocodedLocation()}))},()=>{this.updateGeocodedLocation()})}async updateGeocodedLocation(){if(this.geocodedLocation!==null){this.setCurrentLocationFromGeocodeResult(this.geocodedLocation);return}try{await this.loadMap();const t=await(await fetch(`https://www.googleapis.com/geolocation/v1/geolocate?key=${this.config.apiKey}`,{method:"POST"})).json();if(t.location){const{results:o}=await this.services.geocoder.geocode({location:t.location});this.geocodedLocation=this.geocodedPlaces[o[0].place_id]=o[0],this.setCurrentLocationFromGeocodeResult(o[0])}}catch{this.current.nearbyCount=null,this.current.location=null,this.setSearchError(u.generic)}}}const h=new Map;function b(c,e={}){h.has(c)||h.set(c,new f(c,e))}function S(){for(const c of h.values())c.destroy();h.clear()}export{S as destroy,b as initialize};

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.