UNPKG

@randstad-design/orbit-multitheme

Version:

multitheme Front-end code based on Randstad Human Forward components

287 lines (256 loc) 7.98 kB
/** * maps.js * load google maps with markers and related popups */ import { GoogleMapsApi } from './maps/google-maps-api'; import { MapStyle } from './maps/map-style'; import { PopupWrapper } from './maps/popup-wrapper'; import MarkerClusterer from '@googlemaps/markerclustererplus'; /** * Declare constants */ const attributeBase = 'data-rs-maps'; let Popup = null; export class Maps { constructor(element) { this.map = null; this.element = element; this.locations = []; this.marker = null; this.popup = null; // get elements this.googleMapsKey = this.element.hasAttribute(this.attributes.googleMapsKey) && this.element.getAttribute(this.attributes.googleMapsKey); this.markerUrlPath = this.element.hasAttribute(this.attributes.markerUrl) ? this.element.getAttribute(this.attributes.markerUrl) : this.variables.defaultMarkerUrl; this.clusterMarkerUrlPath = this.element.hasAttribute( this.attributes.clusterMarkerUrl ) ? this.element.getAttribute(this.attributes.clusterMarkerUrl) : this.variables.defaultClusterMarkerUrl; this.markerIsNotClickable = this.element.hasAttribute(this.attributes.markerIsNotClickable) || false; this.mapPlaceholderElement = this.element.querySelector( this.attributes.mapsPlaceholderElement ); this.mapElement = this.mapPlaceholderElement.appendChild( document.createElement('div') ); this.clusterEnabled = this.element.getAttribute(this.attributes.cluster); this.initializeMap(); } /** * Declare attribute constants */ get attributes() { return { clusterMarkerUrl: `${attributeBase}-cluster-marker-url`, markerUrl: `${attributeBase}-marker-url`, markerIsNotClickable: `${attributeBase}-marker-is-not-clickable`, mapsPlaceholderElement: `[${attributeBase}-placeholder]`, googleMapsKey: `${attributeBase}-google-maps-key`, cluster: `${attributeBase}-cluster` }; } /** * Declare variable constants */ get variables() { return { defaultMarkerUrl: '../assets/image/marker.svg', defaultClusterMarkerUrl: '../assets/image/m' }; } /** * Load google maps API */ initializeMap() { // create map, controls and markers after the API is ready const gmapApi = new GoogleMapsApi(this.googleMapsKey); gmapApi .load() .then(() => { this.createMap(); this.customZoomControl(this.mapPlaceholderElement); this.handleMarkers(); this.addMarker(this.locations); if (this.clusterEnabled) { this.setClusterMarkers(); } }) .catch((reason) => { console.error(reason); }); } createMap() { //retrieve center location let zoom = parseInt(this.element.getAttribute('data-rs-maps-zoom')); if (isNaN(zoom)) { zoom = 6; } // get center of map const [centerLat, centerLng] = this.element .getAttribute('data-rs-maps') .split(','); // create map this.map = new google.maps.Map(this.mapPlaceholderElement, { center: new google.maps.LatLng(centerLat, centerLng), zoom: zoom, minZoom: 4, maxZoom: 17, disableDefaultUI: true, panControl: true, zoomControl: false, scaleControl: true, streetViewControl: false, styles: MapStyle.custom, mapTypeId: google.maps.MapTypeId.ROADMAP }); } /** * Create Popup class if not already exists * always AFTER the map is created */ createPopup() { if (Popup === null) { Popup = PopupWrapper.popupClass; } } /** * Retrieve markers from html elements with attribute 'data-rs-map-marker' * and add them to the map */ handleMarkers() { // create the popup class this.createPopup(); this.locations = [].slice .call(this.element.querySelectorAll('[data-rs-map-marker]')) .map((markerElement) => { //build marker item let [lat, lng] = markerElement .getAttribute('data-rs-map-marker') .split(','); const item = {}; item.lat = lat.trim(); item.lng = lng.trim(); item.content = document.createElement('div'); item.content.innerHTML = markerElement.innerHTML; return item; }); // handle click on map related to popups google.maps.event.addListener(this.map, 'click', () => { if (this.marker !== null && typeof this.marker !== 'undefined') { this.marker.open = false; this.marker.customPopup.hide(); } }); } /** * Add marker to the map * @param {any} item Object containing base settings */ addMarker(locations) { // create icon for marker let icon = { url: this.markerUrlPath, size: new google.maps.Size(34, 48) }; this.markers = locations.map((item) => { let popup = new Popup( new google.maps.LatLng(item.lat, item.lng), item.content ); const marker = new google.maps.Marker({ position: new google.maps.LatLng(item.lat, item.lng), icon: icon, map: this.map, customPopup: popup }); popup.marker = marker; if (!this.markerIsNotClickable) { google.maps.event.addListener(marker, 'click', () => { // determine to show or hide the popup let openMarker = false; if (marker.open !== true) { openMarker = true; } if (this.marker !== null && marker !== this.marker) { this.marker.open = false; this.marker.customPopup.hide(); } // set active marker this.marker = marker; // handle display popup if (openMarker) { this.marker.customPopup.setMap(this.marker.map); this.marker.open = true; } else { this.marker.customPopup.hide(); this.marker.open = false; } }); } return marker; }); } setClusterMarkers() { const clusterOptions = { imagePath: this.clusterMarkerUrlPath, imageExtension: 'svg', maxZoom: 15 }; const markerClusterer = new MarkerClusterer( this.map, this.markers, clusterOptions ); // Change styles after cluster is created const styles = markerClusterer.getStyles(); for (let i = 0; i < styles.length; i++) { styles[i].textColor = 'white'; styles[i].textSize = 16; styles[i].width = 58; styles[i].height = 66; styles[i].textLineHeight = 66; } } /** * Create a custom zoom control * @param {any} controlContainer */ customZoomControl(controlContainer) { // hide control container let controlWrapper = controlContainer.appendChild( document.createElement('div') ); controlWrapper.classList.add('gmaps__control-container'); controlWrapper.classList.add('gmaps__control-container--loading'); // create element zoom in/out button let zoomInButton = document.createElement('div'); let zoomOutButton = document.createElement('div'); // create classes for buttons zoomInButton.classList.add('gmaps__button--zoom'); zoomInButton.classList.add('gmaps__button--zoom-in'); zoomOutButton.classList.add('gmaps__button--zoom'); zoomOutButton.classList.add('gmaps__button--zoom-out'); // append controls controlWrapper.appendChild(zoomInButton); controlWrapper.appendChild(zoomOutButton); // Setup the click event listener - zoomIn google.maps.event.addDomListener(zoomInButton, 'click', () => { this.map.setZoom(this.map.getZoom() + 1); }); // Setup the click event listener - zoomOut google.maps.event.addDomListener(zoomOutButton, 'click', () => { this.map.setZoom(this.map.getZoom() - 1); }); } /** * Get selector */ static getSelector() { return `[${attributeBase}]`; } }