aboutsummaryrefslogtreecommitdiff
path: root/src/map.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/map.ts')
-rw-r--r--src/map.ts131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/map.ts b/src/map.ts
new file mode 100644
index 0000000..04a1351
--- /dev/null
+++ b/src/map.ts
@@ -0,0 +1,131 @@
+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 ] })
+ }
+}