I have written a JavaScript code (I just got started) which queries the Opensky REST API every 10 seconds. After I collect the data, I plot it through Leaflet.js. For each item I add a popup text box which opens when I click on the tooltip.
So far the code works great!
Here is the code so you can play around:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=\, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="id=edge">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin="">
</script>
<style>
#openskyMap {
height: 800px;
width:1200px;
}
</style>
<title>
"FETCH JSON from API and map lat lon"
</title>
</head>
<body>
<h1>Where are the flights</h1>
<p>Last Update (UNIX time): <span id="ts"></span></p>
<div id="openskyMap"></div>
/* JAVASCRIPT CODE BEGINS HERE */
<script>
/* DEFINE OPENSKY API URL */
var opensky_url = "https://opensky-network.org/api/states/all?time=TIME";
/* INITIATE LEAFLET MAP */
const mymap = L.map('openskyMap').setView([45, 0], 3);
const attribution = '© <a href="https://www.openstreetmap.org/copyright">OpenStreatMap</a> contributors'
const tileUrl = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
const tiles = L.tileLayer(tileUrl, {attribution});
var layerGroup = L.layerGroup().addTo(mymap);
tiles.addTo(mymap);
/* CHANGE ICON SIZE BASED ON ZOOM */
mymap.on('zoomend', function(e) {
var currentZoom = mymap.getZoom();
console.log("Current Zoom" + " " + currentZoom);
if (currentZoom >= 10) {
damsRadius = 100;
} else {
damsRadius = 20000;
}
});
/* FUNCTION TO GET THE ICAO24 CODE. I CANNOT GET IT OUT OF HERE THOUGH! */
function getIcao24(e) {
var popup = e.target.getPopup();
var content = popup.getContent();
console.log(content)
return content
}
/* INITIATE QUERY FUNCTION */
async function getOpensky() {
/* CALCULATE UNIX TIME TO BE PASSED TO THE URL */
var ts = Math.round((new Date()).getTime() / 1000);
ts = ts.toString();
/* MAKE QUERY TO OPENSKY URL */
const response = await fetch(opensky_url.replace('TIME',ts));
const data = await response.json();
/* PLOT ITEMS TO MAP USING LEAFLET:js */
layerGroup.clearLayers();
for (var key in data.states) {
/* GET SINGLE ITEM FROM JSON */
const item = data.states[key];
try{
/* GET GEOGRAPHICAL COORDINATES*/
const lon = item[5];
const lat = item[6];
/* DEFINE POPUP TEXT TO BE DISPLAYED*/
const popupText = "<p>"+item[0] + " - " + item[1] + "<br/>Lat: " + lat.toFixed(2)+" / Lon: "+lon.toFixed(2)+"<br/>Epoch: "+ts+"</p>";
/* ADD ITEM TO THE MAP. CALL getICAO24 FUNCTION BUT I DON'T KNOW HOW TO SAVE THE OUTPUT*/
L.circle(L.latLng(
parseFloat(item[6]), // lon
parseFloat(item[5]) // lat
), damsRadius).addTo(layerGroup).bindPopup(popupText).on('click', getIcao24);
document.getElementById('ts').textContent = ts;
}
catch (e) {}
}
}
/* CALL FUNCTION FIRST TIME*/
getOpensky();
/* UPDATE FUNCTION EVERY 10 SECONDS */
setInterval(getOpensky, 10000);
</script>
</body>
</html>
Every time I click on an aircraft (item
), the popup window opens as expected. However, I would like to keep the selected popup text open even after the refresh has occurred (setInterval
every 10 seconds). This is not happening due to the fact that when I click on the tooltip, the output is only displayed on the console but not store anywhere to be somehow recognized during the next query.
I though that one possible solution is to add a function called getIcao24
which should return the popup text and get the unique icao24
code (item[0]
) from the string and then check when it appears in the next iteration and set the popup box as open. However I have no clue how to get such information out of the function.
Would you be able to suggest a smart and elegant way to achieve my goal, i.e. maintain the popup box of a clicked item open even after a refresh has occurred?
Best Answer
There are probably many ways to achieve what you want, below is described one of them I usually use.
To have handy some property when you process marker event, you can 'misuse' marker object and just define this property as a new maker property, to which you can give any name as long as it does not collide with standard properties. In the example below it's
_myID
, which gets the value ofitem[0]
.Then when popup is opened (more pertinent
popupopen
event is used),_myID
property is saved in global variableidPopup
.When markers are refreshed next time,
item[0]
values are compared to saved id and upon match popup is opened.There is also
popupclose
event processing function to clearidPopup
if popup is closed by user before refresh. Since popup is closed also at the time marker removal/referesh, there isrefreshInProgress
variable to take care of that.popupFound
variable takes care of the case when marker with the popup is not displayed upon next refresh.So the code could the look something like this: