script.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. var widths = [12, 13, 13, 13, 13, 13, 13, 13];
  2. var opas = [0.8, 0.6, 0.5, 0.5, 0.4];
  3. var mwidths = [1, 1, 1, 1.5, 2, 3, 5, 6, 6, 4, 3, 2];
  4. var backend = "";
  5. var openGr = -1;
  6. var openSt = -1;
  7. function marker(stat, z) {
  8. if (stat.g.length == 1) {
  9. if (z > 15) {
  10. return L.circle(
  11. stat.g[0], {
  12. color: 'black',
  13. fillColor: stat.e ? 'red' : stat.s ? '#0000c3' : '#78f378',
  14. radius: mwidths[23 - z],
  15. fillOpacity: 1,
  16. weight: z > 17 ? 1.5 : 1,
  17. id: stat.i
  18. }
  19. );
  20. } else {
  21. return L.polyline(
  22. [stat.g[0], stat.g[0]], {
  23. color: stat.e ? 'red' : stat.s ? '#0000c3' : '#78f378',
  24. fillColor: stat.e ? 'red' : stat.s ? '#0000c3' : '#78f378',
  25. weight: widths[15 - z],
  26. opacity: opas[15 - z],
  27. id: stat.i
  28. }
  29. );
  30. }
  31. } else {
  32. return L.polygon(
  33. stat.g, {
  34. color: z > 15 ? 'black': (stat.e ? 'red' : stat.s ? '#0000c3' : '#78f378'),
  35. fillColor: stat.e ? 'red' : stat.s ? '#0000c3' : '#78f378',
  36. smoothFactor: 0,
  37. fillOpacity: 0.75,
  38. weight: z > 17 ? 1.5 : 1,
  39. id: stat.i
  40. }
  41. );
  42. }
  43. }
  44. function poly(group, z) {
  45. var col = group.e ? 'red' : group.s ? '#0000c3' : '#85f385';
  46. var style = {
  47. color: col,
  48. fillColor: col,
  49. smoothFactor: 0.4,
  50. fillOpacity: 0.2,
  51. id: group.i
  52. };
  53. if (group.n) {
  54. style.color = "#0000c3";
  55. style.fillColor = "#0000c3";
  56. }
  57. if (z < 16) {
  58. style.weight = 11;
  59. style.opacity = 0.5;
  60. style.fillOpacity = 0.5;
  61. }
  62. return L.polygon(group.g, style)
  63. }
  64. function sugArr(sug, z) {
  65. return L.polyline(sug.a, {
  66. id: sug.i,
  67. color: '#0000c3',
  68. smoothFactor: 0.1,
  69. weight: 4,
  70. opacity: 0.5
  71. });
  72. }
  73. function renderStat(stat) {
  74. openSt = stat.id;
  75. nodeHl(stat.id);
  76. var attrrows = {};
  77. var ll = {
  78. lat: stat.lat,
  79. lon: stat.lon
  80. };
  81. var way = stat.osmid < 0;
  82. var osmid = Math.abs(stat.osmid);
  83. var ident = way ? "Way" : "Node";
  84. var content = document.createElement('div');
  85. content.setAttribute("id", "nav")
  86. var suggD = document.createElement('div');
  87. suggD.setAttribute("id", "sugg")
  88. content.innerHTML = ident + " <a target='_blank' href='https://www.openstreetmap.org/"+ident.toLowerCase()+"/" + osmid + "'>" + osmid + "</a>";
  89. if (stat.attrs.name) {
  90. content.innerHTML += " (<b>\"" + stat.attrs.name + "\"</b>)";
  91. }
  92. content.innerHTML += "<a class='editbut' target='_blank' href='https://www.openstreetmap.org/edit?" + ident.toLowerCase() + "=" + osmid +"'>&#9998;</a>";
  93. var attrTbl = document.createElement('table');
  94. attrTbl.setAttribute("id", "attr-tbl")
  95. content.appendChild(attrTbl);
  96. content.appendChild(suggD);
  97. var tbody = document.createElement('tbody');
  98. attrTbl.appendChild(tbody);
  99. for (var key in stat.attrs) {
  100. var row = document.createElement('tr');
  101. var col1 = document.createElement('td');
  102. var col2 = document.createElement('td');
  103. col2.className = "err-wrap";
  104. tbody.appendChild(row);
  105. row.appendChild(col1);
  106. row.appendChild(col2);
  107. col1.innerHTML = "<a href=\"https://wiki.openstreetmap.org/wiki/Key:" + key + "\" target=\"_blank\"><tt>" + key + "</tt></a>";
  108. for (var i = 0; i < stat.attrs[key].length; i++) col2.innerHTML += "<span class='attrval'>" + stat.attrs[key][i] + "</span>" + "<br>";
  109. attrrows[key] = row;
  110. }
  111. for (var i = 0; i < stat.attrerrs.length; i++) {
  112. var err = stat.attrerrs[i];
  113. var row = attrrows[err.attr[0]];
  114. row.className = "err-" + Math.round(err.conf * 10);
  115. var info = document.createElement('div');
  116. if (err.other_grp) {
  117. // the mismatch was with a group name
  118. if (err.other_osmid > 1) {
  119. info.innerHTML = "Does not match <tt>" + err.other_attr[0] + "</tt> in relation <a onmouseover='groupHl( " + err.other_grp + ")' onmouseout='groupUnHl( " + err.other_grp + ")' target=\"_blank\" href=\"https://www.openstreetmap.org/relation/" + Math.abs(err.other_osmid) + "\">" + Math.abs(err.other_osmid) + "</a>";
  120. } else {
  121. info.innerHTML = "Does not match <tt>" + err.other_attr[0] + "</tt> in relation <span onmouseover='groupHl( " + err.other_grp + ")' onmouseout='groupUnHl( " + err.other_grp + ")'>" + Math.abs(err.other_osmid) + "</span>";
  122. }
  123. } else {
  124. // the mismatch was with another station
  125. if (err.other_osmid != stat.osmid) {
  126. var ident = err.other_osmid < 0 ? "way" : "node";
  127. info.innerHTML = "Does not match <tt>" + err.other_attr[0] + "</tt> in " + ident + " <a onmouseover='nodeHl( " + err.other + ")' onmouseout='nodeUnHl( " + err.other + ")' target=\"_blank\" href=\"https://www.openstreetmap.org/"+ident+"/" + Math.abs(err.other_osmid) + "\">" + Math.abs(err.other_osmid) + "</a>";
  128. } else {
  129. info.innerHTML = "Does not match <tt>" + err.other_attr[0] + "</tt> = '" + err.other_attr[1] + "'";
  130. }
  131. }
  132. info.className = 'attr-err-info';
  133. row.childNodes[1].appendChild(info);
  134. }
  135. var suggList = document.createElement('ul');
  136. if (stat.su.length) {
  137. var a = document.createElement('span');
  138. a.className = "sugtit";
  139. a.innerHTML = "Suggestions";
  140. suggD.appendChild(a);
  141. }
  142. suggD.appendChild(suggList);
  143. for (var i = 0; i < stat.su.length; i++) {
  144. var sugg = stat.su[i];
  145. var suggDiv = document.createElement('li');
  146. if (sugg.type == 1) {
  147. suggDiv.innerHTML = "Move into a <span class='grouplink' onmouseover='groupHl( " + sugg.target_gid + ")' onmouseout='groupUnHl( " + sugg.target_gid + ")'>new relation</span> <tt>public_transport=stop_area</tt>.";
  148. } else if (sugg.type == 2) {
  149. suggDiv.innerHTML = "Move into relation <a onmouseover='groupHl( " + sugg.target_gid + ")' onmouseout='groupUnHl( " + sugg.target_gid + ")' href=\"https://www.openstreetmap.org/relation/" + sugg.target_osm_rel_id + "\" target=\"_blank\">" + sugg.target_osm_rel_id + "</a>.";
  150. } else if (sugg.type == 3) {
  151. suggDiv.innerHTML = "Move from relation <a onmouseover='groupHl( " + sugg.orig_gid + ")' onmouseout='groupUnHl( " + sugg.orig_gid + ")' href=\"https://www.openstreetmap.org/relation/" + sugg.orig_osm_rel_id + "\" target=\"_blank\">" + sugg.orig_osm_rel_id + "</a> into a <span class='grouplink' onmouseover='groupHl( " + sugg.target_gid + ")' onmouseout='groupUnHl( " + sugg.target_gid + ")'>new relation</span> <tt>public_transport=stop_area</tt>.";
  152. } else if (sugg.type == 4) {
  153. suggDiv.innerHTML = "Move from relation <a onmouseover='groupHl( " + sugg.orig_gid + ")' onmouseout='groupUnHl( " + sugg.orig_gid + ")' href=\"https://www.openstreetmap.org/relation/" + sugg.orig_osm_rel_id + "\" target=\"_blank\">" + sugg.orig_osm_rel_id + "</a> into relation <a onmouseover='groupHl( " + sugg.target_gid + ")' onmouseout='groupUnHl( " + sugg.target_gid + ")' href=\"https://www.openstreetmap.org/relation/" + sugg.target_osm_rel_id + "\" target=\"_blank\">" + sugg.target_osm_rel_id + "</a>.";
  154. } else if (sugg.type == 5) {
  155. suggDiv.innerHTML = "Move out of relation <a onmouseover='groupHl( " + sugg.orig_gid + ")' onmouseout='groupUnHl( " + sugg.orig_gid + ")' href=\"https://www.openstreetmap.org/relation/" + sugg.orig_osm_rel_id + "\" target=\"_blank\">" + sugg.orig_osm_rel_id + "</a>";
  156. } else if (sugg.type == 6) {
  157. suggDiv.innerHTML = "Fix attribute <tt>" + sugg.attr + "</tt>.";
  158. } else if (sugg.type == 7) {
  159. suggDiv.innerHTML = "Consider adding a <tt><a target='_blank' href='https://wiki.openstreetmap.org/wiki/Key:name'>name</a></tt> attribute.";
  160. } else if (sugg.type == 8) {
  161. suggDiv.innerHTML = "Attribute <tt>" + sugg.attr + "</tt> seems to be a track number. Use <tt>ref</tt> for this and set <tt>" + sugg.attr + "</tt> to the station name.";
  162. }
  163. suggList.appendChild(suggDiv);
  164. }
  165. L.popup({
  166. opacity: 0.8
  167. })
  168. .setLatLng(ll)
  169. .setContent(content)
  170. .openOn(map)
  171. .on('remove', function() {openSt = -1; nodeUnHl(stat.id);;});
  172. }
  173. function openStat(id) {
  174. window.xmlhttp = new XMLHttpRequest();
  175. window.xmlhttp.onreadystatechange = function() {
  176. if (this.readyState == 4 && this.status == 200 && this == window.xmlhttp) {
  177. var content = JSON.parse(this.responseText);
  178. renderStat(content);
  179. }
  180. };
  181. window.xmlhttp.open("GET", backend + "/stat?id=" + id, true);
  182. window.xmlhttp.send();
  183. }
  184. function renderGroup(grp, ll) {
  185. openGr = grp.id;
  186. var attrrows = {};
  187. groupHl(grp.id);
  188. var content = document.createElement('div');
  189. content.setAttribute("id", "nav");
  190. var newMembers = document.createElement('div');
  191. newMembers.setAttribute("id", "group-stations-new")
  192. newMembers.innerHTML = "<span class='newmemberstit'>New Members</span>";
  193. var oldMembers = document.createElement('div');
  194. oldMembers.setAttribute("id", "group-stations-old")
  195. oldMembers.innerHTML = "<span class='oldmemberstit'>Existing Members</span>";
  196. if (grp.osmid == 1) {
  197. content.innerHTML = "<span class='grouplink'>New relation</span> <tt>public_transport=stop_area</tt>";
  198. } else {
  199. content.innerHTML = "OSM relation <a target='_blank' href='https://www.openstreetmap.org/relation/" + grp.osmid + "'>" + grp.osmid + "</a>";
  200. if (grp.attrs.name) {
  201. content.innerHTML += " (<b>\"" + grp.attrs.name + "\"</b>)";
  202. }
  203. content.innerHTML += "<a class='editbut' target='_blank' href='https://www.openstreetmap.org/edit?relation=" + grp.osmid +"'>&#9998;</a>";
  204. }
  205. var attrTbl = document.createElement('table');
  206. attrTbl.setAttribute("id", "attr-tbl")
  207. content.appendChild(attrTbl);
  208. var tbody = document.createElement('tbody');
  209. attrTbl.appendChild(tbody);
  210. var suggD = document.createElement('div');
  211. suggD.setAttribute("id", "sugg")
  212. for (var key in grp.attrs) {
  213. var row = document.createElement('tr');
  214. var col1 = document.createElement('td');
  215. var col2 = document.createElement('td');
  216. col2.className = "err-wrap";
  217. tbody.appendChild(row);
  218. row.appendChild(col1);
  219. row.appendChild(col2);
  220. col1.innerHTML = "<a href=\"https://wiki.openstreetmap.org/wiki/Key:" + key + "\" target=\"_blank\"><tt>" + key + "</tt></a>";
  221. for (var i = 0; i < grp.attrs[key].length; i++) col2.innerHTML += "<span class='attrval'>" + grp.attrs[key][i] + "</span>" + "<br>";
  222. attrrows[key] = row;
  223. }
  224. for (var i = 0; i < grp.attrerrs.length; i++) {
  225. var err = grp.attrerrs[i];
  226. var row = attrrows[err.attr[0]];
  227. row.className = "err-" + Math.round(err.conf * 10);
  228. var info = document.createElement('div');
  229. if (err.other_grp) {
  230. // the mismatch was with a group name
  231. if (err.other_osmid != grp.osmid) {
  232. if (err.other_osmid > 1) {
  233. info.innerHTML = "Does not match <tt>" + err.other_attr[0] + "</tt> in relation <a onmouseover='groupHl( " + err.other_grp + ")' onmouseout='groupUnHl( " + err.other_grp + ")' target=\"_blank\" href=\"https://www.openstreetmap.org/relation/" + Math.abs(err.other_osmid) + "\">" + Math.abs(err.other_osmid) + "</a>";
  234. } else {
  235. info.innerHTML = "Does not match <tt>" + err.other_attr[0] + "</tt> in relation <span onmouseover='groupHl( " + err.other_grp + ")' onmouseout='groupUnHl( " + err.other_grp + ")'>" + Math.abs(err.other_osmid) + "</span>";
  236. }
  237. } else {
  238. info.innerHTML = "Does not match <tt>" + err.other_attr[0] + "</tt> = '" + err.other_attr[1] + "'";
  239. }
  240. } else {
  241. // the mismatch was with another station
  242. var ident = err.other_osmid < 0 ? "way" : "node";
  243. info.innerHTML = "Does not match <tt>" + err.other_attr[0] + "</tt> in " + ident + " <a onmouseover='nodeHl( " + err.other + ")' onmouseout='nodeUnHl( " + err.other + ")' target=\"_blank\" href=\"https://www.openstreetmap.org/"+ident+"/" + Math.abs(err.other_osmid) + "\">" + Math.abs(err.other_osmid) + "</a>";
  244. }
  245. info.className = 'attr-err-info';
  246. row.childNodes[1].appendChild(info);
  247. }
  248. content.appendChild(newMembers);
  249. if (grp.osmid != 1) content.appendChild(oldMembers);
  250. for (var key in grp.stations) {
  251. var stat = grp.stations[key];
  252. var row = document.createElement('div');
  253. var ident = stat.osmid < 0 ? "Way" : "Node";
  254. row.innerHTML = ident + " <a onmouseover='nodeHl( " + stat.id + ")' onmouseout='nodeUnHl( " + stat.id + ")' target='_blank' href='https://www.openstreetmap.org/" + ident.toLowerCase() + "/" + Math.abs(stat.osmid) + "'>" + Math.abs(stat.osmid) + "</a>";
  255. if (stat.attrs.name) {
  256. row.innerHTML += " (<b>\"" + stat.attrs.name + "\"</b>)";
  257. }
  258. row.style.backgroundColor = stat.e ? '#f58d8d' : stat.s ? '#b6b6e4' : '#c0f7c0';
  259. if (grp.osmid == 1 || stat.orig_group != grp.id) newMembers.appendChild(row);
  260. else {
  261. oldMembers.appendChild(row);
  262. if (stat.group != grp.id) {
  263. row.className = "del-stat";
  264. }
  265. }
  266. }
  267. var suggList = document.createElement('ul');
  268. if (grp.su.length) {
  269. var a = document.createElement('span');
  270. a.className = "sugtit";
  271. a.innerHTML = "Suggestions";
  272. suggD.appendChild(a);
  273. }
  274. suggD.appendChild(suggList);
  275. for (var i = 0; i < grp.su.length; i++) {
  276. var sugg = grp.su[i];
  277. var suggDiv = document.createElement('li');
  278. if (sugg.type == 6) {
  279. suggDiv.innerHTML = "Fix attribute <tt>" + sugg.attr + "</tt>.";
  280. } else if (sugg.type == 7) {
  281. suggDiv.innerHTML = "Consider adding a <tt><a target='_blank' href='https://wiki.openstreetmap.org/wiki/Key:name'>name</a></tt> attribute.";
  282. } else if (sugg.type == 8) {
  283. suggDiv.innerHTML = "Attribute <tt>" + sugg.attr + "</tt> seems to be a track number. Use <tt>ref</tt> for this and set <tt>" + sugg.attr + "</tt> to the station name.";
  284. }
  285. suggList.appendChild(suggDiv);
  286. }
  287. content.appendChild(suggD);
  288. L.popup({opacity: 0.8})
  289. .setLatLng(ll)
  290. .setContent(content)
  291. .openOn(map)
  292. .on('remove', function() {openGr = -1; groupUnHl(grp.id)});
  293. }
  294. function openGroup(id, ll) {
  295. window.xmlhttp = new XMLHttpRequest();
  296. window.xmlhttp.onreadystatechange = function() {
  297. if (this.readyState == 4 && this.status == 200 && this == window.xmlhttp) {
  298. var content = JSON.parse(this.responseText);
  299. renderGroup(content, ll);
  300. }
  301. };
  302. window.xmlhttp.open("GET", backend + "/group?id=" + id, true);
  303. window.xmlhttp.send();
  304. }
  305. function groupHl(id) {
  306. if (!document.groupIdx[id]) return;
  307. document.groupIdx[id].setStyle({
  308. 'weight': 6,
  309. 'color': "#eecc00"
  310. });
  311. }
  312. function groupUnHl(id) {
  313. if (!document.groupIdx[id]) return;
  314. document.groupIdx[id].setStyle({
  315. 'weight': 3,
  316. 'color': document.groupIdx[id].options["fillColor"]
  317. });
  318. }
  319. function nodeHl(id) {
  320. if (!document.nodeIdx[id]) return;
  321. if (map.getZoom() > 15) {
  322. document.nodeIdx[id].setStyle({
  323. 'weight': 5,
  324. 'color': "#eecc00"
  325. });
  326. } else {
  327. document.nodeIdx[id].setStyle({
  328. 'color': "#eecc00"
  329. });
  330. }
  331. }
  332. function nodeUnHl(id) {
  333. if (!document.nodeIdx[id]) return;
  334. if (map.getZoom() > 15) {
  335. document.nodeIdx[id].setStyle({
  336. 'weight': map.getZoom() > 17 ? 1.5 : 1,
  337. 'color': "black"
  338. });
  339. } else {
  340. document.nodeIdx[id].setStyle({
  341. 'color': document.nodeIdx[id].options["fillColor"]
  342. });
  343. }
  344. }
  345. var map = L.map('map', {
  346. renderer: L.canvas(),
  347. attributionControl: false,
  348. }).setView([47.9965, 7.8469], 13);
  349. map.addControl(L.control.attribution({
  350. position: 'bottomright',
  351. prefix: '&copy; <a href="http://ad.cs.uni-freiburg.de">University of Freiburg, Chair of Algorithms and Data Structures</a>'
  352. }));
  353. map.on('popupopen', function(e) {
  354. var px = map.project(e.target._popup._latlng);
  355. px.y -= e.target._popup._container.clientHeight/2;
  356. map.panTo(map.unproject(px),{animate: true});
  357. });
  358. L.tileLayer('http://{s}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png', {
  359. maxZoom: 20,
  360. attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
  361. opacity: 0.8
  362. }).addTo(map);
  363. var layer = L.featureGroup().addTo(map);
  364. var labelLayer = L.featureGroup().addTo(map);
  365. map.on("moveend", function() {
  366. render();
  367. });
  368. function render() {
  369. window.xmlhttp = new XMLHttpRequest();
  370. if (map.getZoom() < 11) {
  371. window.xmlhttp.onreadystatechange = function() {
  372. if (this.readyState == 4 && this.status == 200 && this == window.xmlhttp) {
  373. var content = JSON.parse(this.responseText);
  374. layer.clearLayers();
  375. labelLayer.clearLayers();
  376. var blur = 22 - map.getZoom();
  377. var rad = 25 - map.getZoom();
  378. layer.addLayer(L.heatLayer(content.ok, {
  379. max: 500,
  380. gradient: {
  381. 0: '#cbf7cb',
  382. 0.5: '#78f378',
  383. 1: '#29c329'
  384. },
  385. minOpacity: 0.65,
  386. blur: blur,
  387. radius: rad
  388. }));
  389. layer.addLayer(L.heatLayer(content.sugg, {
  390. max: 500,
  391. gradient: {
  392. 0: '#7f7fbd',
  393. 0.5: '#4444b3',
  394. 1: '#0606c1'
  395. },
  396. minOpacity: 0.65,
  397. blur: blur - 3,
  398. radius: Math.min(12, rad - 3)
  399. }));
  400. layer.addLayer(L.heatLayer(content.err, {
  401. max: 500,
  402. gradient: {
  403. 0: '#f39191',
  404. 0.5: '#ff5656',
  405. 1: '#ff0000'
  406. },
  407. minOpacity: 0.75,
  408. blur: blur - 3,
  409. radius: Math.min(10, rad - 3),
  410. maxZoom: 15
  411. }));
  412. }
  413. };
  414. window.xmlhttp.open("GET", backend + "/heatmap?z=" + map.getZoom() + "&bbox=" + [map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng].join(","), true);
  415. window.xmlhttp.send();
  416. } else {
  417. window.xmlhttp.onreadystatechange = function() {
  418. if (this.readyState == 4 && this.status == 200 && this == window.xmlhttp) {
  419. var content = JSON.parse(this.responseText);
  420. layer.clearLayers();
  421. labelLayer.clearLayers();
  422. document.groupIdx = {};
  423. document.nodeIdx = {};
  424. var stations = [];
  425. var labels = [];
  426. for (var i = 0; i < content.stats.length; i++) {
  427. stat = content.stats[i];
  428. var ndMarker = marker(stat, map.getZoom());
  429. stations.push(ndMarker);
  430. document.nodeIdx[stat.i] = ndMarker;
  431. }
  432. var groups = [];
  433. for (var i = 0; i < content.groups.length; i++) {
  434. group = content.groups[i];
  435. var groupPoly = poly(group, map.getZoom());
  436. groups.push(groupPoly);
  437. document.groupIdx[group.i] = groupPoly;
  438. }
  439. var suggs = [];
  440. for (var i = 0; i < content.su.length; i++) {
  441. sugg = content.su[i];
  442. var a = sugArr(sugg, map.getZoom());
  443. suggs.push(a);
  444. }
  445. if (map.getZoom() > 13) {
  446. layer.addLayer(L.featureGroup(groups).on('click', function(a) {
  447. openGroup(a.layer.options.id, a.layer.getBounds().getCenter());
  448. }));
  449. }
  450. layer.addLayer(L.featureGroup(stations).on('click', function(a) {
  451. openStat(a.layer.options.id);
  452. }));
  453. if (map.getZoom() > 15) {
  454. labelLayer.addLayer(L.featureGroup(labels));
  455. layer.addLayer(L.featureGroup(suggs).on('click', function(a) {
  456. openStat(a.layer.options.id);
  457. }));
  458. }
  459. groupHl(openGr);
  460. nodeHl(openSt);
  461. }
  462. };
  463. window.xmlhttp.open("GET", backend + "/map?z=" + map.getZoom() + "&bbox=" + [map.getBounds().getSouthWest().lat, map.getBounds().getSouthWest().lng, map.getBounds().getNorthEast().lat, map.getBounds().getNorthEast().lng].join(","), true);
  464. window.xmlhttp.send();
  465. }
  466. }
  467. function rowClick(row) {
  468. if (!isSearchOpen()) return;
  469. openGroup(row.gid, row.latlng);
  470. document.getElementById('searchinput').value = "";
  471. search();
  472. }
  473. function select(row) {
  474. if (!isSearchOpen()) return;
  475. if (window.selectedRes) window.selectedRes.className = "searchres";
  476. row.className = "searchres selected-res";
  477. window.selectedRes = row;
  478. }
  479. function unselect(row) {
  480. window.selectedRes = undefined;
  481. if (row) row.className = "searchres";
  482. }
  483. function isSearchOpen() {
  484. return document.getElementById("searchresults").className == "res-open";
  485. }
  486. function search(q) {
  487. var delay = 0;
  488. if (q == window.prevSearch) return;
  489. clearTimeout(window.delayTimer);
  490. window.prevSearch = q;
  491. if (!q) {
  492. unselect(window.selectedRes);
  493. var res = document.getElementById("searchresults");
  494. res.className = "";
  495. return;
  496. }
  497. window.delayTimer = setTimeout(function() {
  498. window.searchhttp = new XMLHttpRequest();
  499. window.searchhttp.open("GET", backend + "/search?q=" + q, true);
  500. window.searchhttp.send();
  501. window.searchhttp.onreadystatechange = function() {
  502. if (this.readyState == 4 && this.status == 200 && this == window.searchhttp) {
  503. var content = JSON.parse(this.responseText);
  504. var res = document.getElementById("searchresults");
  505. res.className = "res-open";
  506. res.innerHTML = "";
  507. for (var i = 0; i < content.length; i++) {
  508. stat = content[i];
  509. var row = document.createElement('span');
  510. row.className="searchres";
  511. row.innerHTML = stat.name;
  512. row.gid = stat.gid;
  513. row.latlng = stat.latlng;
  514. row.onmouseover = function(){select(this)};
  515. row.onclick = function(){rowClick(this)};
  516. if (stat.via && stat.via != stat.name) {
  517. var via = document.createElement('span');
  518. via.className="via";
  519. via.innerHTML = stat.via;
  520. row.appendChild(via);
  521. }
  522. res.appendChild(row);
  523. }
  524. }
  525. }
  526. }, delay);
  527. }
  528. function keypress(e) {
  529. if (e.keyCode == 40) {
  530. var sels = document.getElementsByClassName('selected-res')
  531. if (sels.length) {
  532. var selected = sels[0];
  533. if (selected.nextSibling) select(selected.nextSibling);
  534. } else {
  535. var res = document.getElementsByClassName('searchres')
  536. if (res.length) select(res[0]);
  537. }
  538. } else if (e.keyCode == 38) {
  539. var sels = document.getElementsByClassName('selected-res')
  540. if (sels.length) {
  541. var selected = sels[0];
  542. if (selected.previousSibling) select(selected.previousSibling);
  543. else unselect(selected);
  544. }
  545. }
  546. if (e.keyCode == 13) {
  547. var sels = document.getElementsByClassName('selected-res');
  548. if (sels.length) rowClick(sels[0]);
  549. }
  550. }
  551. document.getElementById('del').onclick = function() {
  552. document.getElementById('searchinput').value = "";
  553. search();
  554. }
  555. render();