It's probably my poor knowledge in JS but I am stuck. My issue is that anything I place where !!!PROBLEM IS HERE!!!
(see code below) is located, is set to the last iteration, here water
as key and "{% static 'map/img/modes/water.png'%}"
as value.
template.html
<script>
for (mode in modes) {
btn_mode = new L.easyButton('<img src="' + modes[mode] + '" style="width: 24px; height: 24px;"/>', function(btn, map){
window.location='/' + mode; <--------- !!!PROBLEM IS HERE!!!
},
'Mode "' + mode + '" information here'
);
btn_mode.addTo(map).setPosition('topleft');
}
</script>
with modes
looking like this (in reality I collect this data in Python, dump it as JSON and pass it onto my map template using the Django template language):
template.html
// Normally retrieved by calling "var modes = JSON.parse('{{ modes | safe }}');"
var modes = {
'default': "{% static 'map/img/modes/default.png'%}",
'agriculture': "{% static 'map/img/modes/argriculture.png'%}",
'commerce': "{% static 'map/img/modes/commerce.png'%}",
'energy': "{% static 'map/img/modes/energy.png'%}",
'environment': "{% static 'map/img/modes/environment.png'%}",
'geology': "{% static 'map/img/modes/geology.png'%}",
'health': "{% static 'map/img/modes/health.png'%}",
'insurance': "{% static 'map/img/modes/insurance.png'%}",
'vegetation': "{% static 'map/img/modes/leaf.png'%}",
'military': "{% static 'map/img/modes/military.png'%}",
'social': "{% static 'map/img/modes/social.png'%}",
'weather': "{% static 'map/img/modes/weather.png'%}",
'thermal': "{% static 'map/img/modes/thermal.png'%}",
'water': "{% static 'map/img/modes/water.png'%}",
}
I don't get this problem if I e.g. place a simple console.log(mode + ' : ' + modes[mode])
at the beginning or the end of the loop's body. I also do not get this issue from the first (icon source) and third (tooltip message) argument of the EasyButton
constructor call. Is there some general JS thing I am missing here or perhaps is it specific to this Leaflet plugin?
Given a JSON dictionary I would like to populate my Leaflet map with buttons that
- automatically get a specific icon assigned based on the current item's value (in my case Django
static
image file) - automatically redirect the user based on the current item's key, which represents a Django view.
My intention is to automatically populate the buttons based on the functionality I have implemented (apps and the respective views) and trigger a redirection to a different view (e.g. 127.0.0.1:8000/environment
for the environment button using the environment.png
static file as an icon). All of this is of course mostly done on the Python side, where the Django apps are installed and managed. Here is how it's currently being visualized:
Minimal reproducible example
The problem is not related to Django. Also I have tried moving the declaration of btn_mode
outside of the loop as well as put everything inside an outside-of-the-loop defined array. Result is always the same.
I work with Eclipse (Django Plugin) but the following example is much easier to check out using e.g. VS Code and the Five Server (or similar simple server for live preview of web content) extension. The Leaflet zoom controls and the world mini map plugins can be removed. I left those so that visually it comes closer to what I am looking for.
<!DOCTYPE html>
<html lang="en">
<head>
<base target="_top">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Map</title>
<link rel="shortcut icon" type="image/x-icon" href="#" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css"
integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2/src/easy-button.css">
<script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"
integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
<script src="https://cdn.jsdelivr.net/gh/maneoverland/leaflet.WorldMiniMap@1.0.0/dist/Control.WorldMiniMap.js"
integrity="sha512-PFw8St3qenU1/dmwCfiYYN/bRcqY1p3+sBATR+rZ6622eyXOk/8izVtlmm/k8qW7KbRIJsku838WCV5LMs6FCg=="
crossorigin=""></script>
<script src="https://cdn.jsdelivr.net/npm/leaflet-easybutton@2/src/easy-button.js"></script>
<style>
html, body {
height: 100%;
margin: 0;
}
.leaflet-container {
height: 100%;
width: 100%;
max-width: 100%;
max-height: 100%;
}
</style>
</head>
<body>
<div id="map" style="width: 100%; height: 100%;"></div>
<script>
const map = L.map('map').setView([48.947012, 8.411119], 13);
const tiles = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
var worldMiniMap = L.control.worldMiniMap(
{
position: 'topright',
style: {
opacity: 0.8,
borderRadius: '0px',
backgroundColor: 'lightblue'
}
}).addTo(map);
</script>
<script>
var modes = {
'a' : 'https://www.freeiconspng.com/uploads/close-icon-46.jpg',
'b' : 'https://www.freeiconspng.com/uploads/close-icon-46.jpg',
'c' : 'https://www.freeiconspng.com/uploads/close-icon-46.jpg',
}
</script>
<script>
for (var mode in modes) {
console.debug(mode + ' | path "' + modes[mode] + '"');
var btn_mode = L.easyButton('<img src="' + modes[mode] + '" style="width: 24px; height: 24px;"/>', function(btn, map){
window.location='/' + mode;
},
'TODO Mode "' + mode + '" information'
);
btn_mode.addTo(map).setPosition('topleft');
}
</script>
</body>
</html>
What you will see here is that, upon clicking on any of the three buttons, the page will redirect you to <some host>/c
.