6 <script src="js/jquery-3.1.0.min.js"></script>
7 <script src="js/chart.umd.js"></script>
8 <script src="js/js.storage.min.js"></script>
9 <script src="js/kismet.ui.theme.js"></script>
11 <link rel="stylesheet" type="text/css" href="css/font-awesome.min.css">
12 <link rel="stylesheet" href="css/leaflet.css" />
13 <link rel="stylesheet" type="text/css" href="css/jquery.jspanel.min.css" />
14 <link rel="stylesheet" type="text/css" href="css/Control.Loading.css" />
16 <script src="js/leaflet.js"></script>
17 <script src="js/Leaflet.MultiOptionsPolyline.min.js"></script>
18 <script src="js/Control.Loading.js"></script>
19 <script src="js/chroma.min.js"></script>
21 <script src="js/js.storage.min.js"></script>
22 <script src="js/kismet.utils.js"></script>
23 <script src="js/kismet.units.js"></script>
25 <script src="js/datatables.min.js"></script>
26 <script src="js/dataTables.scrollResize.js"></script>
28 <script src="https://d3js.org/d3.v4.min.js"></script>
35 <div id="warning" class="warning">
37 <p>To display the Russ map, your browser will connect to the Leaflet and Open Street Map servers to fetch the map tiles. This requires you have a functional Internet connection, and will reveal something about your location (the bounding region where planes have been seen.)
38 <p><input id="dontwarn" type="checkbox">Don't warn me again</input>
39 <p><button id="continue">Continue</button>
41 <div id="map"><svg style="width: 100%; height: 600px;"></svg></div>
45 function getNeighbors(node) {
46 return links.reduce(function (neighbors, link) {
47 if (link.target.id === node.id) {
48 neighbors.push(link.source.id)
49 } else if (link.source.id === node.id) {
50 neighbors.push(link.target.id)
58 function isNeighborLink(node, link) {
59 return link.target.id === node.id || link.source.id === node.id
63 function getNodeColor(node, neighbors) {
64 if (Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1) {
65 return node.level === 1 ? 'blue' : 'green'
68 return node.level === 1 ? 'red' : 'gray'
71 function getLinkColor(node, link) {
72 return isNeighborLink(node, link) ? 'green' : '#E5E5E5'
75 function getTextColor(node, neighbors) {
76 return Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1 ? 'green' : 'white'
79 function selectNode(selectedNode) {
80 var neighbors = getNeighbors(selectedNode)
82 // we modify the styles to highlight selected nodes
83 nodeElements.attr('fill', function (node) { return getNodeColor(node, neighbors) })
84 textElements.attr('fill', function (node) { return getTextColor(node, neighbors) })
85 linkElements.attr('stroke', function (link) { return getLinkColor(selectedNode, link) })
88 var window_visible = true;
90 // Visibility detection from https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
91 // Set the name of the hidden property and the change event for visibility
92 var hidden, visibilityChange;
93 if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
95 visibilityChange = "visibilitychange";
96 } else if (typeof document.msHidden !== "undefined") {
98 visibilityChange = "msvisibilitychange";
99 } else if (typeof document.webkitHidden !== "undefined") {
100 hidden = "webkitHidden";
101 visibilityChange = "webkitvisibilitychange";
104 function handleVisibilityChange() {
105 if (document[hidden]) {
106 window_visible = false;
108 window_visible = true;
112 // Warn if the browser doesn't support addEventListener or the Page Visibility API
113 if (typeof document.addEventListener === "undefined" || hidden === undefined) {
116 // Handle page visibility change
117 document.addEventListener(visibilityChange, handleVisibilityChange, false);
120 var urlparam = new URL(window.location.href);
121 var param_url = urlparam.searchParams.get('parent_url') + "/";
122 var param_prefix = urlparam.searchParams.get('local_uri_prefix', "");
123 var KISMET_PROXY_PREFIX = urlparam.searchParams.get('KISMET_PROXY_PREFIX', "");
125 if (param_prefix == 0)
128 var local_uri_prefix = param_url + param_prefix;
129 if (typeof(KISMET_URI_PREFIX) !== 'undefined')
130 local_uri_prefix = KISMET_URI_PREFIX;
132 var map_configured = false;
141 data = kismet.sanitizeObject(d);
143 map_configured = true;
144 var nodes = d['nodes']
145 var links = d['links']
147 var width = window.innerWidth
148 var height = window.innerHeight
150 var svg = d3.select('svg')
152 svg.attr('width', width).attr('height', height)
153 .call(d3.zoom().on("zoom", function () {
154 svg.attr("transform", d3.event.transform)
158 // simulation setup with all forces
161 .id(function (link) { return link.id })
162 .strength(function (link) { return link.strength })
166 //.force('link', linkForce)
167 .force('charge', d3.forceManyBody().strength(-10))
168 .force('center', d3.forceCenter(width / 2, height / 2))
169 .force('link', linkForce)
171 var dragDrop = d3.drag().on('start', function (node) {
174 }).on('drag', function (node) {
175 simulation.alphaTarget(0.7).restart()
178 }).on('end', function (node) {
179 if (!d3.event.active) {
180 simulation.alphaTarget(0)
186 var linkElements = svg.append("g")
187 .attr("class", "links")
190 .enter().append("line")
191 .attr("stroke-width", 1)
192 .attr("stroke", "rgba(255, 255, 255, 5.0)")
194 var nodeElements = svg.append("g")
195 .attr("class", "nodes")
198 .enter().append("circle")
200 .attr("fill", getNodeColor)
202 .on('click', selectNode)
204 var textElements = svg.append("g")
205 .attr("class", "texts")
208 .enter().append("text")
209 .text(function (node) { return node.label })
210 .attr("font-size", 15)
214 simulation.nodes(nodes).on('tick', () => {
216 .attr('cx', function (node) { return node.x })
217 .attr('cy', function (node) { return node.y })
219 .attr('x', function (node) { return node.x })
220 .attr('y', function (node) { return node.y })
222 .attr('x1', function (link) { return link.source.x })
223 .attr('y1', function (link) { return link.source.y })
224 .attr('x2', function (link) { return link.target.x })
225 .attr('y2', function (link) { return link.target.y })
228 simulation.force("link").links(links)
231 var load_maps = kismet.getStorage('kismet.russ.maps_ok', false);
233 function poll_map() {
234 if (window_visible && !$('#map').is(':hidden') && load_maps) {
235 $.get(local_uri_prefix + KISMET_PROXY_PREFIX + "phy/DOT/map_data.json")
237 console.log("sending to function");
240 //.always(function(d) {
241 // tid = setTimeout(function() { poll_map(); }, 2000);
244 tid = setTimeout(function() { poll_map(); }, 2000);
248 // Set a global timeout
252 withCredentials: true
257 $('#warning').hide();
259 $('#continue').on('click', function() {
260 if ($('#dontwarn').is(":checked"))
261 kismet.putStorage('kismet.russ.maps_ok', true);
262 $('#warning').hide();