var map = L.map('map', { minZoom: 5, maxZoom: 10 }).setView([50,18], 5); L.tileLayer('https://{s}.tile.thunderforest.com/spinal-map/{z}/{x}/{y}.png?apikey={apikey}', { attribution: '© Thunderforest, © OpenStreetMap contributors', apikey: 'db5ae1f5778a448ca662554581f283c5', }).addTo(map); var de1t = [50.085448739143715, 8.461733038044116]; // title, hostname, popup, location var nodes = { pl1: { location: [52.1904441909767, 20.922122237417636], city: "Warsaw, Poland", hostname: "pl1.420129.xyz", datacenter: "equinix wa3", description: "", publicKey: "v854+5m4Diqh8oGo6/sGVS7LELsreIjMujkWqwc6bWo=", linkLocal: "fe80::129:3" }, de1: { location: [49.44951340282083, 11.014075123186862], city: "Nuremberg, Germany", hostname: "de1.420129.xyz", datacenter: "hetzner nbg", description: "Tunneled to Frankfurt. If you have a node here at hetzner nuremberg, it will go nbg -> fra -> nbg.", publicKey: "N9rGceoiFcc/obnHrqMAmVlrb/E2Br55+doekTKwNF8=", linkLocal: "fe80::129:2" }, nl1: { location: [52.36679746122722, 4.891598348592709], city: "Amsterdam, Netherlands", hostname: "nl1.420129.xyz", datacenter: "scaleway AMS-1", description: "I don't know where exactly", publicKey: "iZfLBtF6BiQvdKXx4Yl02u+OL6ls35gSpWCRmB9q4lU=", linkLocal: "fe80::129:1" }, it1: { location: [41.66806722233489, 12.503981281868477], city: "Rome, Italy", hostname: "it1.420129.xyz", datacenter: "c1vhosting?", description: "Location also approximate, there's no evidence of the existence of the data center", publicKey: "", linkLocal: "fe80::129:4" } } function line(from, to, popup) { L.polyline([from, to], {opacity: 0.5}).addTo(map).bindPopup(popup); } var opened = null; const sidebarContent = document.getElementById("sidebarContent"); const nodesElement = document.getElementById("nodes"); sidebarContent.onclick = (ev) => { if (opened == null) return; const popup = opened[0]; const rect = opened[1].getBoundingClientRect(); console.log('a') //sidebarContent.removeChild(opened); popup.style.height = rect.height - 20 + 'px'; popup.style.transform = 'none'; nodesElement.style.opacity = 1; opened = null; map.closePopup(); setTimeout(() => { sidebarContent.removeChild(popup); }, 300); }; function onNodeClick(ev, node, elem) { console.log('b') if (opened != null) return; const rect = elem.getBoundingClientRect(); nodesElement.style.opacity = 0; ele = elem.cloneNode(true); ele.innerHTML += `

Datacenter: ${node.datacenter}
${node.description.split('\n').slice(1).join('\n')}`; ele.onclick = (ev) => {ev.stopPropagation()}; ele.classList.add('selectedNode'); sidebarContent.appendChild(ele); ele.style.width = rect.width - 40 + 'px'; // padding or margin ele.style.height = rect.height - 20 + 'px'; ele.style.top = rect.top - 10 + 'px'; //ele.style.left = rect.left - 10 + 'px'; ele.offsetHeight; const destY = 72 - rect.top; // window.innerHeight / 4 ele.style.transform = `translateY(${destY}px)`; ele.style.height = window.innerHeight / 3 + 'px'; opened = [ele, elem]; ev.stopPropagation(); } for (let node of Object.values(nodes)) { let marker = L.marker(node.location).addTo(map).bindPopup(`${node.city}
DC: ${node.datacenter}`); let ele = document.createElement("div"); ele.innerHTML = `${node.city}`; if (node.description != '') ele.innerHTML += `
${node.description.split('\n')[0]}`; ele.onclick = (ev) => { marker.openPopup(); map.panTo(node.location, { padding: [1000, 1000] }); onNodeClick(ev, node, ele); }; nodesElement.appendChild(ele); } line(nodes.de1.location, de1t, "Tunnel (already included in other labels)
4ms"); line(de1t, nodes.pl1.location, "de1 - pl1
24ms"); line(de1t, nodes.nl1.location, "de1 - nl1
10ms"); line(nodes.nl1.location, nodes.it1.location, "it1 - nl1
25ms");