Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /branches/destination-access/extras/find-fixme/web/www/fixme.openlayers2.js
Parent Directory
|
Revision Log
Revision 2008 -
(show annotations)
(download)
(as text)
Sun Sep 1 14:49:11 2019 UTC (5 years, 6 months ago) by amb
File MIME type: application/javascript
File size: 15678 byte(s)
Sun Sep 1 14:49:11 2019 UTC (5 years, 6 months ago) by amb
File MIME type: application/javascript
File size: 15678 byte(s)
Merge from trunk (renaming of openlayers to openlayers2).
1 | // |
2 | // Routino (extras) fixme web page Javascript |
3 | // |
4 | // Part of the Routino routing software. |
5 | // |
6 | // This file Copyright 2008-2014, 2019 Andrew M. Bishop |
7 | // |
8 | // This program is free software: you can redistribute it and/or modify |
9 | // it under the terms of the GNU Affero General Public License as published by |
10 | // the Free Software Foundation, either version 3 of the License, or |
11 | // (at your option) any later version. |
12 | // |
13 | // This program is distributed in the hope that it will be useful, |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | // GNU Affero General Public License for more details. |
17 | // |
18 | // You should have received a copy of the GNU Affero General Public License |
19 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | // |
21 | |
22 | |
23 | //////////////////////////////////////////////////////////////////////////////// |
24 | /////////////////////////////// Initialisation ///////////////////////////////// |
25 | //////////////////////////////////////////////////////////////////////////////// |
26 | |
27 | // Process the URL query string and extract the arguments |
28 | |
29 | var legal={"^lon" : "^[-0-9.]+$", |
30 | "^lat" : "^[-0-9.]+$", |
31 | "^zoom" : "^[0-9]+$"}; |
32 | |
33 | var args={}; |
34 | |
35 | if(location.search.length>1) |
36 | { |
37 | var query,queries; |
38 | |
39 | query=location.search.replace(/^\?/,""); |
40 | query=query.replace(/;/g,"&"); |
41 | queries=query.split("&"); |
42 | |
43 | for(var i=0;i<queries.length;i++) |
44 | { |
45 | queries[i].match(/^([^=]+)(=(.*))?$/); |
46 | |
47 | var k=RegExp.$1; |
48 | var v=decodeURIComponent(RegExp.$3); |
49 | |
50 | for(var l in legal) |
51 | { |
52 | if(k.match(RegExp(l)) && v.match(RegExp(legal[l]))) |
53 | args[k]=v; |
54 | } |
55 | } |
56 | } |
57 | |
58 | |
59 | //////////////////////////////////////////////////////////////////////////////// |
60 | ///////////////////////////////// Map handling ///////////////////////////////// |
61 | //////////////////////////////////////////////////////////////////////////////// |
62 | |
63 | var map; |
64 | var layerMap=[], layerHighlights, layerVectors, layerBoxes; |
65 | var epsg4326, epsg900913; |
66 | |
67 | var box; |
68 | var select; |
69 | |
70 | // |
71 | // Initialise the 'map' object |
72 | // |
73 | |
74 | function map_init() // called from fixme.html |
75 | { |
76 | // Create the map (Map URLs and limits are in mapprops.js) |
77 | |
78 | epsg4326=new OpenLayers.Projection("EPSG:4326"); |
79 | epsg900913=new OpenLayers.Projection("EPSG:900913"); |
80 | |
81 | map = new OpenLayers.Map ("map", |
82 | { |
83 | controls:[ |
84 | new OpenLayers.Control.Navigation(), |
85 | new OpenLayers.Control.PanZoomBar(), |
86 | new OpenLayers.Control.ScaleLine(), |
87 | new OpenLayers.Control.LayerSwitcher() |
88 | ], |
89 | |
90 | projection: epsg900913, |
91 | displayProjection: epsg4326, |
92 | |
93 | minZoomLevel: mapprops.zoomout, |
94 | numZoomLevels: mapprops.zoomin-mapprops.zoomout+1, |
95 | maxResolution: 156543.03390625 / Math.pow(2,mapprops.zoomout), |
96 | |
97 | restrictedExtent: new OpenLayers.Bounds(mapprops.westedge,mapprops.southedge,mapprops.eastedge,mapprops.northedge).transform(epsg4326,epsg900913) |
98 | }); |
99 | |
100 | // Get a URL for the tile (mostly copied from OpenLayers/Layer/XYZ.js). |
101 | |
102 | function limitedUrl(bounds) |
103 | { |
104 | var res = this.map.getResolution(); |
105 | |
106 | var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w)); |
107 | var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h)); |
108 | var z = this.map.getZoom() + this.map.minZoomLevel; |
109 | |
110 | var limit = Math.pow(2, z); |
111 | x = ((x % limit) + limit) % limit; |
112 | |
113 | var xyz = {"x": x, "y": y, "z": z}; |
114 | var url = this.url; |
115 | |
116 | if (OpenLayers.Util.isArray(url)) |
117 | { |
118 | var s = "" + xyz.x + xyz.y + xyz.z; |
119 | url = this.selectUrl(s, url); |
120 | } |
121 | |
122 | return OpenLayers.String.format(url, xyz); |
123 | } |
124 | |
125 | // Add map tile layers |
126 | |
127 | for(var l=0; l<mapprops.mapdata.length; l++) |
128 | { |
129 | var urls; |
130 | |
131 | if(OpenLayers.Util.isArray(mapprops.mapdata[l].tiles.subdomains)) |
132 | { |
133 | urls=[]; |
134 | |
135 | for(var s=0; s<mapprops.mapdata[l].tiles.subdomains.length; s++) |
136 | urls.push(mapprops.mapdata[l].tiles.url.replace(/\${s}/,mapprops.mapdata[l].tiles.subdomains[s])); |
137 | } |
138 | else |
139 | urls=mapprops.mapdata[l].tiles.url; |
140 | |
141 | layerMap[l] = new OpenLayers.Layer.TMS(mapprops.mapdata[l].label, |
142 | urls, |
143 | { |
144 | getURL: limitedUrl, |
145 | displayOutsideMaxExtent: true, |
146 | buffer: 1 |
147 | }); |
148 | map.addLayer(layerMap[l]); |
149 | } |
150 | |
151 | // Update the attribution if the layer changes |
152 | |
153 | function change_attribution_event(event) |
154 | { |
155 | for(var l=0; l<mapprops.mapdata.length; l++) |
156 | if(layerMap[l] == event.layer) |
157 | change_attribution(l); |
158 | } |
159 | |
160 | map.events.register("changelayer",layerMap,change_attribution_event); |
161 | |
162 | function change_attribution(l) |
163 | { |
164 | var data_url =mapprops.mapdata[l].attribution.data_url; |
165 | var data_text=mapprops.mapdata[l].attribution.data_text; |
166 | var tile_url =mapprops.mapdata[l].attribution.tile_url; |
167 | var tile_text=mapprops.mapdata[l].attribution.tile_text; |
168 | |
169 | document.getElementById("attribution_data").innerHTML="<a href=\"" + data_url + "\" target=\"data_attribution\">" + data_text + "</a>"; |
170 | document.getElementById("attribution_tile").innerHTML="<a href=\"" + tile_url + "\" target=\"tile_attribution\">" + tile_text + "</a>"; |
171 | } |
172 | |
173 | change_attribution(0); |
174 | |
175 | // Add two vectors layers (one for highlights that display behind the vectors) |
176 | |
177 | layerHighlights = new OpenLayers.Layer.Vector("Highlights",{displayInLayerSwitcher: false}); |
178 | map.addLayer(layerHighlights); |
179 | |
180 | layerVectors = new OpenLayers.Layer.Vector("Markers",{displayInLayerSwitcher: false}); |
181 | map.addLayer(layerVectors); |
182 | |
183 | // Handle feature selection and popup |
184 | |
185 | select = new OpenLayers.Control.SelectFeature(layerVectors, |
186 | {onSelect: selectFeature, onUnselect: unselectFeature}); |
187 | |
188 | map.addControl(select); |
189 | select.activate(); |
190 | |
191 | createPopup(); |
192 | |
193 | // Add a boxes layer |
194 | |
195 | layerBoxes = new OpenLayers.Layer.Boxes("Boundary",{displayInLayerSwitcher: false}); |
196 | map.addLayer(layerBoxes); |
197 | |
198 | box=null; |
199 | |
200 | // Move the map |
201 | |
202 | map.events.register("moveend", map, updateURLs); |
203 | |
204 | var lon =args["lon"]; |
205 | var lat =args["lat"]; |
206 | var zoom=args["zoom"]; |
207 | |
208 | if(lon !== undefined && lat !== undefined && zoom !== undefined) |
209 | { |
210 | if(lon<mapprops.westedge) lon=mapprops.westedge; |
211 | if(lon>mapprops.eastedge) lon=mapprops.eastedge; |
212 | |
213 | if(lat<mapprops.southedge) lat=mapprops.southedge; |
214 | if(lat>mapprops.northedge) lat=mapprops.northedge; |
215 | |
216 | if(zoom<mapprops.zoomout) zoom=mapprops.zoomout; |
217 | if(zoom>mapprops.zoomin) zoom=mapprops.zoomin; |
218 | |
219 | var lonlat = new OpenLayers.LonLat(lon,lat); |
220 | lonlat.transform(epsg4326,epsg900913); |
221 | |
222 | map.moveTo(lonlat,zoom-map.minZoomLevel); |
223 | } |
224 | else |
225 | { |
226 | map.setCenter(map.restrictedExtent.getCenterLonLat(), map.getZoomForExtent(map.restrictedExtent,true)); |
227 | map.maxResolution = map.getResolution(); |
228 | } |
229 | |
230 | // Unhide editing URL if variable set |
231 | |
232 | if(mapprops.editurl !== undefined && mapprops.editurl !== "") |
233 | { |
234 | var edit_url=document.getElementById("edit_url"); |
235 | |
236 | edit_url.style.display=""; |
237 | edit_url.href=mapprops.editurl; |
238 | } |
239 | |
240 | updateURLs(); |
241 | } |
242 | |
243 | |
244 | // |
245 | // Format a number in printf("%.5f") format. |
246 | // |
247 | |
248 | function format5f(number) |
249 | { |
250 | var newnumber=Math.floor(number*100000+0.5); |
251 | var delta=0; |
252 | |
253 | if(newnumber>=0 && newnumber<100000) delta= 100000; |
254 | if(newnumber<0 && newnumber>-100000) delta=-100000; |
255 | |
256 | var string=String(newnumber+delta); |
257 | |
258 | var intpart =string.substring(0,string.length-5); |
259 | var fracpart=string.substring(string.length-5,string.length); |
260 | |
261 | if(delta>0) intpart="0"; |
262 | if(delta<0) intpart="-0"; |
263 | |
264 | return(intpart + "." + fracpart); |
265 | } |
266 | |
267 | |
268 | // |
269 | // Build a set of URL arguments for the map location |
270 | // |
271 | |
272 | function buildMapArguments() |
273 | { |
274 | var lonlat = map.getCenter().clone(); |
275 | lonlat.transform(epsg900913,epsg4326); |
276 | |
277 | var zoom = map.getZoom() + map.minZoomLevel; |
278 | |
279 | return "lat=" + format5f(lonlat.lat) + ";lon=" + format5f(lonlat.lon) + ";zoom=" + zoom; |
280 | } |
281 | |
282 | |
283 | // |
284 | // Update the URLs |
285 | // |
286 | |
287 | function updateURLs() |
288 | { |
289 | var mapargs=buildMapArguments(); |
290 | |
291 | var links=document.getElementsByTagName("a"); |
292 | |
293 | for(var i=0; i<links.length; i++) |
294 | { |
295 | var element=links[i]; |
296 | |
297 | if(element.id == "permalink_url") |
298 | element.href=location.pathname + "?" + mapargs; |
299 | |
300 | if(element.id == "edit_url") |
301 | element.href=mapprops.editurl + "?" + mapargs; |
302 | } |
303 | } |
304 | |
305 | |
306 | //////////////////////////////////////////////////////////////////////////////// |
307 | ///////////////////////// Popup and selection handling ///////////////////////// |
308 | //////////////////////////////////////////////////////////////////////////////// |
309 | |
310 | var popup=null; |
311 | |
312 | // |
313 | // Create a popup - independent of map because want it fixed on screen not fixed on map. |
314 | // |
315 | |
316 | function createPopup() |
317 | { |
318 | popup=document.createElement("div"); |
319 | |
320 | popup.className = "popup"; |
321 | |
322 | popup.innerHTML = "<span></span>"; |
323 | |
324 | popup.style.display = "none"; |
325 | |
326 | popup.style.position = "fixed"; |
327 | popup.style.top = "-4000px"; |
328 | popup.style.left = "-4000px"; |
329 | popup.style.zIndex = "100"; |
330 | |
331 | popup.style.padding = "5px"; |
332 | |
333 | popup.style.opacity=0.85; |
334 | popup.style.backgroundColor="#C0C0C0"; |
335 | popup.style.border="4px solid #404040"; |
336 | |
337 | document.body.appendChild(popup); |
338 | } |
339 | |
340 | |
341 | // |
342 | // Draw a popup - independent of map because want it fixed on screen not fixed on map. |
343 | // |
344 | |
345 | function drawPopup(html) |
346 | { |
347 | if(html===null) |
348 | { |
349 | popup.style.display="none"; |
350 | return; |
351 | } |
352 | |
353 | if(popup.style.display=="none") |
354 | { |
355 | var map_div=document.getElementById("map"); |
356 | |
357 | popup.style.left =map_div.offsetParent.offsetLeft+map_div.offsetLeft+60 + "px"; |
358 | popup.style.top = map_div.offsetTop +30 + "px"; |
359 | popup.style.width =map_div.clientWidth-120 + "px"; |
360 | |
361 | popup.style.display=""; |
362 | } |
363 | |
364 | var close="<span style='float: right; cursor: pointer;' onclick='drawPopup(null)'>X</span>"; |
365 | |
366 | popup.innerHTML=close+html; |
367 | } |
368 | |
369 | |
370 | // |
371 | // Select a feature |
372 | // |
373 | |
374 | function selectFeature(feature) |
375 | { |
376 | if(feature.attributes.dump) |
377 | ajaxGET("fixme.cgi?dump=" + feature.attributes.dump, runDumpSuccess); |
378 | |
379 | layerHighlights.destroyFeatures(); |
380 | |
381 | var highlight_style = new OpenLayers.Style({},{strokeColor: "#F0F000",strokeWidth: 8, |
382 | fillColor: "#F0F000",pointRadius: 4}); |
383 | |
384 | var highlight = new OpenLayers.Feature.Vector(feature.geometry.clone(),{},highlight_style); |
385 | |
386 | layerHighlights.addFeatures([highlight]); |
387 | } |
388 | |
389 | |
390 | // |
391 | // Un-select a feature |
392 | // |
393 | |
394 | function unselectFeature(feature) |
395 | { |
396 | layerHighlights.destroyFeatures(); |
397 | |
398 | drawPopup(null); |
399 | } |
400 | |
401 | |
402 | // |
403 | // Display the dump data |
404 | // |
405 | |
406 | function runDumpSuccess(response) |
407 | { |
408 | var string=response.responseText; |
409 | |
410 | if(mapprops.editurl !== undefined && mapprops.editurl !== "") |
411 | { |
412 | var types=["node", "way", "relation"]; |
413 | |
414 | for(var t in types) |
415 | { |
416 | var type=types[t]; |
417 | |
418 | var regexp=RegExp(type + " id='([0-9]+)'"); |
419 | |
420 | var match=string.match(regexp); |
421 | |
422 | if(match !== null) |
423 | { |
424 | var id=match[1]; |
425 | |
426 | string=string.replace(regexp,type + " id='<a href='" + mapprops.browseurl + "/" + type + "/" + id + "' target='" + type + id + "'>" + id + "</a>'"); |
427 | } |
428 | } |
429 | } |
430 | |
431 | drawPopup(string.split("><").join("><br><").split("<br><tag").join("<br> <tag")); |
432 | } |
433 | |
434 | |
435 | //////////////////////////////////////////////////////////////////////////////// |
436 | /////////////////////////////// Server handling //////////////////////////////// |
437 | //////////////////////////////////////////////////////////////////////////////// |
438 | |
439 | // |
440 | // Define an AJAX request object |
441 | // |
442 | |
443 | function ajaxGET(url,success,failure,state) |
444 | { |
445 | var ajaxRequest=new XMLHttpRequest(); |
446 | |
447 | function ajaxGOT(options) { |
448 | if(this.readyState==4) |
449 | if(this.status==200) |
450 | { if(typeof(options.success)=="function") options.success(this,options.state); } |
451 | else |
452 | { if(typeof(options.failure)=="function") options.failure(this,options.state); } |
453 | } |
454 | |
455 | ajaxRequest.onreadystatechange = function(){ ajaxGOT.call(ajaxRequest,{success: success, failure: failure, state: state}); }; |
456 | ajaxRequest.open("GET", url, true); |
457 | ajaxRequest.send(null); |
458 | } |
459 | |
460 | |
461 | // |
462 | // Display the status |
463 | // |
464 | |
465 | function displayStatus(type,subtype,content) |
466 | { |
467 | var child=document.getElementById("result_status").firstChild; |
468 | |
469 | do |
470 | { |
471 | if(child.id !== undefined) |
472 | child.style.display="none"; |
473 | |
474 | child=child.nextSibling; |
475 | } |
476 | while(child !== null); |
477 | |
478 | var chosen_status=document.getElementById("result_status_" + type); |
479 | |
480 | chosen_status.style.display=""; |
481 | |
482 | if(subtype !== undefined) |
483 | { |
484 | var format_status=document.getElementById("result_status_" + subtype).innerHTML; |
485 | |
486 | chosen_status.innerHTML=format_status.replace("#",String(content)); |
487 | } |
488 | } |
489 | |
490 | |
491 | // |
492 | // Display data statistics |
493 | // |
494 | |
495 | function displayStatistics() |
496 | { |
497 | // Use AJAX to get the statistics |
498 | |
499 | ajaxGET("fixme.cgi?statistics=yes", runStatisticsSuccess); |
500 | } |
501 | |
502 | |
503 | // |
504 | // Success in running data statistics generation. |
505 | // |
506 | |
507 | function runStatisticsSuccess(response) |
508 | { |
509 | document.getElementById("statistics_data").innerHTML="<pre>" + response.responseText + "</pre>"; |
510 | document.getElementById("statistics_link").style.display="none"; |
511 | } |
512 | |
513 | |
514 | // |
515 | // Get the requested data |
516 | // |
517 | |
518 | function displayData(datatype) // called from fixme.html |
519 | { |
520 | // Delete the old data |
521 | |
522 | unselectFeature(); |
523 | |
524 | select.deactivate(); |
525 | |
526 | layerVectors.destroyFeatures(); |
527 | layerHighlights.destroyFeatures(); |
528 | |
529 | if(box !== null) |
530 | layerBoxes.removeMarker(box); |
531 | box=null; |
532 | |
533 | // Print the status |
534 | |
535 | displayStatus("no_data"); |
536 | |
537 | // Return if just here to clear the data |
538 | |
539 | if(datatype === "") |
540 | return; |
541 | |
542 | // Get the new data |
543 | |
544 | var mapbounds=map.getExtent().clone(); |
545 | mapbounds.transform(epsg900913,epsg4326); |
546 | |
547 | var url="fixme.cgi"; |
548 | |
549 | url=url + "?lonmin=" + format5f(mapbounds.left); |
550 | url=url + ";latmin=" + format5f(mapbounds.bottom); |
551 | url=url + ";lonmax=" + format5f(mapbounds.right); |
552 | url=url + ";latmax=" + format5f(mapbounds.top); |
553 | url=url + ";data=" + datatype; |
554 | |
555 | // Use AJAX to get the data |
556 | |
557 | ajaxGET(url, runFixmeSuccess, runFailure); |
558 | } |
559 | |
560 | |
561 | // |
562 | // Success in getting the error log data |
563 | // |
564 | |
565 | function runFixmeSuccess(response) |
566 | { |
567 | var lines=response.responseText.split("\n"); |
568 | |
569 | var style = new OpenLayers.Style({},{stroke: false, |
570 | pointRadius: 3,fillColor: "#FF0000", |
571 | cursor: "pointer"}); |
572 | |
573 | var features=[]; |
574 | |
575 | for(var line=0;line<lines.length;line++) |
576 | { |
577 | var words=lines[line].split(" "); |
578 | |
579 | if(line === 0) |
580 | { |
581 | var lat1=words[0]; |
582 | var lon1=words[1]; |
583 | var lat2=words[2]; |
584 | var lon2=words[3]; |
585 | |
586 | var bounds = new OpenLayers.Bounds(lon1,lat1,lon2,lat2).transform(epsg4326,epsg900913); |
587 | |
588 | box = new OpenLayers.Marker.Box(bounds); |
589 | |
590 | layerBoxes.addMarker(box); |
591 | } |
592 | else if(words[0] !== "") |
593 | { |
594 | var dump=words[0]; |
595 | var lat=words[1]; |
596 | var lon=words[2]; |
597 | |
598 | var lonlat = new OpenLayers.LonLat(lon,lat).transform(epsg4326,epsg900913); |
599 | |
600 | var point = new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat); |
601 | |
602 | features.push(new OpenLayers.Feature.Vector(point,{dump: dump},style)); |
603 | } |
604 | } |
605 | |
606 | select.activate(); |
607 | |
608 | layerVectors.addFeatures(features); |
609 | |
610 | displayStatus("data","fixme",lines.length-2); |
611 | } |
612 | |
613 | |
614 | // |
615 | // Failure in getting data. |
616 | // |
617 | |
618 | function runFailure(response) |
619 | { |
620 | displayStatus("failed"); |
621 | } |