summaryrefslogtreecommitdiff
path: root/client/map
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2019-04-19 00:50:45 +0200
committerJules Laplace <julescarbon@gmail.com>2019-04-19 00:50:45 +0200
commit9515fc2e473e3fc51fbf26b77d3f49122808ce1b (patch)
tree9d8f382bae76855e7868abe74d35cfe50f33edc8 /client/map
parent03dae85958c9f4c4a41c9c5534cd54ccc1d04c5f (diff)
filter map by type
Diffstat (limited to 'client/map')
-rw-r--r--client/map/index.js302
1 files changed, 179 insertions, 123 deletions
diff --git a/client/map/index.js b/client/map/index.js
index 29fc2286..4492a69a 100644
--- a/client/map/index.js
+++ b/client/map/index.js
@@ -28,7 +28,9 @@ const arcStyles = {
},
}
+const buttonOrder = ['edu', 'company', 'gov']
const sortOrder = ['edu', 'company', 'gov', 'mil']
+const typeScores = { all: 0, edu: 1, company: 2, gov: 3, mil: 3 }
const redDot = L.icon({
iconUrl: '/assets/img/reddot.png',
@@ -37,145 +39,199 @@ const redDot = L.icon({
popupAnchor: [0, -5] // point from which the popup should open relative to the iconAnchor
})
-function addMarker(map, latlng, citations) {
- const marker = L.marker(latlng, { icon: redDot }).addTo(map)
- let message = citations.map(citation => {
- const { title, addresses, year, pdf, doi } = citation
- let rec = [
- "<b>", title, "</b>",
- ]
- if (pdf && pdf.length) {
- rec.unshift("<a href='" + pdf[0] + "' target='_blank'>")
- rec.push("</a>")
- }
- else if (doi && doi.length) {
- rec.unshift("<a href='" + doi[0] + "' target='_blank'>")
- rec.push("</a>")
+class Map {
+ constructor(el, data) {
+ let { paper, citations } = data
+ this.el = el
+ this.paper = paper
+ this.markers = []
+ this.arcs = []
+ this.filter = typeScores.all
+
+ if (paper.addresses && paper.addresses.length) {
+ this.source = [
+ paper.addresses[0].lat,
+ paper.addresses[0].lng
+ ].map(n => (parseFloat(n) || 0))
+ } else {
+ console.error("No address found for root paper")
+ this.source = [0, 0]
+ // console.log(data)
}
- if (year) {
- rec.push(" (" + year + ")")
+
+ // group papers by address
+ this.citationsByAddress = {}
+ this.citations = citations
+ this.citations.forEach(citation => {
+ if (!citation.addresses) {
+ return
+ }
+ citation.addresses.forEach(address => {
+ if (!(address.name in this.citationsByAddress)) {
+ this.citationsByAddress[address.name] = { address, citations: [] }
+ }
+ this.citationsByAddress[address.name].citations.push(citation)
+ })
+ })
+ this.build()
+ this.bind()
+ this.buildMarkers()
+ this.rootMarker.openPopup()
+ }
+
+ build() {
+ this.map = L.map(this.el).setView([25, 0], 2)
+ L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
+ attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
+ '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
+ 'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
+ maxZoom: 18,
+ id: 'mapbox.dark',
+ style: 'mapbox://styles/mapbox/dark-v9',
+ accessToken: 'pk.eyJ1IjoiZmFuc2FsY3kiLCJhIjoiY2pvN3I1czJwMHF5NDNrbWRoMWpteHlrdCJ9.kMpM5syQUhVjKkn1iVx9fg'
+ }).addTo(this.map)
+ }
+
+ bind() {
+ // a transparent div to cover the map, so normal scroll events will not be eaten by leaflet
+ const mapCover = document.createElement("div")
+ mapCover.classList.add("map_cover")
+ mapCover.innerHTML = "<div class='cover_message'>Click here to explore the map</div>"
+ mapCover.querySelector('div').addEventListener('click', () => {
+ this.map.scrollWheelZoom.enable()
+ if (mapCover.parentNode === this.el) {
+ this.el.removeChild(mapCover)
+ }
+ })
+ mapCover.querySelector('div').addEventListener('touchstart', (e) => {
+ e.preventDefault()
+ })
+ mapCover.querySelector('div').addEventListener('tap', () => {
+ this.map.scrollWheelZoom.enable()
+ if (mapCover.parentNode === this.el) {
+ this.el.removeChild(mapCover)
+ }
+ })
+ function stopPropagation(e) {
+ e.stopPropagation()
}
- const addressString = addresses.map(addr => addr.name).join('<br/>')
- rec.push("<br>")
- rec.push(addressString)
- return rec.join("")
- })
+ mapCover.addEventListener('mousewheel', stopPropagation, true)
+ mapCover.addEventListener('DOMMouseScroll', stopPropagation, true)
- marker.bindPopup(message.join('<br><br>'))
- return marker
-}
+ this.map.scrollWheelZoom.disable()
+ this.map.on('focus', () => {
+ this.map.scrollWheelZoom.enable()
+ if (mapCover.parentNode === this.el) {
+ this.el.removeChild(mapCover)
+ }
+ })
+ this.map.on('blur', () => {
+ this.map.scrollWheelZoom.disable()
+ // el.appendChild(mapCover)
+ })
-function addArc(map, src, dest, arcStyle) {
- L.bezier({
- path: [
- [
- { lat: src[0], lng: src[1] },
- { lat: dest[0], lng: dest[1] },
- ],
- ]
- }, arcStyle).addTo(map)
-}
+ this.el.appendChild(mapCover)
-export default function append(el, payload) {
- const { data } = payload
- if (!data) return
- let { paper, citations } = data
- let source = [0, 0]
+ buttonOrder.forEach(type => {
+ const typeClass = type.substr(0, 3)
+ const el = document.querySelector('.map-legend .' + typeClass)
+ el.addEventListener('click', () => {
+ console.log(el)
+ this.filterMarkers(el, type)
+ })
+ })
+ }
- let map = L.map(el).setView([25, 0], 2)
- L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
- attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
- '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
- 'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
- maxZoom: 18,
- id: 'mapbox.dark',
- style: 'mapbox://styles/mapbox/dark-v9',
- accessToken: 'pk.eyJ1IjoiZmFuc2FsY3kiLCJhIjoiY2pvN3I1czJwMHF5NDNrbWRoMWpteHlrdCJ9.kMpM5syQUhVjKkn1iVx9fg'
- }).addTo(map)
+ filterMarkers(el, type) {
+ const active = document.querySelector('.map-legend .active')
+ if (active) active.classList.remove('active')
+ const newFilter = typeScores[type]
+ if (this.filter === newFilter) {
+ this.filter = typeScores.all
+ } else {
+ this.filter = newFilter
+ el.classList.add('active')
+ }
+ this.buildMarkers()
+ }
- if (paper.addresses && paper.addresses.length) {
- source = [paper.addresses[0].lat, paper.addresses[0].lng].map(n => (parseFloat(n) || 0))
- } else {
- console.error("No address found for root paper")
- // console.log(data)
+ resetMarkers() {
+ this.arcs.forEach(arc => arc.remove())
+ this.markers.forEach(marker => marker.remove())
+ this.markers = []
+ this.arcs = []
}
- // group papers by address
- let citationsByAddress = {}
- citations.forEach(citation => {
- if (!citation.addresses) {
+ buildMarkers() {
+ this.resetMarkers()
+ Object.keys(this.citationsByAddress).map(name => {
+ const { citations: citationList, address } = this.citationsByAddress[name]
+ if (this.filter && typeScores[address.type] !== this.filter) return
+ // console.log(name, citationsByAddress[name])
// console.log(citation)
- return
- }
- // console.log(citation)
- citation.addresses.forEach(address => {
- if (!(address.name in citationsByAddress)) {
- citationsByAddress[address.name] = { address, citations: []}
+ const latlng = [address.lat, address.lng].map(n => parseFloat(n))
+ if (Number.isNaN(latlng[0]) || Number.isNaN(latlng[1])) return
+ this.addMarker(latlng, citationList)
+ const style = { ...arcStyles[address.type] }
+ let weight = Math.min(citationList.length, 5)
+ let opacity = 0.5 + Math.min(citationList.length / 5, 0.5)
+ if (address.type !== 'edu') {
+ weight += 1
+ opacity = 1
}
- citationsByAddress[address.name].citations.push(citation)
+ style.weight = String(weight)
+ style.opacity = opacity
+ this.addArc(this.source, latlng, style)
})
- })
- Object.keys(citationsByAddress).map(name => {
- const { citations: citationList, address: citationAddress } = citationsByAddress[name]
- // console.log(name, citationsByAddress[name])
- // console.log(citation)
- const latlng = [citationAddress.lat, citationAddress.lng].map(n => parseFloat(n))
- if (Number.isNaN(latlng[0]) || Number.isNaN(latlng[1])) return
- addMarker(map, latlng, citationList)
- const style = { ...arcStyles[citationAddress.type] }
- let weight = Math.min(citationList.length, 5)
- let opacity = 0.5 + Math.min(citationList.length / 5, 0.5)
- if (citationAddress.type !== 'edu') {
- weight += 1
- opacity = 1
- }
- style.weight = String(weight)
- style.opacity = opacity
- addArc(map, source, latlng, style)
- })
-
- // console.log(paper)
+ this.rootMarker = this.addMarker(this.source, [this.paper])
+ }
- const rootMarker = addMarker(map, source, [paper])
- rootMarker.openPopup()
+ addMarker(latlng, citations) {
+ const marker = L.marker(latlng, { icon: redDot }).addTo(this.map)
+ let message = citations.map(citation => {
+ const { title, addresses, year, pdf, doi } = citation
+ let rec = [
+ "<b>", title, "</b>",
+ ]
+ if (pdf && pdf.length) {
+ rec.unshift("<a href='" + pdf[0] + "' target='_blank'>")
+ rec.push("</a>")
+ }
+ else if (doi && doi.length) {
+ rec.unshift("<a href='" + doi[0] + "' target='_blank'>")
+ rec.push("</a>")
+ }
+ if (year) {
+ rec.push(" (" + year + ")")
+ }
+ const addressString = addresses.map(addr => addr.name).join('<br/>')
+ rec.push("<br>")
+ rec.push(addressString)
+ return rec.join("")
+ })
- // a transparent div to cover the map, so normal scroll events will not be eaten by leaflet
- const mapCover = document.createElement("div")
- mapCover.classList.add("map_cover")
- mapCover.innerHTML = "<div class='cover_message'>Click here to explore the map</div>"
- mapCover.querySelector('div').addEventListener('click', () => {
- map.scrollWheelZoom.enable()
- if (mapCover.parentNode === el) {
- el.removeChild(mapCover)
- }
- })
- mapCover.querySelector('div').addEventListener('touchstart', (e) => {
- e.preventDefault()
- })
- mapCover.querySelector('div').addEventListener('tap', () => {
- map.scrollWheelZoom.enable()
- if (mapCover.parentNode === el) {
- el.removeChild(mapCover)
- }
- })
- function stopPropagation(e) {
- e.stopPropagation()
+ marker.bindPopup(message.join('<br><br>'))
+ this.markers.push(marker)
+ return marker
}
- mapCover.addEventListener('mousewheel', stopPropagation, true)
- mapCover.addEventListener('DOMMouseScroll', stopPropagation, true)
- map.scrollWheelZoom.disable()
- map.on('focus', () => {
- map.scrollWheelZoom.enable()
- if (mapCover.parentNode === el) {
- el.removeChild(mapCover)
- }
- })
- map.on('blur', () => {
- map.scrollWheelZoom.disable()
- // el.appendChild(mapCover)
- })
+ addArc(src, dest, arcStyle) {
+ const arc = L.bezier({
+ path: [
+ [
+ { lat: src[0], lng: src[1] },
+ { lat: dest[0], lng: dest[1] },
+ ],
+ ]
+ }, arcStyle).addTo(this.map)
+ this.arcs.push(arc)
+ }
+}
- el.appendChild(mapCover)
+export default function append(el, payload) {
+ const { data } = payload
+ if (!data) return
+ let mapContainer = new Map(el, data)
+ return mapContainer
}