import { h } from 'lib/h' import * as Button from 'lib/button' import * as ContextMenu from 'lib/contextMenu' import * as Layout from 'lib/layout' import * as Modal from 'lib/modal' import * as Marker from 'marker' import * as MarkerForm from 'markerForm' import * as State from 'state' import * as Serialization from 'serialization' const L = window.L export function view() { // Wait for elements to be on page before installing map window.setTimeout(installMap, 0) return layout() } const mapId: string = 'g-Map__Content' function layout(): Element { return h('div', { className: 'g-Layout__Page' }, h('div', { className: 'g-Layout__Header' }, h('a', { className: 'g-Layout__Home', href: '#' }, 'Map' ) ) , h('div', { className: 'g-Map' }, h('div', { id: mapId}) ) ) } function installMap(): object { const map = L.map(mapId, { center: [51.505, -0.09], zoom: 2, attributionControl: false }) map.addLayer(L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png')) const mapMarkers = L.featureGroup() map.addLayer(mapMarkers) map.addEventListener('contextmenu', e => { ContextMenu.show( e.originalEvent, [ { label: 'Add a marker', action: () => { const pos = e.latlng const lastMarker = State.last() Modal.show(MarkerForm.view({ onValidate: (color: string, icon: string, name: string, radius: number) => { const id = State.add({ pos, color, icon, name, radius }) Marker.add({ id, pos, color, icon, name, radius, addToMap: marker => mapMarkers.addLayer(marker), removeFromMap: marker => mapMarkers.removeLayer(marker) }) Modal.hide() }, onCancel: () => Modal.hide(), color: lastMarker ? lastMarker.color : '#3F92CF', icon: lastMarker ? lastMarker.icon : '', name: '', radius: 0, })) } } ] ) }) // Init from hash const hash = window.location.hash.substr(1) const state = Serialization.decode(hash) State.reset(state) addMarkers({ map, mapMarkers, state, isInit: true }) // Reload from hash window.addEventListener('popstate', _ => reloadFromHash(map, mapMarkers)) return map } export function reloadFromHash(map: L.Map, mapMarkers: L.FeatureGroup) { const state = Serialization.decode(window.location.hash.substr(1)) mapMarkers.clearLayers() addMarkers({ map, mapMarkers, state, isInit: false }) } interface AddMarkersOptions { map: L.Map, mapMarkers: L.FeatureGroup, state: State.State, isInit: boolean, } function addMarkers({ map, mapMarkers, state, isInit }: AddMarkersOptions) { state.forEach((marker, id) => { const { pos, color, icon, name, radius } = marker Marker.add({ id, pos, color, icon, name, radius, addToMap: marker => mapMarkers.addLayer(marker), removeFromMap: marker => mapMarkers.removeLayer(marker) }) }) // Focus if (state.length > 0 && (isInit || !map.getBounds().contains(mapMarkers.getBounds()))) { map.fitBounds(mapMarkers.getBounds(), { padding: [ 50, 50 ] }) } }