1// import { 2// getMarkers, getInfoWindow, 3// } from './helpers'; 4 5// import { 6// setDBAutocomplete 7// } from "./autocomplete-db"; 8 9const selectors = { 10 locationsSection: '.js-locations-section', 11 locationsMap: '#locations-map', 12 searchInput: '#locations-search', 13 selectState: '#locations-state-select', 14 searchBtn: '.js-search-loc-btn', 15 locationsBlock: '.locations-block', 16 locationsList: '#locations-list', 17 lettersList: '#letters-list', 18 locationsSearchInfo: '.dsl-search-result-info', 19 currentLocationBtn: '.dsl-get-current-location', 20 loaderDiv: '.dsl-js-loader', 21 resetBtn: '.dsl-reset-filters', 22 radiusDiv: '#radius_range', 23 tabs: '.tab', 24}; 25 26const state = { 27 map: null, 28 markers: [], 29 // allData: {}, 30 address: null, 31 currentInfo: null, 32 radiusRange: 250, 33 circle: null, 34 resetBtn: null, 35 clusterer: null, 36 defaultCountryCode: ds_locations && ds_locations['default_country_code'] ? ds_locations['default_country_code'] : "USA", 37 searchRadius: ds_locations && ds_locations['search_radius'] ? ds_locations['search_radius'] : '100', 38}; 39 40/** 41 * Switch to show or hide listing with locations in sidebar container. 42 * Depend on filter and search results. 43 */ 44const switchLocationsBlock = (setShow = true) => { 45 const {locationsBlock} = state; 46 if (locationsBlock) { 47 const isShow = locationsBlock.classList.contains('is-visible'); 48 49 if (setShow) { 50 !isShow && locationsBlock.classList.add('is-visible'); 51 } else { 52 isShow && locationsBlock.classList.remove('is-visible'); 53 } 54 } 55}; 56 57/** 58 * Add info about locations init and search result. 59 * */ 60const setLocationsSearchInfo = ({type = 'default', count}) => { 61 const {locationsSearchInfo, locationsSection} = state; 62 const checkCountryCodes = () => ['USA', 'CAN'].includes(state.defaultCountryCode); 63 64 if (locationsSearchInfo) { 65 const searchInfoMessages = { 66 default: (count) => checkCountryCodes ? '' : `${count} ` + ds_locations.translate.location, 67 error: () => '<span class="error">' + ds_locations.translate.error_locations + '</span>', 68 empty: () => '<span class="error">' + ds_locations.translate.no_locations + '</span>', 69 result: (count) => checkCountryCodes ? '' : `<span>${count}</span> ${(count > 1) ? ds_locations.translate.locations_f : ds_locations.translate.location_f}`, 70 }; 71 72 // remove all previous "Search Result" status classes 73 locationsSection.classList.remove('search-error', 'search-empty', 'search-found'); 74 locationsSearchInfo.classList.remove('no-results'); 75 switchLocationsBlock(false); 76 77 if (type === 'error') { 78 locationsSearchInfo.classList.add('no-results'); 79 locationsSection.classList.add('search-error'); 80 } 81 82 if (type === 'empty') { 83 locationsSearchInfo.classList.add('no-results'); 84 locationsSection.classList.add('search-empty'); 85 } 86 87 if (type === 'result' && count) { 88 // show locations list 89 switchLocationsBlock(); 90 locationsSection.classList.add('search-found'); 91 } 92 93 locationsSearchInfo.innerHTML = searchInfoMessages[type](count); 94 } 95}; 96 97const removeCurrentInfo = () => { 98 if (state.currentInfo) { 99 const {item, marker, info} = state.currentInfo; 100 item && item.classList.remove('active'); 101 102 info.close(); 103 state.currentInfo = null; 104 } 105}; 106const setCurrentInfo = async (currentInfo, reset) => { 107 const {item, marker, info, id} = currentInfo; 108 109 // remove old info 110 if (reset) { 111 removeCurrentInfo(); 112 } 113 114 // set current Info 115 state.currentInfo = currentInfo; 116 117 if (item) { 118 item.classList.add('active'); 119 } 120 121 state.map.panTo(marker.getPosition()); 122 123 if (info.getContent()) { 124 info.open(state.map, marker); 125 } else { 126 info.setContent('<div class="info-window-content"><p class="loading">Loading...</p></div>'); 127 info.open(state.map, marker); 128 129 try { 130 const response = await getInfoWindow({pid: id}); 131 if (response.html) { 132 info.setContent(response.html); 133 } else { 134 info.close(); 135 } 136 } catch (e) { 137 console.log(e); 138 info.close(); 139 } 140 } 141}; 142 143const setLocationsList = ({data}) => { 144 145 const {locationsList} = state; 146 147 if (locationsList) { 148 locationsList.innerHTML = data.html; 149 const locationsListItems = locationsList.children;
150 [...locationsListItems].forEach((locationsListItem) => { 151 const id = locationsListItem.getAttribute('data-id'); 152 // eslint-disable-next-line no-shadow 153 const marker = state.markers.find((marker) => marker.pid === +id); 154 locationsListItem.addEventListener('click', () => { 155 removeCurrentInfo(); 156 state.map.panTo(marker.getPosition()); 157 state.map.setZoom(8); 158 }); 159 }); 160 } 161}; 162 163const setMarkers = ({data}) => { 164 // remove prevent info window popup on map 165 removeCurrentInfo(); 166 167 // Reset old markers from map 168 state.markers.forEach((marker) => marker.setMap(null)); 169 state.markers = []; 170 171 const clusterOptions = {styles: [{fillColor: '#DE1B22'}]}; 172 173 state.clusterer = new markerClusterer.MarkerClusterer({map: state.map, markers: state.markers}, clusterOptions); 174 175 // show info message about search result 176 setLocationsSearchInfo({ 177 type: 'result', 178 count: data.markers.length, 179 }); 180 181 for (const key in data.markers) { 182 const markerData = data.markers[key]; 183 const infowindow = new google.maps.InfoWindow(); 184 infowindow.addListener('closeclick', () => { 185 removeCurrentInfo(); 186 }); 187 188 const icon = ds_locations.icon; 189 // Create and add new marker from response on map 190 // deprecated https://developers.google.com/maps/documentation/javascript/advanced-markers/migration 191 let marker = new google.maps.Marker({ 192 map: state.map, 193 position: new google.maps.LatLng(markerData.lat, markerData.lng), 194 icon, 195 title: 'Marker', 196 pid: markerData.pid, 197 }); 198 199 // let marker = new google.maps.marker.AdvancedMarkerElement({ 200 // map: state.map, 201 // position: new google.maps.LatLng(markerData.lat, markerData.lng), 202 // icon, 203 // pid: markerData.pid, 204 // }); 205 206 state.markers.push(marker); 207 state.clusterer.addMarker(marker); 208 209 marker.addListener('click', () => { 210 const locationsListItem = state.locationsList && state.locationsList.querySelector(`[data-id='${markerData.pid}']`); 211 const newCurrentInfo = { 212 id: markerData.pid, 213 item: locationsListItem, 214 marker, 215 info: infowindow, 216 }; 217 218 // TODO WTF 219 if (state.currentInfo) { 220 // eslint-disable-next-line no-empty 221 if (state.currentInfo.id === markerData.pid) { 222 223 } else { 224 setCurrentInfo(newCurrentInfo, true); 225 } 226 } else { 227 setCurrentInfo(newCurrentInfo); 228 } 229 }); 230 } 231}; 232 233const fitBoundsToMarkers = (radiusVal) => { 234 if (state.circle) { 235 state.circle.setMap(null); 236 } 237 const circle = new google.maps.Circle({ 238 map: state.map, 239 fillColor: 'transparent', 240 strokeColor: 'transparent', 241 }); 242 state.circle = circle; 243 circle.setCenter(new google.maps.LatLng(state.map.getCenter())); 244 245 circle.setRadius((radiusVal * 850)); 246 state.map.fitBounds(circle.getBounds()); 247}; 248 249const fitBoundsMarkers = () => { 250 const bounds = new google.maps.LatLngBounds(); 251 state.markers.forEach((marker) => bounds.extend(marker.getPosition())); 252 state.map.fitBounds(bounds); 253 const listener = google.maps.event.addListener(state.map, 'idle', () => { 254 if (state.map.getZoom() > 16) state.map.setZoom(16); 255 google.maps.event.removeListener(listener); 256 }); 257}; 258 259const removeMarkers = () => { 260 state.clusterer.setMap(null); 261 state.markers.forEach((marker) => { 262 state.clusterer.removeMarker(marker); 263 marker.setMap(null); 264 }); 265 state.markers = []; 266 state.locationsList.innerHTML = ''; 267 state.map.setCenter(new google.maps.LatLng(20, 0)); 268 state.map.setZoom(3); 269}; 270 271const initMap = async () => { 272 const {locationsMap} = state; 273 274 if (locationsMap) { 275 try { 276 state.map = new google.maps.Map(locationsMap, { 277 center: {lat: parseInt(ds_locations.center.lat), lng: parseInt(ds_locations.center.lng)}, 278 zoom: parseInt(ds_locations.zoom), 279 zoomControl: ds_locations.zoom_control, 280 disableDefaultUI: true, 281 zoomControlOptions: { 282 position: google.maps.ControlPosition.RIGHT_CENTER, 283 }, 284 gestureHandling: 'cooperative', 285 mapId: 'DSL-WP', 286 //styles: JSON.parse(ds_locations.map_styles), 287 }); 288 state.geocoder = new google.maps.Geocoder(); 289 290 let data = {type: 'all'}; 291 292 const response = await getMarkers(data); 293 294 if (response.success) { 295 // state.allData = response.data; 296 setMarkers({data: response.data}); 297 setLocationsList({data: response.data}); 298 } else { 299 setLocationsSearchInfo({type: 'empty'}); 300 removeMarkers(); 301 } 302 } catch (e) { 303 if (e.typeError === 'markers') { 304 setLocationsSearchInfo({type: 'empty'}); 305 removeMarkers(); 306 } else { 307 console.log(e); 308 } 309 } 310 } 311}; 312 313const runSearch = async (coordinates, radius, region) => { 314 const { 315 searchInput 316 } = state; 317 318 const address = coordinates || searchInput.value; 319 const searchBy=searchInput.getAttribute('data-search') || 'address_title'; 320 321 state.resetBtn.style.display = 'block'; 322 try { 323 let data = {search: address, search_by:searchBy}, extendedAddress = `${address} , ${state.defaultCountryCode}`, response = {}; 324 325 if (region) { 326 data = {type: 'by_state', state: region}; 327 response = await getMarkers(data); 328 } else { 329 330 if (validationZipCode(address, state.defaultCountryCode)) { 331 response = await getMarkersByZip({address: extendedAddress, state}); 332 } 333 if (!response.success) { 334 response = await getMarkers(data); 335 } 336 } 337 338 339 state.address = address; 340 341 if (response.success) { 342 removeMarkers(); 343 setMarkers({data: response.data}); 344 fitBoundsMarkers(); 345 setLocationsList({data: response.data}); 346 } else { 347 setLocationsSearchInfo({type: 'empty'}); 348 removeMarkers(); 349 } 350 } catch (e) { 351 if (e.typeError === 'markers') { 352 setLocationsSearchInfo({type: 'empty'}); 353 removeMarkers(); 354 } 355 } 356}; 357 358const initSearch = () => { 359 const { 360 searchInput, currentLocationBtn, searchBtn, radiusDiv, selectState 361 } = state; 362 363 if (searchInput) { 364 const handlerSearchPlace = () => { 365 if (searchInput.value.trim().length !== 0) { 366 if (searchInput.value !== state.address) { 367 runSearch(); 368 } 369 } else { 370 setLocationsSearchInfo({type: 'error'}); 371 } 372 }; 373 if (searchBtn) { 374 searchBtn.addEventListener('click', () => { 375 if (selectState) { 376 selectState.value = ''; 377 } 378 handlerSearchPlace(); 379 }); 380 } 381 382 searchInput.addEventListener('keydown', (ev) => { 383 if (ev.keyCode === 13) { 384 if (selectState) { 385 selectState.value = ''; 386 } 387 handlerSearchPlace(); 388 } 389 }); 390 } 391 392 if (selectState) { 393 selectState.addEventListener("change", function () { 394 searchInput.value = ''; 395 runSearch(false, false, selectState.value); 396 }); 397 } 398 399 if (currentLocationBtn) { 400 currentLocationBtn.addEventListener('click', () => { 401 if (navigator.geolocation) { 402 navigator.geolocation.getCurrentPosition((position) => { 403 const lat = position.coords.latitude; 404 const long = position.coords.longitude; 405 state.map.setCenter(new google.maps.LatLng(lat, long), 4); 406 }, (err) => { 407 console.log(err); 408 }); 409 } 410 }); 411 } 412 413 if (radiusDiv) { 414 radiusDiv.addEventListener('mouseup', () => { 415 if (state.radiusRange !== radiusDiv.value) { 416 if (navigator.geolocation) { 417 navigator.geolocation.getCurrentPosition((position) => { 418 state.map.setCenter(new google.maps.LatLng(position.coords.latitude, position.coords.longitude)); 419 state.map.setZoom(9); 420 421 fitBoundsToMarkers(+radiusDiv.value); 422 runSearch(`${lat}, ${long}`, radiusDiv.value); 423 }); 424 } 425 } 426 state.radiusRange = radiusDiv.value; 427 }); 428 } 429 430 state.resetBtn.addEventListener('click', () => { 431 let data = {type: 'all'}; 432 433 getMarkers(data).then((response) => { 434 if (response.success) { 435 searchInput.value = ''; 436 selectState.value = ''; 437 438 setMarkers({data: response.data}); 439 setLocationsList({data: response.data}); 440 441 state.map.setCenter(new google.maps.LatLng(parseInt(ds_locations.center.lat), parseInt(ds_locations.center.lng))); 442 state.map.setZoom(parseInt(ds_locations.zoom)); 443 state.resetBtn.style.display = 'none'; 444 } 445 }); 446 }); 447}; 448 449// const initSingleMap = async () => { 450// const {singleMap} = state; 451// if (singleMap) { 452// try { 453// state.map = new google.maps.Map(singleMap, { 454// center: {lat: 40.2213207, lng: -94.6041298}, 455// zoom: 5, 456// disableDefaultUI: true, 457// zoomControl: false, 458// gestureHandling: 'cooperative', 459// zoomControlOptions: { 460// //position: google.maps.ControlPosition.RIGHT_CENTER, 461// }, 462// }); 463// 464// const response = await getMarkers(data); 465// if (response.success) { 466// setMarkers({data: response.data}); 467// // eslint-disable-next-line max-len 468// //state.map.setCenter(new google.maps.LatLng(response.data.markers[0].lat, response.data.markers[0].lng)); 469// fitBoundsMarkers(); 470// setLocationsList({data}); 471// } else { 472// removeMarkers(); 473// } 474// } catch (e) { 475// if (e.typeError === 'markers') { 476// removeMarkers(); 477// } else { 478// console.log(e); 479// } 480// } 481// } 482// }; 483 484const mapSearchWithAutocomplete = () => { 485 const {locationsSection, ...restSelectors} = selectors; 486 state.locationsSection = document.querySelector(locationsSection); 487 if (state.locationsSection) {
488 Object.keys(restSelectors).forEach((key) => { 489 state[key] = document.querySelector(restSelectors[key]); 490 }); 491 492 initMap(); 493 //initSingleMap(); 494 initSearch(); 495 496 setDBAutocomplete(state.searchInput); 497 } 498}; 499 500mapSearchWithAutocomplete();
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.