Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/extras/find-fixme/web/www/fixme.openlayers.js
Parent Directory
|
Revision Log
Revision 1377 -
(hide annotations)
(download)
(as text)
Mon Jun 3 19:08:51 2013 UTC (11 years, 9 months ago) by amb
Original Path: trunk/extras/find-fixme/web/www/fixme.js
File MIME type: application/javascript
File size: 13754 byte(s)
Mon Jun 3 19:08:51 2013 UTC (11 years, 9 months ago) by amb
Original Path: trunk/extras/find-fixme/web/www/fixme.js
File MIME type: application/javascript
File size: 13754 byte(s)
Nicely format the item tag information.
1 | amb | 1367 | // |
2 | // Routino (extras) fixme web page Javascript | ||
3 | // | ||
4 | // Part of the Routino routing software. | ||
5 | // | ||
6 | // This file Copyright 2008-2013 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 | k=RegExp.$1; | ||
48 | v=unescape(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 | lon =args["lon"]; | ||
77 | lat =args["lat"]; | ||
78 | zoom=args["zoom"]; | ||
79 | |||
80 | // Map URLs and limits are in mapprops.js. | ||
81 | |||
82 | // | ||
83 | // Create the map | ||
84 | // | ||
85 | |||
86 | epsg4326=new OpenLayers.Projection("EPSG:4326"); | ||
87 | epsg900913=new OpenLayers.Projection("EPSG:900913"); | ||
88 | |||
89 | map = new OpenLayers.Map ("map", | ||
90 | { | ||
91 | controls:[ | ||
92 | new OpenLayers.Control.Navigation(), | ||
93 | new OpenLayers.Control.PanZoomBar(), | ||
94 | new OpenLayers.Control.ScaleLine(), | ||
95 | new OpenLayers.Control.LayerSwitcher() | ||
96 | ], | ||
97 | |||
98 | projection: epsg900913, | ||
99 | displayProjection: epsg4326, | ||
100 | |||
101 | minZoomLevel: mapprops.zoomout, | ||
102 | numZoomLevels: mapprops.zoomin-mapprops.zoomout+1, | ||
103 | maxResolution: 156543.03390625 / Math.pow(2,mapprops.zoomout), | ||
104 | |||
105 | // These two lines are not needed with OpenLayers 2.12 | ||
106 | units: "m", | ||
107 | maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34), | ||
108 | |||
109 | restrictedExtent: new OpenLayers.Bounds(mapprops.westedge,mapprops.southedge,mapprops.eastedge,mapprops.northedge).transform(epsg4326,epsg900913) | ||
110 | }); | ||
111 | |||
112 | // Add map tile layers | ||
113 | |||
114 | for(var l=0;l < mapprops.mapdata.length;l++) | ||
115 | { | ||
116 | layerMap[l] = new OpenLayers.Layer.TMS(mapprops.mapdata[l].label, | ||
117 | mapprops.mapdata[l].tileurl, | ||
118 | { | ||
119 | getURL: limitedUrl, | ||
120 | displayOutsideMaxExtent: true, | ||
121 | buffer: 1 | ||
122 | }); | ||
123 | map.addLayer(layerMap[l]); | ||
124 | } | ||
125 | |||
126 | // Update the attribution if the layer changes | ||
127 | |||
128 | map.events.register("changelayer",layerMap,change_attribution_event); | ||
129 | |||
130 | function change_attribution_event(event) | ||
131 | { | ||
132 | for(var l=0;l < mapprops.mapdata.length;l++) | ||
133 | if(this[l] == event.layer) | ||
134 | change_attribution(l); | ||
135 | } | ||
136 | |||
137 | function change_attribution(l) | ||
138 | { | ||
139 | var data_url =mapprops.mapdata[l].attribution.data_url; | ||
140 | var data_text=mapprops.mapdata[l].attribution.data_text; | ||
141 | var tile_url =mapprops.mapdata[l].attribution.tile_url; | ||
142 | var tile_text=mapprops.mapdata[l].attribution.tile_text; | ||
143 | |||
144 | document.getElementById("attribution_data").innerHTML="<a href=\"" + data_url + "\" target=\"data_attribution\">" + data_text + "</a>"; | ||
145 | document.getElementById("attribution_tile").innerHTML="<a href=\"" + tile_url + "\" target=\"tile_attribution\">" + tile_text + "</a>"; | ||
146 | } | ||
147 | |||
148 | change_attribution(0); | ||
149 | |||
150 | // Get a URL for the tile (mostly copied from OpenLayers/Layer/XYZ.js). | ||
151 | |||
152 | function limitedUrl(bounds) | ||
153 | { | ||
154 | var res = map.getResolution(); | ||
155 | |||
156 | var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w)); | ||
157 | var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h)); | ||
158 | var z = map.getZoom() + map.minZoomLevel; | ||
159 | |||
160 | var limit = Math.pow(2, z); | ||
161 | x = ((x % limit) + limit) % limit; | ||
162 | |||
163 | var xyz = {'x': x, 'y': y, 'z': z}; | ||
164 | var url = this.url; | ||
165 | |||
166 | if (OpenLayers.Util.isArray(url)) | ||
167 | { | ||
168 | var s = '' + xyz.x + xyz.y + xyz.z; | ||
169 | url = this.selectUrl(s, url); | ||
170 | } | ||
171 | |||
172 | return OpenLayers.String.format(url, xyz); | ||
173 | } | ||
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 | // Set the map centre to the limited range specified | ||
201 | |||
202 | map.setCenter(map.restrictedExtent.getCenterLonLat(), map.getZoomForExtent(map.restrictedExtent,true)); | ||
203 | map.maxResolution = map.getResolution(); | ||
204 | |||
205 | // Move the map | ||
206 | |||
207 | if(lon != undefined && lat != undefined && zoom != undefined) | ||
208 | { | ||
209 | if(lon<mapprops.westedge) lon=mapprops.westedge; | ||
210 | if(lon>mapprops.eastedge) lon=mapprops.eastedge; | ||
211 | |||
212 | if(lat<mapprops.southedge) lat=mapprops.southedge; | ||
213 | if(lat>mapprops.northedge) lat=mapprops.northedge; | ||
214 | |||
215 | if(zoom<mapprops.zoomout) zoom=mapprops.zoomout; | ||
216 | if(zoom>mapprops.zoomin) zoom=mapprops.zoomin; | ||
217 | |||
218 | var lonlat = new OpenLayers.LonLat(lon,lat); | ||
219 | lonlat.transform(epsg4326,epsg900913); | ||
220 | |||
221 | map.moveTo(lonlat,zoom-map.minZoomLevel); | ||
222 | } | ||
223 | |||
224 | // Unhide editing URL if variable set | ||
225 | |||
226 | if(mapprops.editurl != undefined && mapprops.editurl != "") | ||
227 | { | ||
228 | edit_url=document.getElementById("edit_url"); | ||
229 | |||
230 | edit_url.style.display=""; | ||
231 | edit_url.href=mapprops.editurl; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | |||
236 | // | ||
237 | // Format a number in printf("%.5f") format. | ||
238 | // | ||
239 | |||
240 | function format5f(number) | ||
241 | { | ||
242 | var newnumber=Math.floor(number*100000+0.5); | ||
243 | var delta=0; | ||
244 | |||
245 | if(newnumber>=0 && newnumber<100000) delta= 100000; | ||
246 | if(newnumber<0 && newnumber>-100000) delta=-100000; | ||
247 | |||
248 | var string=String(newnumber+delta); | ||
249 | |||
250 | var intpart =string.substring(0,string.length-5); | ||
251 | var fracpart=string.substring(string.length-5,string.length); | ||
252 | |||
253 | if(delta>0) intpart="0"; | ||
254 | if(delta<0) intpart="-0"; | ||
255 | |||
256 | return(intpart + "." + fracpart); | ||
257 | } | ||
258 | |||
259 | |||
260 | // | ||
261 | // Build a set of URL arguments for the map location | ||
262 | // | ||
263 | |||
264 | function buildMapArguments() | ||
265 | { | ||
266 | var lonlat = map.getCenter().clone(); | ||
267 | lonlat.transform(epsg900913,epsg4326); | ||
268 | |||
269 | var zoom = map.getZoom() + map.minZoomLevel; | ||
270 | |||
271 | return "lat=" + format5f(lonlat.lat) + ";lon=" + format5f(lonlat.lon) + ";zoom=" + zoom; | ||
272 | } | ||
273 | |||
274 | |||
275 | // | ||
276 | // Update a URL | ||
277 | // | ||
278 | |||
279 | function updateURL(element) // called from fixme.html | ||
280 | { | ||
281 | if(element.id == "permalink_url") | ||
282 | element.href=location.pathname + "?" + buildMapArguments(); | ||
283 | |||
284 | if(element.id == "edit_url") | ||
285 | element.href=mapprops.editurl + "?" + buildMapArguments(); | ||
286 | } | ||
287 | |||
288 | |||
289 | //////////////////////////////////////////////////////////////////////////////// | ||
290 | ///////////////////////// Popup and selection handling ///////////////////////// | ||
291 | //////////////////////////////////////////////////////////////////////////////// | ||
292 | |||
293 | var popup=null; | ||
294 | |||
295 | // | ||
296 | // Create a popup - not using OpenLayers because want it fixed on screen not fixed on map. | ||
297 | // | ||
298 | |||
299 | function createPopup() | ||
300 | { | ||
301 | popup=document.createElement('div'); | ||
302 | |||
303 | popup.className = "popup"; | ||
304 | |||
305 | popup.innerHTML = "<span></span>"; | ||
306 | |||
307 | popup.style.display = "none"; | ||
308 | |||
309 | popup.style.position = "fixed"; | ||
310 | popup.style.top = "-4000px"; | ||
311 | popup.style.left = "-4000px"; | ||
312 | popup.style.zIndex = "100"; | ||
313 | |||
314 | popup.style.padding = "5px"; | ||
315 | |||
316 | popup.style.opacity=0.85; | ||
317 | popup.style.backgroundColor="#C0C0C0"; | ||
318 | popup.style.border="4px solid #404040"; | ||
319 | |||
320 | document.body.appendChild(popup); | ||
321 | } | ||
322 | |||
323 | |||
324 | // | ||
325 | // Draw a popup - not using OpenLayers because want it fixed on screen not fixed on map. | ||
326 | // | ||
327 | |||
328 | function drawPopup(html) | ||
329 | { | ||
330 | if(html==null) | ||
331 | { | ||
332 | popup.style.display="none"; | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | if(popup.style.display=="none") | ||
337 | { | ||
338 | var map_div=document.getElementById("map"); | ||
339 | |||
340 | popup.style.left =map_div.offsetParent.offsetLeft+map_div.offsetLeft+60 + "px"; | ||
341 | popup.style.top = map_div.offsetTop +30 + "px"; | ||
342 | popup.style.width =map_div.clientWidth-100 + "px"; | ||
343 | |||
344 | popup.style.display=""; | ||
345 | } | ||
346 | |||
347 | popup.innerHTML=html; | ||
348 | } | ||
349 | |||
350 | |||
351 | // | ||
352 | // Select a feature | ||
353 | // | ||
354 | |||
355 | function selectFeature(feature) | ||
356 | { | ||
357 | if(feature.attributes.dump) | ||
358 | OpenLayers.Request.GET({url: "fixme.cgi?dump=" + feature.attributes.dump, success: runDumpSuccess}); | ||
359 | |||
360 | layerHighlights.destroyFeatures(); | ||
361 | |||
362 | highlight_style = new OpenLayers.Style({},{strokeColor: "#F0F000",strokeWidth: 8, | ||
363 | fillColor: "#F0F000",pointRadius: 6}); | ||
364 | |||
365 | highlight = new OpenLayers.Feature.Vector(feature.geometry.clone(),{},highlight_style); | ||
366 | |||
367 | layerHighlights.addFeatures([highlight]); | ||
368 | } | ||
369 | |||
370 | |||
371 | // | ||
372 | // Un-select a feature | ||
373 | // | ||
374 | |||
375 | function unselectFeature(feature) | ||
376 | { | ||
377 | layerHighlights.destroyFeatures(); | ||
378 | |||
379 | drawPopup(null); | ||
380 | } | ||
381 | |||
382 | |||
383 | // | ||
384 | // Display the dump data | ||
385 | // | ||
386 | |||
387 | function runDumpSuccess(response) | ||
388 | { | ||
389 | amb | 1377 | drawPopup(response.responseText.split("><").join("><br><").split("<br><tag").join("<br> <tag")); |
390 | amb | 1367 | } |
391 | |||
392 | |||
393 | //////////////////////////////////////////////////////////////////////////////// | ||
394 | /////////////////////////////// Server handling //////////////////////////////// | ||
395 | //////////////////////////////////////////////////////////////////////////////// | ||
396 | |||
397 | // | ||
398 | // Display the status | ||
399 | // | ||
400 | |||
401 | function displayStatus(type,subtype,content) | ||
402 | { | ||
403 | var child=document.getElementById("result_status").firstChild; | ||
404 | |||
405 | do | ||
406 | { | ||
407 | if(child.id != undefined) | ||
408 | child.style.display="none"; | ||
409 | |||
410 | child=child.nextSibling; | ||
411 | } | ||
412 | while(child != undefined); | ||
413 | |||
414 | var chosen_status=document.getElementById("result_status_" + type); | ||
415 | |||
416 | chosen_status.style.display=""; | ||
417 | |||
418 | if(subtype != null) | ||
419 | { | ||
420 | var format_status=document.getElementById("result_status_" + subtype).innerHTML; | ||
421 | |||
422 | chosen_status.innerHTML=format_status.replace('#',String(content)); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | |||
427 | // | ||
428 | // Get the requested data | ||
429 | // | ||
430 | |||
431 | function displayData(datatype) // called from fixme.html | ||
432 | { | ||
433 | // Delete the old data | ||
434 | |||
435 | unselectFeature(); | ||
436 | |||
437 | select.deactivate(); | ||
438 | |||
439 | layerVectors.destroyFeatures(); | ||
440 | layerHighlights.destroyFeatures(); | ||
441 | |||
442 | if(box != null) | ||
443 | layerBoxes.removeMarker(box); | ||
444 | box=null; | ||
445 | |||
446 | // Print the status | ||
447 | |||
448 | displayStatus("no_data"); | ||
449 | |||
450 | // Return if just here to clear the data | ||
451 | |||
452 | if(datatype == "") | ||
453 | return; | ||
454 | |||
455 | // Get the new data | ||
456 | |||
457 | var mapbounds=map.getExtent().clone(); | ||
458 | mapbounds.transform(epsg900913,epsg4326); | ||
459 | |||
460 | var url="fixme.cgi"; | ||
461 | |||
462 | url=url + "?lonmin=" + mapbounds.left; | ||
463 | url=url + ";latmin=" + mapbounds.bottom; | ||
464 | url=url + ";lonmax=" + mapbounds.right; | ||
465 | url=url + ";latmax=" + mapbounds.top; | ||
466 | url=url + ";data=" + datatype; | ||
467 | |||
468 | // Use AJAX to get the data | ||
469 | |||
470 | OpenLayers.Request.GET({url: url, success: runFixmeSuccess, falure: runFailure}); | ||
471 | } | ||
472 | |||
473 | |||
474 | // | ||
475 | // Success in getting the error log data | ||
476 | // | ||
477 | |||
478 | function runFixmeSuccess(response) | ||
479 | { | ||
480 | var lines=response.responseText.split('\n'); | ||
481 | |||
482 | var style = new OpenLayers.Style({},{stroke: false, | ||
483 | pointRadius: 3,fillColor: "#FF0000", | ||
484 | cursor: "pointer"}); | ||
485 | |||
486 | var features=[]; | ||
487 | |||
488 | for(var line=0;line<lines.length;line++) | ||
489 | { | ||
490 | var words=lines[line].split(' '); | ||
491 | |||
492 | if(line == 0) | ||
493 | { | ||
494 | var lat1=words[0]; | ||
495 | var lon1=words[1]; | ||
496 | var lat2=words[2]; | ||
497 | var lon2=words[3]; | ||
498 | |||
499 | var bounds = new OpenLayers.Bounds(lon1,lat1,lon2,lat2).transform(epsg4326,epsg900913); | ||
500 | |||
501 | box = new OpenLayers.Marker.Box(bounds); | ||
502 | |||
503 | layerBoxes.addMarker(box); | ||
504 | } | ||
505 | else if(words[0] != "") | ||
506 | { | ||
507 | var dump=words[0]; | ||
508 | var lat=words[1]; | ||
509 | var lon=words[2]; | ||
510 | |||
511 | var lonlat = new OpenLayers.LonLat(lon,lat).transform(epsg4326,epsg900913); | ||
512 | |||
513 | var point = new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat); | ||
514 | |||
515 | features.push(new OpenLayers.Feature.Vector(point,{dump: dump},style)); | ||
516 | } | ||
517 | } | ||
518 | |||
519 | select.activate(); | ||
520 | |||
521 | layerVectors.addFeatures(features); | ||
522 | |||
523 | displayStatus("data","fixme",lines.length-2); | ||
524 | } | ||
525 | |||
526 | |||
527 | // | ||
528 | // Failure in getting data. | ||
529 | // | ||
530 | |||
531 | function runFailure(response) | ||
532 | { | ||
533 | displayStatus("failed"); | ||
534 | } |