"use strict"; import MarkerClusterer from "@googlemaps/markerclustererplus"; import Events from "../_events"; import MarkerUI from "./map.google.marker"; const GoogleMapsDriver = ((window) => { class GoogleMapsDriver { getName() { return "GoogleMapsDriver"; } init(el, config = []) { const ui = this; ui.el = el; ui.config = config; ui.markers = []; window[`init${ui.getName()}`] = () => { ui.googleApiLoaded(); }; const script = document.createElement("script"); script.src = `https://maps.googleapis.com/maps/api/js?key=${ config["key"] }&callback=init${ui.getName()}`; script.async = true; script.defer = true; document.head.appendChild(script); } googleApiLoaded() { const ui = this; const el = ui.el; const config = ui.config; const mapDiv = el.querySelector(".mapAPI-map"); const zoom = config["mapZoom"] && config["mapZoom"] !== "0" ? parseInt(config["mapZoom"]) : 10; const center = config["center"] && config["center"] !== "," ? { lat: config["center"][1], lng: config["center"][0], } : { lat: 0, lng: 0, }; const style = config["style"] ? config["style"] : null; console.log(`${ui.getName()}: API is loaded`); // init fontawesome icons ui.MarkerUI = MarkerUI.init(); ui.map = new google.maps.Map(mapDiv, { zoom, center, fullscreenControl: true, styles: style, }); ui.default_zoom = zoom; mapDiv.classList.add("mapboxgl-map"); ui.popup = new ui.MarkerUI({ map: ui.map, align: ["center", "top"], divClass: "mapboxgl-popup popup mapboxgl-popup-anchor-bottom d-none", html: '
' + '
×
' + '
' + "
", }); ui.popup.setMap(ui.map); ui.geocoder = new google.maps.Geocoder(); ui.cluster = new MarkerClusterer(ui.map, null, { styles: [ { width: 30, height: 30, className: "mapboxgl-cluster", }, ], }); el.dispatchEvent(new Event(Events.MAPAPILOADED)); } addMarker(crds, config) { const ui = this; const pos = { lat: crds[1], lng: crds[0], }; const marker = new ui.MarkerUI({ position: pos, map: ui.map, align: ["center", "top"], html: `
${config["icon"]}
`, onClick: () => { const el = document.querySelector(`#Marker${config["id"]}`); ui.showPopup(pos, config["content"]); el.dispatchEvent(new Event(Events.MAPMARKERCLICK)); }, }); ui.markers.push(marker); ui.cluster.addMarker(marker); return marker; } showPopup(pos, content) { const ui = this; const popup = ui.popup.getDiv(); if (ui.config["flyToMarker"]) { ui.map.setCenter(pos); // panTo if (!ui.config["noZoom"]) { ui.map.setZoom(18); } } // keep it hidden to render content popup.style.opacity = "0"; popup.classList.remove("d-none"); popup.querySelector(".mapboxgl-popup-content .html").innerHTML = content; popup .querySelector(".mapboxgl-popup-close-button") .addEventListener("click", (e) => { e.preventDefault(); ui.hidePopup(); }); // set position when content was rendered ui.popup.setPosition(pos, ["center", "top"]); // display popup popup.style.opacity = "1"; popup.style["margin-top"] = "-1rem"; } hidePopup() { const ui = this; const popup = ui.popup.getDiv(); popup.classList.add("d-none"); if (!ui.config["noRestoreBounds"] || ui.config["flyToBounds"]) { ui.restoreBounds(); } ui.el.dispatchEvent(new Event(Events.MAPPOPUPCLOSE)); } geocode(addr, callback) { const ui = this; ui.geocoder.geocode( { address: addr, }, (results, status) => { if (status === "OK") { //results[0].geometry.location; if (typeof callback === "function") { callback(results); } return results; } else { console.error( `${ui.getName()}: Geocode was not successful for the following reason: ${status}` ); } } ); } reverseGeocode(latLng, callback) { const ui = this; ui.geocoder.geocode( { location: latlng, }, (results, status) => { if (status === "OK") { //results[0].formatted_address; if (typeof callback === "function") { callback(results); } return results; } else { console.error( `${ui.getName()}: Reverse Geocoding was not successful for the following reason: ${status}` ); } } ); } addGeoJson(config) { const ui = this; const geojson = JSON.parse(config["geojson"]); const firstMarker = geojson.features[0].geometry.coordinates; //Map.setCenter(firstMarker); const bounds = new google.maps.LatLngBounds(); // add markers to map geojson.features.forEach((marker) => { const id = marker.id; const crds = marker.geometry.coordinates; const content = marker.properties.content; ui.addMarker(crds, { id, content, icon: marker.icon, flyToMarker: config["flyToMarker"], }); bounds.extend({ lat: crds[1], lng: crds[0], }); }); if (ui.markers.length > 1) { ui.map.fitBounds(bounds, { padding: 30, }); //panToBounds } else if (ui.markers[0]) { ui.map.setCenter(ui.markers[0].getPosition()); } ui.default_bounds = bounds; ui.default_zoom = ui.map.getZoom(); } getMap() { const ui = this; return ui.map; } getPopup() { const ui = this; return ui.popup; } restoreBounds() { const ui = this; if (ui.default_bounds && ui.markers.length > 1) { ui.map.fitBounds(ui.default_bounds, { padding: 30, }); //panToBounds } else { if (ui.markers[0]) { ui.map.setCenter(ui.markers[0].getPosition()); } ui.restoreZoom(); } } restoreZoom() { const ui = this; ui.map.setZoom(ui.default_zoom); } } return GoogleMapsDriver; })(window); export default GoogleMapsDriver;