Files
nairobi/app/assets/javascripts/map.js
Javi Martín 5a432da498 Update old usages of investments JSON data
We aren't using these properties since commit 3fa3c90db. An old test was
failing when checking for Axe accessibility issues because of this.
2025-11-17 15:45:28 +01:00

280 lines
8.8 KiB
JavaScript

(function() {
"use strict";
App.Map = {
maps: [],
initialize: function() {
$("*[data-map]:visible").each(function() {
App.Map.initializeMap(this);
});
},
destroy: function() {
App.Map.maps.forEach(function(map) {
map.off();
map.remove();
});
App.Map.maps = [];
},
initializeMap: function(element) {
var createMarker, editable, geozoneLayers, investmentsMarkers, map, marker, markerClustering,
markerData, markerIcon, markers, moveOrPlaceMarker, removeMarker, removeMarkerSelector;
App.Map.cleanInvestmentCoordinates(element);
removeMarkerSelector = $(element).data("marker-remove-selector");
investmentsMarkers = $(element).data("marker-investments-coordinates");
editable = $(element).data("marker-editable");
markerClustering = $(element).data("marker-clustering");
if (markerClustering) {
markers = L.markerClusterGroup({ chunkedLoading: true });
} else {
markers = L.layerGroup();
}
marker = null;
markerIcon = function(alt_text) {
return L.divIcon({
className: "map-marker",
iconSize: [30, 30],
iconAnchor: [15, 40],
html: $('<div class="map-icon"></div>').attr("aria-label", alt_text)[0].outerHTML
});
};
createMarker = function(latitude, longitude, text) {
var newMarker, markerLatLng;
markerLatLng = new L.LatLng(latitude, longitude);
newMarker = L.marker(markerLatLng, {
icon: markerIcon(text),
draggable: editable
});
if (editable) {
newMarker.on("dragend", function() {
App.Map.updateFormfields(map, newMarker);
});
}
markers.addLayer(newMarker);
return newMarker;
};
removeMarker = function() {
if (marker) {
map.removeLayer(marker);
marker = null;
}
App.Map.clearFormfields(element);
};
moveOrPlaceMarker = function(e) {
if (marker) {
marker.setLatLng(e.latlng);
} else {
marker = createMarker(e.latlng.lat, e.latlng.lng);
}
App.Map.updateFormfields(map, marker);
};
map = App.Map.leafletMap(element);
App.Map.maps.push(map);
App.Map.addAttribution(map);
markerData = App.Map.markerData(element);
if (markerData.lat && markerData.long && !investmentsMarkers) {
marker = createMarker(markerData.lat, markerData.long, markerData.title);
}
if (editable) {
$(removeMarkerSelector).on("click", removeMarker);
map.on("zoomend", function() {
if (marker) {
App.Map.updateFormfields(map, marker);
}
});
map.on("click", moveOrPlaceMarker);
}
App.Map.addInvestmentsMarkers(investmentsMarkers, createMarker);
geozoneLayers = App.Map.geozoneLayers(map);
App.Map.addGeozones(map, geozoneLayers);
App.Map.addLayerControl(map, geozoneLayers);
map.addLayer(markers);
},
leafletMap: function(element) {
var centerData, mapCenterLatLng, map;
centerData = App.Map.centerData(element);
mapCenterLatLng = new L.LatLng(centerData.lat, centerData.long);
map = L.map(element.id, { scrollWheelZoom: false }).setView(mapCenterLatLng, centerData.zoom);
map.on("focus", function() {
map.scrollWheelZoom.enable();
});
map.on("blur mouseout", function() {
map.scrollWheelZoom.disable();
});
return map;
},
attributionPrefix: function() {
return '<a href="https://leafletjs.com" title="A JavaScript library for interactive maps">Leaflet</a>';
},
markerData: function(element) {
var dataCoordinates, formCoordinates, inputs, latitude, longitude;
inputs = App.Map.coordinatesInputs(element);
dataCoordinates = {
lat: $(element).data("marker-latitude"),
long: $(element).data("marker-longitude"),
title: $(element).data("marker-title")
};
formCoordinates = {
lat: inputs.lat.val(),
long: inputs.long.val(),
zoom: inputs.zoom.val()
};
if (App.Map.validCoordinates(formCoordinates)) {
latitude = formCoordinates.lat;
longitude = formCoordinates.long;
} else if (App.Map.validCoordinates(dataCoordinates)) {
latitude = dataCoordinates.lat;
longitude = dataCoordinates.long;
}
return {
lat: latitude,
long: longitude,
title: dataCoordinates.title,
zoom: formCoordinates.zoom
};
},
centerData: function(element) {
var markerCoordinates, latitude, longitude, zoom;
markerCoordinates = App.Map.markerData(element);
if (App.Map.validCoordinates(markerCoordinates)) {
latitude = markerCoordinates.lat;
longitude = markerCoordinates.long;
} else {
latitude = $(element).data("map-center-latitude");
longitude = $(element).data("map-center-longitude");
}
if (App.Map.validZoom(markerCoordinates.zoom)) {
zoom = markerCoordinates.zoom;
} else {
zoom = $(element).data("map-zoom");
}
return {
lat: latitude,
long: longitude,
zoom: zoom
};
},
coordinatesInputs: function(element) {
return {
lat: $($(element).data("latitude-input-selector")),
long: $($(element).data("longitude-input-selector")),
zoom: $($(element).data("zoom-input-selector"))
};
},
updateFormfields: function(map, marker) {
var inputs = App.Map.coordinatesInputs(map._container);
inputs.lat.val(marker.getLatLng().lat);
inputs.long.val(marker.getLatLng().lng);
inputs.zoom.val(map.getZoom());
},
clearFormfields: function(element) {
var inputs = App.Map.coordinatesInputs(element);
inputs.lat.val("");
inputs.long.val("");
inputs.zoom.val("");
},
addInvestmentsMarkers: function(markers, createMarker) {
if (markers) {
markers.forEach(function(coordinates) {
var marker;
if (App.Map.validCoordinates(coordinates)) {
marker = createMarker(coordinates.lat, coordinates.long, coordinates.title);
marker.bindPopup(App.Map.getPopupContent(coordinates));
}
});
}
},
cleanInvestmentCoordinates: function(element) {
var clean_markers, markers;
markers = $(element).attr("data-marker-investments-coordinates");
if (markers != null) {
clean_markers = markers.replace(/-?(\*+)/g, null);
$(element).attr("data-marker-investments-coordinates", clean_markers);
}
},
addAttribution: function(map) {
var element, mapAttribution, mapTilesProvider;
element = map._container;
mapTilesProvider = $(element).data("map-tiles-provider");
mapAttribution = $(element).data("map-tiles-provider-attribution");
map.attributionControl.setPrefix(App.Map.attributionPrefix());
L.tileLayer(mapTilesProvider, { attribution: mapAttribution }).addTo(map);
},
addGeozones: function(map, geozoneLayers) {
$.each(geozoneLayers, function(_, geozoneLayer) {
App.Map.addGeozone(map, geozoneLayer);
});
},
addLayerControl: function(map, geozoneLayers) {
if (Object.keys(geozoneLayers).length > 1) {
L.control.layers(null, geozoneLayers).addTo(map);
}
},
geozoneLayers: function(map) {
var geozones = $(map._container).data("geozones");
var layers = {};
if (geozones) {
geozones.forEach(function(geozone) {
if (geozone.outline_points) {
layers[geozone.name] = App.Map.geozoneLayer(geozone);
}
});
}
return layers;
},
geozoneLayer: function(geozone) {
var geojsonData = JSON.parse(geozone.outline_points);
return L.geoJSON(geojsonData, {
style: function(feature) {
return {
color: feature.properties.color || geozone.color,
fillOpacity: 0.3,
className: "map-polygon"
};
},
onEachFeature: function(feature, layer) {
var headings = feature.properties.headings || geozone.headings;
if (headings) {
layer.bindPopup(headings.join("<br>"));
}
}
});
},
addGeozone: function(map, geozoneLayer) {
geozoneLayer.addTo(map);
},
getPopupContent: function(data) {
return "<a href='" + data.link + "'>" + data.title + "</a>";
},
validZoom: function(zoom) {
return App.Map.isNumeric(zoom);
},
validCoordinates: function(coordinates) {
return App.Map.isNumeric(coordinates.lat) && App.Map.isNumeric(coordinates.long);
},
isNumeric: function(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
};
}).call(this);