Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/web/www/routino/router.openlayers.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1948 - (show annotations) (download) (as text)
Fri Jun 15 18:14:43 2018 UTC (6 years, 9 months ago) by amb
File MIME type: application/javascript
File size: 56515 byte(s)
Enable the search buttons if two markers are placed by searching for a
named location.

1 //
2 // Routino router web page Javascript
3 //
4 // Part of the Routino routing software.
5 //
6 // This file Copyright 2008-2018 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 var vismarkers, markers, markersmoved, paramschanged;
24 var homelat=null, homelon=null;
25
26
27 ////////////////////////////////////////////////////////////////////////////////
28 /////////////////////////////// Initialisation /////////////////////////////////
29 ////////////////////////////////////////////////////////////////////////////////
30
31 // Make a deep copy of the routino profile.
32
33 var routino_default={};
34 for(var l1 in routino)
35 if(typeof(routino[l1])!="object")
36 routino_default[l1]=routino[l1];
37 else
38 {
39 routino_default[l1]={};
40 for(var l2 in routino[l1])
41 if(typeof(routino[l1][l2])!="object")
42 routino_default[l1][l2]=Number(routino[l1][l2]);
43 else
44 {
45 routino_default[l1][l2]={};
46 for(var l3 in routino[l1][l2])
47 routino_default[l1][l2][l3]=Number(routino[l1][l2][l3]);
48 }
49 }
50
51 // Store the latitude and longitude in the routino variable
52
53 routino.point=[];
54 for(var marker=1;marker<=mapprops.maxmarkers;marker++)
55 {
56 routino.point[marker]={};
57
58 routino.point[marker].lon="";
59 routino.point[marker].lat="";
60 routino.point[marker].search="";
61 routino.point[marker].active=false;
62 routino.point[marker].used=false;
63 routino.point[marker].home=false;
64 }
65
66 // Process the URL query string and extract the arguments
67
68 var legal={"^lon" : "^[-0-9.]+$",
69 "^lat" : "^[-0-9.]+$",
70 "^zoom" : "^[0-9]+$",
71
72 "^lon[1-9]" : "^[-0-9.]+$",
73 "^lat[1-9]" : "^[-0-9.]+$",
74 "^search[1-9]" : "^.+$",
75 "^transport" : "^[a-z]+$",
76 "^highway-[a-z]+" : "^[0-9.]+$",
77 "^speed-[a-z]+" : "^[0-9.]+$",
78 "^property-[a-z]+" : "^[0-9.]+$",
79 "^oneway" : "^(1|0|true|false|on|off)$",
80 "^turns" : "^(1|0|true|false|on|off)$",
81 "^weight" : "^[0-9.]+$",
82 "^height" : "^[0-9.]+$",
83 "^width" : "^[0-9.]+$",
84 "^length" : "^[0-9.]+$",
85
86 "^language" : "^[-a-zA-Z]+$",
87
88 "^reverse" : "(1|0|true|false|on|off)",
89 "^loop" : "(1|0|true|false|on|off)"};
90
91 var args={};
92
93 if(location.search.length>1)
94 {
95 var query,queries;
96
97 query=location.search.replace(/^\?/,"");
98 query=query.replace(/;/g,"&");
99 queries=query.split("&");
100
101 for(var i=0;i<queries.length;i++)
102 {
103 queries[i].match(/^([^=]+)(=(.*))?$/);
104
105 var k=RegExp.$1;
106 var v=decodeURIComponent(RegExp.$3);
107
108 for(var l in legal)
109 {
110 if(k.match(RegExp(l)) && v.match(RegExp(legal[l])))
111 args[k]=v;
112 }
113 }
114 }
115
116
117 //
118 // Fill in the HTML - add the missing waypoints
119 //
120
121 function html_init() // called from router.html
122 {
123 var waypoints=document.getElementById("waypoints");
124
125 var waypoint_html=waypoints.firstElementChild.outerHTML.split("XXX");
126
127 waypoints.removeChild(waypoints.firstElementChild);
128
129 for(var marker=1;marker<=mapprops.maxmarkers;marker++)
130 {
131 var waypoint=document.createElement('div');
132
133 waypoints.appendChild(waypoint);
134
135 waypoint.outerHTML=waypoint_html.join(marker);
136 }
137
138 waypoints.addEventListener('dragstart',dragWaypointStart,false);
139 waypoints.addEventListener('dragend' ,dragWaypointEnd ,false);
140 waypoints.addEventListener('dragenter',dragWaypointEnter,false);
141 waypoints.addEventListener('dragover' ,dragWaypointOver ,false);
142 waypoints.addEventListener('dragleave',dragWaypointLeave,false);
143 waypoints.addEventListener('drop' ,dragWaypointDrop ,false);
144
145
146 var map=document.getElementById("map");
147
148 map.addEventListener('dragenter',dragWaypointMapEnter,false);
149 map.addEventListener('dragover' ,dragWaypointMapOver ,false);
150 map.addEventListener('dragleave',dragWaypointMapLeave,false);
151 map.addEventListener('drop' ,dragWaypointMapDrop ,false);
152 }
153
154
155 ////////////////////////////////////////////////////////////////////////////////
156 //////////////////////////////// Form handling /////////////////////////////////
157 ////////////////////////////////////////////////////////////////////////////////
158
159 //
160 // Form initialisation - fill in the uninitialised parts
161 //
162
163 function form_init() // called from router.html
164 {
165 // Fill in the waypoints
166
167 vismarkers=0;
168
169 for(var marker=mapprops.maxmarkers;marker>=1;marker--)
170 {
171 var lon=args["lon" + marker];
172 var lat=args["lat" + marker];
173 var search=args["search" + marker];
174
175 if(lon !== undefined && lat !== undefined && search !== undefined && lon !== "" && lat !== "" && search !== "")
176 {
177 markerAddForm(marker);
178
179 formSetSearch(marker,search);
180 formSetCoords(marker,lon,lat);
181
182 markerAddMap(marker);
183
184 markerSearch(marker);
185
186 vismarkers++;
187 }
188 else if(lon !== undefined && lat !== undefined && lon !== "" && lat !== "")
189 {
190 markerAddForm(marker);
191
192 formSetCoords(marker,lon,lat);
193
194 markerAddMap(marker);
195
196 markerCoords(marker);
197
198 vismarkers++;
199 }
200 else if(search !== undefined && search !== "")
201 {
202 markerAddForm(marker);
203
204 formSetSearch(marker,search);
205
206 markerSearch(marker);
207
208 DoSearch(marker);
209
210 vismarkers++;
211 }
212 else if(vismarkers || marker<=2)
213 {
214 markerAddForm(marker);
215
216 vismarkers++;
217 }
218
219 var searchfield=document.forms["form"].elements["search" + marker];
220
221 if(searchfield.addEventListener)
222 searchfield.addEventListener("keyup", searchOnReturnKey, false);
223 else if(searchfield.attachEvent)
224 searchfield.attachEvent("keyup", searchOnReturnKey); // Internet Explorer
225 }
226
227 if(args["loop"] !== undefined)
228 formSetLoopReverse("loop",args["loop"]);
229 else
230 formSetLoopReverse("loop",false);
231
232 if(args["reverse"] !== undefined)
233 formSetLoopReverse("reverse",args["reverse"]);
234 else
235 formSetLoopReverse("reverse",false);
236
237 // Update the transport type with the URL settings which updates all HTML forms to defaults.
238
239 var transport=routino.transport;
240
241 if(args["transport"] !== undefined)
242 transport=args["transport"];
243
244 formSetTransport(transport);
245
246 // Update the HTML with the URL settings
247
248 if(args["language"] !== undefined)
249 formSetLanguage(args["language"]);
250 else
251 formSetLanguage();
252
253 for(var key in routino.profile_highway)
254 if(args["highway-" + key] !== undefined)
255 formSetHighway(key,args["highway-" + key]);
256
257 for(var key in routino.profile_speed)
258 if(args["speed-" + key] !== undefined)
259 formSetSpeed(key,args["speed-" + key]);
260
261 for(var key in routino.profile_property)
262 if(args["property-" + key] !== undefined)
263 formSetProperty(key,args["property-" + key]);
264
265 for(var key in routino.restrictions)
266 {
267 if(key=="oneway" || key=="turns")
268 {
269 if(args[key] !== undefined)
270 formSetRestriction(key,args[key]);
271 }
272 else
273 {
274 if(args["restrict-" + key] !== undefined)
275 formSetRestriction(key,args["restrict-" + key]);
276 }
277 }
278
279 // Get the home location cookie and compare to each waypoint
280
281 var cookies=document.cookie.split("; ");
282
283 for(var cookie=0;cookie<cookies.length;cookie++)
284 if(cookies[cookie].substr(0,"Routino-home".length)=="Routino-home")
285 {
286 var data=cookies[cookie].split(/[=:;]/);
287
288 if(data[1]=="lon") homelon=Number(data[2]);
289 if(data[3]=="lat") homelat=Number(data[4]);
290 }
291
292 if(homelon!==null && homelat!==null)
293 {
294 for(var m=1;m<=vismarkers;m++)
295 markerCheckHome(m);
296
297 // If the first location is empty and the cookie is set then fill it.
298
299 if(!routino.point[1].used)
300 markerMoveHome(1);
301 }
302
303 updateURLs();
304
305 updateSearchButtons();
306 }
307
308
309 //
310 // Function to perform the search if the return key is pressed.
311 // (using 'onchange' only triggers once and is confusing when clicking outside the field).
312 //
313
314 function searchOnReturnKey(ev)
315 {
316 if(ev.keyCode==13)
317 if(this.name.match(/^search([0-9]+)$/))
318 formSetSearch(RegExp.$1);
319
320 return(true);
321 }
322
323
324 //
325 // Change of language in the form
326 //
327
328 function formSetLanguage(value) // called from router.html (with no arguments)
329 {
330 if(value === undefined)
331 {
332 for(var lang=0;lang<document.forms["form"].elements["language"].length;lang++)
333 if(document.forms["form"].elements["language"][lang].checked)
334 routino.language=document.forms["form"].elements["language"][lang].value;
335 }
336 else
337 {
338 for(var lang=0;lang<document.forms["form"].elements["language"].length;lang++)
339 if(document.forms["form"].elements["language"][lang].value==value)
340 document.forms["form"].elements["language"][lang].checked=true;
341 else
342 document.forms["form"].elements["language"][lang].checked=false;
343
344 routino.language=value;
345 }
346
347 updateURLs();
348 }
349
350
351 //
352 // Change of transport in the form
353 //
354
355 function formSetTransport(value) // called from router.html
356 {
357 routino.transport=value;
358
359 for(var key in routino.transports)
360 document.forms["form"].elements["transport"][routino.transports[key]-1].checked=(key==routino.transport);
361
362 for(var key in routino.profile_highway)
363 document.forms["form"].elements["highway-" + key].value=routino.profile_highway[key][routino.transport];
364
365 for(var key in routino.profile_speed)
366 document.forms["form"].elements["speed-" + key].value=routino.profile_speed[key][routino.transport];
367
368 for(var key in routino.profile_property)
369 document.forms["form"].elements["property-" + key].value=routino.profile_property[key][routino.transport];
370
371 for(var key in routino.restrictions)
372 {
373 if(key=="oneway" || key=="turns")
374 document.forms["form"].elements["restrict-" + key].checked=routino.profile_restrictions[key][routino.transport];
375 else
376 document.forms["form"].elements["restrict-" + key].value=routino.profile_restrictions[key][routino.transport];
377 }
378
379 paramschanged=true;
380
381 updateURLs();
382 }
383
384
385 //
386 // Change of highway in the form
387 //
388
389 function formSetHighway(type,value) // called from router.html (with one argument)
390 {
391 if(value == "+")
392 {
393 value=routino.profile_highway[type][routino.transport];
394 value=10*Math.floor(value/10)+10;
395 }
396 else if(value == "-")
397 {
398 value=routino.profile_highway[type][routino.transport]-10;
399 value=10*Math.ceil(value/10)-10;
400 }
401 else if(value == "=")
402 value=document.forms["form"].elements["highway-" + type].value;
403
404 value=Number(value);
405 if(isNaN(value)) value= 50;
406 if(value>100) value=100;
407 if(value< 0) value= 0;
408
409 document.forms["form"].elements["highway-" + type].value=value;
410 routino.profile_highway[type][routino.transport]=value;
411
412 paramschanged=true;
413
414 updateURLs();
415 }
416
417
418 //
419 // Change of Speed in the form
420 //
421
422 function formSetSpeed(type,value) // called from router.html (with one argument)
423 {
424 if(value == "+")
425 {
426 value=routino.profile_speed[type][routino.transport];
427 if(value<10) value=2*Math.floor(value/2)+2;
428 else if(value<30) value=5*Math.floor(value/5)+5;
429 else value=10*Math.floor(value/10)+10;
430 }
431 else if(value == "-")
432 {
433 value=routino.profile_speed[type][routino.transport];
434 if(value<=10) value=2*Math.ceil(value/2)-2;
435 else if(value<=30) value=5*Math.ceil(value/5)-5;
436 else value=10*Math.ceil(value/10)-10;
437 }
438 else if(value == "=")
439 value=document.forms["form"].elements["speed-" + type].value;
440
441 value=Number(value);
442 if(isNaN(value)) value= 60;
443 if(value>150) value=150;
444 if(value< 0) value= 0;
445
446 document.forms["form"].elements["speed-" + type].value=value;
447 routino.profile_speed[type][routino.transport]=value;
448
449 paramschanged=true;
450
451 updateURLs();
452 }
453
454
455 //
456 // Change of Property in the form
457 //
458
459 function formSetProperty(type,value) // called from router.html (with one argument)
460 {
461 if(value == "+")
462 {
463 value=routino.profile_property[type][routino.transport];
464 if(value>=40 && value<60) value=2*Math.floor(value/2)+2;
465 else value=5*Math.floor(value/5)+5;
466 }
467 else if(value == "-")
468 {
469 value=routino.profile_property[type][routino.transport];
470 if(value>40 && value<=60) value=2*Math.ceil(value/2)-2;
471 else value=5*Math.ceil(value/5)-5;
472 }
473 else if(value == "=")
474 value=document.forms["form"].elements["property-" + type].value;
475
476 value=Number(value);
477 if(isNaN(value)) value= 50;
478 if(value>100) value=100;
479 if(value< 0) value= 0;
480
481 document.forms["form"].elements["property-" + type].value=value;
482 routino.profile_property[type][routino.transport]=value;
483
484 paramschanged=true;
485
486 updateURLs();
487 }
488
489
490 //
491 // Change of Restriction rule in the form
492 //
493
494 function formSetRestriction(type,value) // called from router.html (with one argument)
495 {
496 if(type=="oneway" || type=="turns")
497 {
498 if(value === undefined)
499 value=document.forms["form"].elements["restrict-" + type].checked;
500
501 document.forms["form"].elements["restrict-" + type].checked=value;
502 routino.profile_restrictions[type][routino.transport]=value;
503 }
504 else if(type=="weight")
505 {
506 if(value == "+")
507 value=routino.profile_restrictions[type][routino.transport]+5;
508 else if(value == "-")
509 value=routino.profile_restrictions[type][routino.transport]-5;
510 else if(value == "=")
511 value=document.forms["form"].elements["restrict-" + type].value;
512
513 value=Number(value);
514 if(isNaN(value)) value= 0;
515 if(value>50) value=50;
516 if(value< 0) value= 0;
517
518 document.forms["form"].elements["restrict-" + type].value=value;
519 routino.profile_restrictions[type][routino.transport]=value;
520 }
521 else /* if(type=="height" || type=="width" || type=="length") */
522 {
523 if(value == "+")
524 value=routino.profile_restrictions[type][routino.transport]+1;
525 else if(value == "-")
526 value=routino.profile_restrictions[type][routino.transport]-1;
527 else if(value == "=")
528 value=document.forms["form"].elements["restrict-" + type].value;
529
530 value=Number(value);
531 if(isNaN(value)) value= 0;
532 if(value>25) value=25;
533 if(value< 0) value= 0;
534
535 document.forms["form"].elements["restrict-" + type].value=value;
536 routino.profile_restrictions[type][routino.transport]=value;
537 }
538
539 paramschanged=true;
540
541 updateURLs();
542 }
543
544
545 //
546 // Set the feature coordinates from the form when the form changes.
547 //
548
549 function formSetCoords(marker,lon,lat) // called from router.html (with one argument)
550 {
551 clearSearchResult(marker);
552
553 if(lon === undefined && lat === undefined)
554 {
555 lon=document.forms["form"].elements["lon" + marker].value;
556 lat=document.forms["form"].elements["lat" + marker].value;
557 }
558
559 if(lon === "" && lat === "")
560 {
561 document.forms["form"].elements["lon" + marker].value="";
562 document.forms["form"].elements["lat" + marker].value="";
563
564 routino.point[marker].lon="";
565 routino.point[marker].lat="";
566
567 updateURLs();
568 }
569 else
570 {
571 var lonlat;
572
573 if(lon==="")
574 {
575 lonlat=map.getCenter().clone();
576 lonlat.transform(epsg900913,epsg4326);
577
578 lon=lonlat.lon;
579 }
580
581 if(lon<-180) lon=-180;
582 if(lon>+180) lon=+180;
583
584 if(lat==="")
585 {
586 lonlat=map.getCenter().clone();
587 lonlat.transform(epsg900913,epsg4326);
588
589 lat=lonlat.lat;
590 }
591
592 if(lat<-90 ) lat=-90 ;
593 if(lat>+90 ) lat=+90 ;
594
595 lonlat = new OpenLayers.LonLat(lon,lat);
596 lonlat.transform(epsg4326,epsg900913);
597
598 markers[marker].move(lonlat);
599
600 markersmoved=true;
601
602 document.forms["form"].elements["lon" + marker].value=format5f(lon);
603 document.forms["form"].elements["lat" + marker].value=format5f(lat);
604
605 routino.point[marker].lon=lon;
606 routino.point[marker].lat=lat;
607 routino.point[marker].used=true;
608
609 markerCheckHome(marker);
610 }
611 }
612
613
614 //
615 // Set the search field from the form when the form changes.
616 //
617
618 function formSetSearch(marker,search) // called from event handler linked to router.html (with one argument)
619 {
620 clearSearchResult(marker);
621
622 if(search === undefined)
623 {
624 routino.point[marker].search=document.forms["form"].elements["search" + marker].value;
625
626 DoSearch(marker);
627 }
628 else
629 {
630 document.forms["form"].elements["search" + marker].value=search;
631
632 routino.point[marker].search=search;
633 }
634 }
635
636
637 //
638 // Change of loop or reverse option in the form
639 //
640
641 function formSetLoopReverse(type,value) // called from router.html (with one argument)
642 {
643 if(value === undefined)
644 value=document.forms["form"].elements[type].checked;
645
646 document.forms["form"].elements[type].checked=value;
647
648 if(type == "loop")
649 routino.loop=value;
650 else
651 routino.reverse=value;
652
653 updateURLs();
654 }
655
656
657 //
658 // Format a number in printf("%.5f") format.
659 //
660
661 function format5f(number)
662 {
663 var newnumber=Math.floor(number*100000+0.5);
664 var delta=0;
665
666 if(newnumber>=0 && newnumber<100000) delta= 100000;
667 if(newnumber<0 && newnumber>-100000) delta=-100000;
668
669 var string=String(newnumber+delta);
670
671 var intpart =string.substring(0,string.length-5);
672 var fracpart=string.substring(string.length-5,string.length);
673
674 if(delta>0) intpart="0";
675 if(delta<0) intpart="-0";
676
677 return(intpart + "." + fracpart);
678 }
679
680
681 //
682 // Build a set of URL arguments
683 //
684
685 function buildURLArguments(lang)
686 {
687 var url= "transport=" + routino.transport;
688
689 for(var marker=1;marker<=vismarkers;marker++)
690 if(routino.point[marker].active)
691 {
692 url=url + ";lon" + marker + "=" + format5f(routino.point[marker].lon);
693 url=url + ";lat" + marker + "=" + format5f(routino.point[marker].lat);
694 if(routino.point[marker].search !== "")
695 url=url + ";search" + marker + "=" + encodeURIComponent(routino.point[marker].search);
696 }
697
698 for(var key in routino.profile_highway)
699 if(routino.profile_highway[key][routino.transport]!=routino_default.profile_highway[key][routino.transport])
700 url=url + ";highway-" + key + "=" + routino.profile_highway[key][routino.transport];
701
702 for(var key in routino.profile_speed)
703 if(routino.profile_speed[key][routino.transport]!=routino_default.profile_speed[key][routino.transport])
704 url=url + ";speed-" + key + "=" + routino.profile_speed[key][routino.transport];
705
706 for(var key in routino.profile_property)
707 if(routino.profile_property[key][routino.transport]!=routino_default.profile_property[key][routino.transport])
708 url=url + ";property-" + key + "=" + routino.profile_property[key][routino.transport];
709
710 for(var key in routino.restrictions)
711 if(routino.profile_restrictions[key][routino.transport]!=routino_default.profile_restrictions[key][routino.transport])
712 url=url + ";" + key + "=" + routino.profile_restrictions[key][routino.transport];
713
714 if(routino.loop)
715 url=url + ";loop=true";
716
717 if(routino.reverse)
718 url=url + ";reverse=true";
719
720 if(lang && routino.language)
721 url=url + ";language=" + routino.language;
722
723 return(url);
724 }
725
726
727 //
728 // Build a set of URL arguments for the map location
729 //
730
731 function buildMapArguments()
732 {
733 var lonlat = map.getCenter().clone();
734 lonlat.transform(epsg900913,epsg4326);
735
736 var zoom = map.getZoom() + map.minZoomLevel;
737
738 return "lat=" + format5f(lonlat.lat) + ";lon=" + format5f(lonlat.lon) + ";zoom=" + zoom;
739 }
740
741
742 //
743 // Update the URLs
744 //
745
746 function updateURLs()
747 {
748 var urlargs1=buildURLArguments(true);
749 var urlargs2=buildURLArguments(false);
750 var mapargs=buildMapArguments();
751
752 var links=document.getElementsByTagName("a");
753
754 for(var i=0; i<links.length; i++)
755 {
756 var element=links[i];
757
758 if(element.id == "permalink_url")
759 element.href=location.pathname + "?" + urlargs1 + ";" + mapargs;
760
761 if(element.id == "visualiser_url")
762 element.href="visualiser.html" + "?" + mapargs;
763
764 if(element.id == "edit_url")
765 element.href=mapprops.editurl + "?" + mapargs;
766
767 if(element.id.match(/^lang_([a-zA-Z-]+)_url$/))
768 element.href="router.html" + "." + RegExp.$1 + "?" + urlargs2 + ";" + mapargs;
769 }
770 }
771
772
773 ////////////////////////////////////////////////////////////////////////////////
774 ///////////////////////////////// Map handling /////////////////////////////////
775 ////////////////////////////////////////////////////////////////////////////////
776
777 var map;
778 var layerMap=[], layerVectors, layerGPX;
779 var epsg4326, epsg900913;
780 var routing_type;
781
782 //
783 // Initialise the 'map' object
784 //
785
786 function map_init() // called from router.html
787 {
788 // Create the map (Map URLs and limits are in mapprops.js)
789
790 epsg4326=new OpenLayers.Projection("EPSG:4326");
791 epsg900913=new OpenLayers.Projection("EPSG:900913");
792
793 map = new OpenLayers.Map ("map",
794 {
795 controls:[
796 new OpenLayers.Control.Navigation(),
797 new OpenLayers.Control.PanZoomBar(),
798 new OpenLayers.Control.ScaleLine(),
799 new OpenLayers.Control.LayerSwitcher()
800 ],
801
802 projection: epsg900913,
803 displayProjection: epsg4326,
804
805 minZoomLevel: mapprops.zoomout,
806 numZoomLevels: mapprops.zoomin-mapprops.zoomout+1,
807 maxResolution: 156543.03390625 / Math.pow(2,mapprops.zoomout),
808
809 restrictedExtent: new OpenLayers.Bounds(mapprops.westedge,mapprops.southedge,mapprops.eastedge,mapprops.northedge).transform(epsg4326,epsg900913)
810 });
811
812 // Get a URL for the tile (mostly copied from OpenLayers/Layer/XYZ.js).
813
814 function limitedUrl(bounds)
815 {
816 var res = this.map.getResolution();
817
818 var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
819 var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
820 var z = this.map.getZoom() + this.map.minZoomLevel;
821
822 var limit = Math.pow(2, z);
823 x = ((x % limit) + limit) % limit;
824
825 var xyz = {"x": x, "y": y, "z": z};
826 var url = this.url;
827
828 if (OpenLayers.Util.isArray(url))
829 {
830 var s = "" + xyz.x + xyz.y + xyz.z;
831 url = this.selectUrl(s, url);
832 }
833
834 return OpenLayers.String.format(url, xyz);
835 }
836
837 // Add map tile layers
838
839 for(var l=0; l<mapprops.mapdata.length; l++)
840 {
841 var urls;
842
843 if(OpenLayers.Util.isArray(mapprops.mapdata[l].tiles.subdomains))
844 {
845 urls=[];
846
847 for(var s=0; s<mapprops.mapdata[l].tiles.subdomains.length; s++)
848 urls.push(mapprops.mapdata[l].tiles.url.replace(/\${s}/,mapprops.mapdata[l].tiles.subdomains[s]));
849 }
850 else
851 urls=mapprops.mapdata[l].tiles.url;
852
853 layerMap[l] = new OpenLayers.Layer.TMS(mapprops.mapdata[l].label,
854 urls,
855 {
856 getURL: limitedUrl,
857 displayOutsideMaxExtent: true,
858 buffer: 1
859 });
860 map.addLayer(layerMap[l]);
861 }
862
863 // Update the attribution if the layer changes
864
865 function change_attribution_event(event)
866 {
867 for(var l=0; l<mapprops.mapdata.length; l++)
868 if(layerMap[l] == event.layer)
869 change_attribution(l);
870 }
871
872 map.events.register("changelayer",layerMap,change_attribution_event);
873
874 function change_attribution(l)
875 {
876 var data_url =mapprops.mapdata[l].attribution.data_url;
877 var data_text=mapprops.mapdata[l].attribution.data_text;
878 var tile_url =mapprops.mapdata[l].attribution.tile_url;
879 var tile_text=mapprops.mapdata[l].attribution.tile_text;
880
881 document.getElementById("attribution_data").innerHTML="<a href=\"" + data_url + "\" target=\"data_attribution\">" + data_text + "</a>";
882 document.getElementById("attribution_tile").innerHTML="<a href=\"" + tile_url + "\" target=\"tile_attribution\">" + tile_text + "</a>";
883 }
884
885 change_attribution(0);
886
887 // Define a GPX layer but don't add it yet
888
889 layerGPX={shortest: null, quickest: null};
890
891 gpx_style={shortest: new OpenLayers.Style({},{strokeWidth: 3, strokeColor: "#00FF00"}),
892 quickest: new OpenLayers.Style({},{strokeWidth: 3, strokeColor: "#0000FF"})};
893
894 // Add a vectors layer
895
896 layerVectors = new OpenLayers.Layer.Vector("Markers",{displayInLayerSwitcher: false});
897 map.addLayer(layerVectors);
898
899 // A set of markers
900
901 markers={};
902 markersmoved=false;
903 paramschanged=false;
904
905 for(var marker=1;marker<=mapprops.maxmarkers;marker++)
906 {
907 markers[marker] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0),{},
908 new OpenLayers.Style({},{externalGraphic: "icons/marker-" + marker + "-red.png",
909 fillColor: "white",
910 graphicYOffset: -25,
911 graphicWidth: 21,
912 graphicHeight: 25,
913 display: "none"}));
914
915 layerVectors.addFeatures([markers[marker]]);
916 }
917
918 // A function to drag the markers
919
920 var drag = new OpenLayers.Control.DragFeature(layerVectors,
921 {onDrag: dragMarkerMove,
922 onComplete: dragMarkerComplete });
923 map.addControl(drag);
924 drag.activate();
925
926 // Markers to highlight a selected point
927
928 for(var highlight in highlights)
929 {
930 highlights[highlight] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0),{},
931 new OpenLayers.Style({},{strokeColor: route_dark_colours[highlight],
932 fillColor: "white",
933 pointRadius: 10,
934 strokeWidth: 4,
935 fillOpacity: 0,
936 display: "none"}));
937
938 layerVectors.addFeatures([highlights[highlight]]);
939 }
940
941 // A popup for routing results
942
943 for(var popup in popups)
944 popups[popup] = createPopup(popup);
945
946 // Move the map
947
948 map.events.register("moveend", map, updateURLs);
949
950 var lon =args["lon"];
951 var lat =args["lat"];
952 var zoom=args["zoom"];
953
954 if(lon !== undefined && lat !== undefined && zoom !== undefined)
955 {
956 if(lon<mapprops.westedge) lon=mapprops.westedge;
957 if(lon>mapprops.eastedge) lon=mapprops.eastedge;
958
959 if(lat<mapprops.southedge) lat=mapprops.southedge;
960 if(lat>mapprops.northedge) lat=mapprops.northedge;
961
962 if(zoom<mapprops.zoomout) zoom=mapprops.zoomout;
963 if(zoom>mapprops.zoomin) zoom=mapprops.zoomin;
964
965 var lonlat = new OpenLayers.LonLat(lon,lat);
966 lonlat.transform(epsg4326,epsg900913);
967
968 map.moveTo(lonlat,zoom-map.minZoomLevel);
969 }
970 else
971 {
972 map.setCenter(map.restrictedExtent.getCenterLonLat(), map.getZoomForExtent(map.restrictedExtent,true));
973 map.maxResolution = map.getResolution();
974 }
975
976 // Unhide editing URL if variable set
977
978 if(mapprops.editurl !== undefined && mapprops.editurl !== "")
979 {
980 var edit_url=document.getElementById("edit_url");
981
982 edit_url.style.display="";
983 edit_url.href=mapprops.editurl;
984 }
985
986 updateURLs();
987 }
988
989
990 //
991 // Callback for a marker drag occuring on the map.
992 //
993
994 function dragMarkerMove(feature,pixel)
995 {
996 for(var marker in markers)
997 if(feature==markers[marker])
998 dragMarkerSetForm(marker);
999 }
1000
1001
1002 //
1003 // Callback for completing a marker drag on the map.
1004 //
1005
1006 function dragMarkerComplete(feature,pixel)
1007 {
1008 for(var marker in markers)
1009 if(feature==markers[marker])
1010 dragMarkerSetForm(marker);
1011
1012 updateURLs();
1013 }
1014
1015
1016 //
1017 // Set the feature coordinates in the form after dragging it on the map.
1018 //
1019
1020 function dragMarkerSetForm(marker)
1021 {
1022 var lonlat = new OpenLayers.LonLat(markers[marker].geometry.x, markers[marker].geometry.y);
1023 lonlat.transform(epsg900913,epsg4326);
1024
1025 formSetCoords(marker,lonlat.lon,lonlat.lat);
1026 }
1027
1028
1029 ////////////////////////////////////////////////////////////////////////////////
1030 /////////////////////////////// Marker dragging ////////////////////////////////
1031 ////////////////////////////////////////////////////////////////////////////////
1032
1033 var dragged_waypoint=null,dragged_marker=null;
1034 var dragged_waypoint_over=null,dragged_marker_over=null;
1035 var dragged_icon_x,dragged_icon_y;
1036
1037 //
1038 // Drag a waypoint up or down the list.
1039 //
1040
1041 function dragWaypointStart(e)
1042 {
1043 var w=e.target;
1044
1045 while(w!=null && w.className != "waypoint")
1046 w=w.parentElement;
1047
1048 if(w===null)
1049 return;
1050
1051 w.style.opacity = "0.5";
1052
1053 dragged_waypoint=w;
1054 dragged_marker=Number.parseInt(dragged_waypoint.id.substring(8));
1055
1056 dragged_icon_x=e.clientX-e.target.offsetLeft;
1057 dragged_icon_y=e.clientY-e.target.offsetTop;
1058 }
1059
1060 function dragWaypointEnd(e)
1061 {
1062 e.preventDefault();
1063
1064 if(dragged_waypoint===null)
1065 return;
1066
1067 dragged_waypoint.style.opacity = "";
1068
1069 dragged_waypoint=null;
1070 dragged_marker=null;
1071
1072 if(dragged_waypoint_over===null)
1073 return;
1074
1075 dragged_waypoint_over.style.border = "";
1076
1077 dragged_waypoint_over=null;
1078 dragged_marker_over=null;
1079 }
1080
1081
1082 //
1083 // Drag a waypoint over another one up or down the list.
1084 //
1085
1086 function dragWaypointEnter(e)
1087 {
1088 var w=e.target;
1089
1090 while(w!=null && w.className != "waypoint")
1091 w=w.parentElement;
1092
1093 if(w===null)
1094 return;
1095
1096 if(dragged_waypoint_over!==null)
1097 dragged_waypoint_over.style.border = "";
1098
1099 if(w==dragged_waypoint)
1100 return;
1101
1102 dragged_waypoint_over=w;
1103 dragged_marker_over=Number.parseInt(dragged_waypoint_over.id.substring(8));
1104
1105 if(dragged_marker>dragged_marker_over)
1106 w.style.borderTop = "3px solid black";
1107 else
1108 w.style.borderBottom = "3px solid black";
1109 }
1110
1111 function dragWaypointOver(e)
1112 {
1113 e.preventDefault();
1114 }
1115
1116 function dragWaypointLeave(e)
1117 {
1118 var w=e.target;
1119
1120 while(w!=null && w.className != "waypoint")
1121 w=w.parentElement;
1122
1123 if(w===null)
1124 return;
1125
1126 if(w==dragged_waypoint_over)
1127 return;
1128
1129 w.style.border = "";
1130 }
1131
1132
1133 //
1134 // Drop the waypoint after dragging up or down the list.
1135 //
1136
1137 function dragWaypointDrop(e)
1138 {
1139 e.preventDefault();
1140
1141 if(dragged_marker_over===null)
1142 return;
1143
1144 if(dragged_marker_over>dragged_marker)
1145 for(var m=dragged_marker;m<dragged_marker_over;m++)
1146 markerSwap(m,m+1);
1147
1148 if(dragged_marker_over<dragged_marker)
1149 for(var m=dragged_marker;m>dragged_marker_over;m--)
1150 markerSwap(m,m-1);
1151 }
1152
1153
1154 //
1155 // Drag a waypoint over the map.
1156 //
1157
1158 function dragWaypointMapEnter(e)
1159 {
1160 e.preventDefault();
1161
1162 if(dragged_waypoint_over!==null)
1163 dragged_waypoint_over.style.border = "";
1164 }
1165
1166 function dragWaypointMapOver(e)
1167 {
1168 e.preventDefault();
1169 }
1170
1171 function dragWaypointMapLeave(e)
1172 {
1173 e.preventDefault();
1174 }
1175
1176
1177 //
1178 // Drop the waypoint after dragging it over the map.
1179 //
1180
1181 function dragWaypointMapDrop(e)
1182 {
1183 e.preventDefault();
1184
1185 var rect = document.getElementById("map").getBoundingClientRect();
1186
1187 var lonlat = map.getLonLatFromViewPortPx(new OpenLayers.Pixel(e.clientX-rect.left-window.scrollX-dragged_icon_x+8,
1188 e.clientY-rect.top -window.scrollY-dragged_icon_y+21));
1189 lonlat.transform(epsg900913,epsg4326);
1190
1191 formSetCoords(dragged_marker,lonlat.lon,lonlat.lat);
1192
1193 if(!routino.point[dragged_marker].active)
1194 markerToggleMap(dragged_marker);
1195 }
1196
1197
1198 ////////////////////////////////////////////////////////////////////////////////
1199 /////////////////////////////// Marker handling ////////////////////////////////
1200 ////////////////////////////////////////////////////////////////////////////////
1201
1202 //
1203 // Toggle a marker on the map.
1204 //
1205
1206 function markerToggleMap(marker) // called from router.html
1207 {
1208 if(!routino.point[marker].used)
1209 {
1210 routino.point[marker].used=true;
1211 markerCentre(marker);
1212 markerCoords(marker);
1213 }
1214
1215 markerAddRemoveMap(marker,!routino.point[marker].active);
1216 }
1217
1218
1219 //
1220 // Show or hide a marker on the map.
1221 //
1222
1223 function markerAddRemoveMap(marker,active)
1224 {
1225 if(active)
1226 markerAddMap(marker);
1227 else
1228 markerRemoveMap(marker);
1229 }
1230
1231
1232 //
1233 // Show a marker on the map.
1234 //
1235
1236 function markerAddMap(marker)
1237 {
1238 clearSearchResult(marker);
1239
1240 markers[marker].style.display = "";
1241 routino.point[marker].active=true;
1242 routino.point[marker].used=true;
1243
1244 updateIcon(marker);
1245
1246 markersmoved=true;
1247
1248 updateURLs();
1249
1250 updateSearchButtons();
1251 }
1252
1253
1254 //
1255 // Remove a marker from the map.
1256 //
1257
1258 function markerRemoveMap(marker)
1259 {
1260 clearSearchResult(marker);
1261
1262 markers[marker].style.display = "none";
1263 routino.point[marker].active=false;
1264
1265 updateIcon(marker);
1266
1267 markersmoved=true;
1268
1269 updateURLs();
1270
1271 updateSearchButtons();
1272 }
1273
1274
1275 //
1276 // Display search string for the marker
1277 //
1278
1279 function markerSearch(marker) // called from router.html
1280 {
1281 clearSearchResult(marker);
1282
1283 document.getElementById("coords" + marker).style.display="none";
1284 document.getElementById("search" + marker).style.display="";
1285 }
1286
1287
1288 //
1289 // Display coordinates for the marker
1290 //
1291
1292 function markerCoords(marker) // called from router.html
1293 {
1294 clearSearchResult(marker);
1295
1296 document.getElementById("search" + marker).style.display="none";
1297 document.getElementById("coords" + marker).style.display="";
1298 }
1299
1300
1301 //
1302 // Centre the marker on the map
1303 //
1304
1305 function markerCentre(marker) // called from router.html
1306 {
1307 if(!routino.point[marker].used)
1308 return;
1309
1310 clearSearchResult(marker);
1311
1312 var lonlat=map.getCenter().clone();
1313 lonlat.transform(epsg900913,epsg4326);
1314
1315 formSetCoords(marker,lonlat.lon,lonlat.lat);
1316 }
1317
1318
1319 //
1320 // Centre the map on the marker
1321 //
1322
1323 function markerRecentre(marker) // called from router.html
1324 {
1325 if(!routino.point[marker].used)
1326 return;
1327
1328 clearSearchResult(marker);
1329
1330 var lon=routino.point[marker].lon;
1331 var lat=routino.point[marker].lat;
1332
1333 var lonlat = new OpenLayers.LonLat(lon,lat);
1334 lonlat.transform(epsg4326,epsg900913);
1335
1336 map.panTo(lonlat);
1337 }
1338
1339
1340 //
1341 // Clear the current marker.
1342 //
1343
1344 function markerRemove(marker) // called from router.html
1345 {
1346 clearSearchResult(marker);
1347
1348 for(var m=marker;m<vismarkers;m++)
1349 markerCopy(m,m+1);
1350
1351 markerRemoveForm(vismarkers--);
1352
1353 if(vismarkers==1)
1354 markerAddAfter(1);
1355
1356 updateSearchButtons();
1357 }
1358
1359
1360 //
1361 // Add a marker before the current one.
1362 //
1363
1364 function markerAddBefore(marker)
1365 {
1366 if(vismarkers==mapprops.maxmarkers || marker==1)
1367 return false;
1368
1369 clearSearchResult(marker);
1370
1371 markerAddForm(++vismarkers);
1372
1373 for(var m=vismarkers;m>marker;m--)
1374 markerCopy(m,m-1);
1375
1376 markerClearForm(marker-1);
1377 }
1378
1379
1380 //
1381 // Add a marker after the current one.
1382 //
1383
1384 function markerAddAfter(marker) // called from router.html
1385 {
1386 if(vismarkers==mapprops.maxmarkers)
1387 return false;
1388
1389 clearSearchResult(marker);
1390
1391 markerAddForm(++vismarkers);
1392
1393 for(var m=vismarkers;m>(marker+1);m--)
1394 markerCopy(m,m-1);
1395
1396 markerClearForm(marker+1);
1397 }
1398
1399
1400 //
1401 // Set this marker as the home location.
1402 //
1403
1404 function markerHome(marker) // called from router.html
1405 {
1406 if(!routino.point[marker].used)
1407 {
1408 markerMoveHome(marker);
1409 }
1410 else
1411 {
1412 clearSearchResult(marker);
1413
1414 markerSetClearHome(marker,!routino.point[marker].home);
1415 }
1416 }
1417
1418
1419 //
1420 // Set this marker as the current location.
1421 //
1422
1423 function markerLocate(marker) // called from router.html
1424 {
1425 clearSearchResult(marker);
1426
1427 function success(position)
1428 {
1429 formSetCoords(marker,position.coords.longitude,position.coords.latitude);
1430 markerAddMap(marker);
1431 }
1432
1433 function failure(error)
1434 {
1435 alert("Error: " + error.message);
1436 }
1437
1438 if(navigator.geolocation)
1439 navigator.geolocation.getCurrentPosition(success,failure);
1440 else
1441 alert("Error: Geolocation unavailable");
1442 }
1443
1444
1445 //
1446 // Update the search buttons enable/disable.
1447 //
1448
1449 function updateSearchButtons()
1450 {
1451 var markersactive=0;
1452
1453 for(var m=1;m<=vismarkers;m++)
1454 if(routino.point[m].active)
1455 markersactive++;
1456
1457 if(markersactive<2)
1458 {
1459 document.getElementById("shortest1").disabled="disabled";
1460 document.getElementById("quickest1").disabled="disabled";
1461 document.getElementById("shortest2").disabled="disabled";
1462 document.getElementById("quickest2").disabled="disabled";
1463 }
1464 else
1465 {
1466 document.getElementById("shortest1").disabled="";
1467 document.getElementById("quickest1").disabled="";
1468 document.getElementById("shortest2").disabled="";
1469 document.getElementById("quickest2").disabled="";
1470 }
1471 }
1472
1473
1474 //
1475 // Update an icon to set colours and home or normal marker.
1476 //
1477
1478 function updateIcon(marker)
1479 {
1480 if(routino.point[marker].home)
1481 {
1482 if(routino.point[marker].active)
1483 document.getElementById("icon" + marker).src="icons/marker-home-red.png";
1484 else
1485 document.getElementById("icon" + marker).src="icons/marker-home-grey.png";
1486
1487 markers[marker].style.externalGraphic="icons/marker-home-red.png";
1488 }
1489 else
1490 {
1491 if(routino.point[marker].active)
1492 document.getElementById("icon" + marker).src="icons/marker-" + marker + "-red.png";
1493 else
1494 document.getElementById("icon" + marker).src="icons/marker-" + marker + "-grey.png";
1495
1496 markers[marker].style.externalGraphic="icons/marker-" + marker + "-red.png";
1497 }
1498
1499 layerVectors.drawFeature(markers[marker]);
1500 }
1501
1502
1503 //
1504 // Move the marker to the home location
1505 //
1506
1507 function markerMoveHome(marker)
1508 {
1509 if(homelon===null || homelat===null)
1510 return;
1511
1512 routino.point[marker].home=true;
1513 routino.point[marker].used=true;
1514
1515 formSetCoords(marker,homelon,homelat);
1516 markerAddMap(marker);
1517 }
1518
1519
1520 //
1521 // Set or clear the home marker icon
1522 //
1523
1524 function markerSetClearHome(marker,home)
1525 {
1526 var cookie;
1527 var date = new Date();
1528
1529 if(home)
1530 {
1531 homelat=format5f(routino.point[marker].lat);
1532 homelon=format5f(routino.point[marker].lon);
1533
1534 cookie="Routino-home=lon:" + homelon + ":lat:" + homelat;
1535
1536 date.setUTCFullYear(date.getUTCFullYear()+5);
1537
1538 routino.point[marker].home=true;
1539 }
1540 else
1541 {
1542 homelat=null;
1543 homelon=null;
1544
1545 cookie="Routino-home=unset";
1546
1547 date.setUTCFullYear(date.getUTCFullYear()-1);
1548
1549 routino.point[marker].home=false;
1550 }
1551
1552 document.cookie=cookie + ";expires=" + date.toGMTString();
1553
1554 updateIcon(marker);
1555
1556 for(var m=1;m<=mapprops.maxmarkers;m++)
1557 markerCheckHome(m);
1558 }
1559
1560
1561 //
1562 // Check if a marker is the home marker
1563 //
1564
1565 function markerCheckHome(marker)
1566 {
1567 var home=routino.point[marker].home;
1568
1569 if(routino.point[marker].lon==homelon && routino.point[marker].lat==homelat)
1570 routino.point[marker].home=true;
1571 else
1572 routino.point[marker].home=false;
1573
1574 if(home!=routino.point[marker].home)
1575 updateIcon(marker);
1576 }
1577
1578
1579 //
1580 // Move this marker up.
1581 //
1582
1583 function markerMoveUp(marker) // called from router.html
1584 {
1585 if(marker==1)
1586 {
1587 for(var m=1;m<vismarkers;m++)
1588 markerSwap(m,m+1);
1589 }
1590 else
1591 markerSwap(marker,marker-1);
1592 }
1593
1594
1595 //
1596 // Move this marker down.
1597 //
1598
1599 function markerMoveDown(marker) // called from router.html
1600 {
1601 if(marker==vismarkers)
1602 {
1603 for(var m=vismarkers;m>1;m--)
1604 markerSwap(m,m-1);
1605 }
1606 else
1607 markerSwap(marker,marker+1);
1608 }
1609
1610
1611 //
1612 // Copy a marker from one place to another.
1613 //
1614
1615 function markerCopy(marker1,marker2)
1616 {
1617 for(var element in routino.point[marker2])
1618 routino.point[marker1][element]=routino.point[marker2][element];
1619
1620 document.getElementById("search" + marker1).style.display=document.getElementById("search" + marker2).style.display;
1621
1622 document.getElementById("coords" + marker1).style.display=document.getElementById("coords" + marker2).style.display;
1623
1624 document.forms["form"].elements["search" + marker1].value=document.forms["form"].elements["search" + marker2].value;
1625
1626 formSetCoords(marker1,routino.point[marker1].lon,routino.point[marker1].lat);
1627
1628 markerAddRemoveMap(marker1,routino.point[marker1].active);
1629 }
1630
1631
1632 //
1633 // Swap a pair of markers.
1634 //
1635
1636 function markerSwap(marker1,marker2)
1637 {
1638 for(var element in routino.point[marker2])
1639 {
1640 var temp=routino.point[marker1][element];
1641 routino.point[marker1][element]=routino.point[marker2][element];
1642 routino.point[marker2][element]=temp;
1643 }
1644
1645 var search_display=document.getElementById("search" + marker1).style.display;
1646 document.getElementById("search" + marker1).style.display=document.getElementById("search" + marker2).style.display;
1647 document.getElementById("search" + marker2).style.display=search_display;
1648
1649 var coords_display=document.getElementById("coords" + marker1).style.display;
1650 document.getElementById("coords" + marker1).style.display=document.getElementById("coords" + marker2).style.display;
1651 document.getElementById("coords" + marker2).style.display=coords_display;
1652
1653 var search_value=document.forms["form"].elements["search" + marker1].value;
1654 document.forms["form"].elements["search" + marker1].value=document.forms["form"].elements["search" + marker2].value;
1655 document.forms["form"].elements["search" + marker2].value=search_value;
1656
1657 formSetCoords(marker1,routino.point[marker1].lon,routino.point[marker1].lat);
1658 formSetCoords(marker2,routino.point[marker2].lon,routino.point[marker2].lat);
1659
1660 markerAddRemoveMap(marker1,routino.point[marker1].active);
1661 markerAddRemoveMap(marker2,routino.point[marker2].active);
1662 }
1663
1664
1665 //
1666 // Reverse the markers.
1667 //
1668
1669 function markersReverse() // called from router.html
1670 {
1671 for(var marker=1;marker<=vismarkers/2;marker++)
1672 markerSwap(marker,vismarkers+1-marker);
1673
1674 markersmoved=true;
1675
1676 updateURLs();
1677 }
1678
1679
1680 //
1681 // Close the loop.
1682 //
1683
1684 function markersLoop() // called from router.html
1685 {
1686 if(vismarkers==mapprops.maxmarkers)
1687 return false;
1688
1689 if(routino.point[vismarkers].lon==routino.point[1].lon && routino.point[vismarkers].lat==routino.point[1].lat)
1690 {
1691 if(routino.point[vismarkers].active)
1692 return false;
1693 else
1694 {
1695 markerToggleMap(vismarkers);
1696 return true;
1697 }
1698 }
1699
1700 if(routino.point[vismarkers].used)
1701 markerAddForm(++vismarkers);
1702
1703 markerCopy(vismarkers,1);
1704
1705 markersmoved=true;
1706
1707 updateURLs();
1708
1709 updateSearchButtons();
1710 }
1711
1712
1713 //
1714 // Display the form for a marker
1715 //
1716
1717 function markerAddForm(marker)
1718 {
1719 document.getElementById("waypoint" + marker).style.display="";
1720 }
1721
1722
1723 //
1724 // Hide the form for a marker
1725 //
1726
1727 function markerRemoveForm(marker)
1728 {
1729 document.getElementById("waypoint" + marker).style.display="none";
1730
1731 markerClearForm(marker);
1732 }
1733
1734
1735 //
1736 // Clear the form for a marker
1737 //
1738
1739 function markerClearForm(marker)
1740 {
1741 markerRemoveMap(marker);
1742 markerCoords(marker);
1743
1744 formSetCoords(marker,"","");
1745 formSetSearch(marker,"");
1746
1747 updateIcon(marker);
1748
1749 routino.point[marker].used=false;
1750 routino.point[marker].home=false;
1751 routino.point[marker].active=false;
1752 }
1753
1754
1755 ////////////////////////////////////////////////////////////////////////////////
1756 //////////////////////////// Route results handling ////////////////////////////
1757 ////////////////////////////////////////////////////////////////////////////////
1758
1759 var route_light_colours={shortest: "#60C060", quickest: "#6060C0"};
1760 var route_dark_colours ={shortest: "#408040", quickest: "#404080"};
1761
1762 var highlights={shortest: null, quickest: null};
1763 var popups={shortest: null, quickest: null};
1764 var routepoints={shortest: {}, quickest: {}};
1765 var gpx_style={shortest: null, quickest: null};
1766
1767
1768 //
1769 // Highlight a specific item in the route
1770 //
1771
1772 function highlight(type,line,action)
1773 {
1774 if(action == "clear")
1775 {
1776 highlights[type].style.display = "none";
1777
1778 drawPopup(type,null);
1779 }
1780 else if(action == "zoom")
1781 {
1782 var lonlat = new OpenLayers.LonLat(routepoints[type][line].lon,routepoints[type][line].lat);
1783 lonlat.transform(epsg4326,epsg900913);
1784
1785 map.moveTo(lonlat,map.numZoomLevels-3);
1786 }
1787 else
1788 {
1789 // Marker
1790
1791 var lonlat = new OpenLayers.LonLat(routepoints[type][line].lon,routepoints[type][line].lat);
1792 lonlat.transform(epsg4326,epsg900913);
1793
1794 highlights[type].move(lonlat);
1795
1796 if(highlights[type].style.display == "none")
1797 highlights[type].style.display = "";
1798
1799 // Popup
1800
1801 drawPopup(type,"<table>" + routepoints[type][line].html + "</table>");
1802 }
1803
1804 layerVectors.drawFeature(highlights[type]);
1805 }
1806
1807
1808 //
1809 // Create a popup - independent of map because want it fixed on screen not fixed on map.
1810 //
1811
1812 function createPopup(type)
1813 {
1814 var popup=document.createElement("div");
1815
1816 popup.className = "popup";
1817
1818 popup.innerHTML = "<span></span>";
1819
1820 popup.style.display = "none";
1821
1822 popup.style.position = "fixed";
1823 popup.style.top = "-4000px";
1824 popup.style.left = "-4000px";
1825 popup.style.zIndex = "100";
1826
1827 popup.style.padding = "5px";
1828
1829 popup.style.opacity=0.85;
1830 popup.style.backgroundColor=route_light_colours[type];
1831 popup.style.border="4px solid " + route_dark_colours[type];
1832
1833 document.body.appendChild(popup);
1834
1835 return(popup);
1836 }
1837
1838
1839 //
1840 // Draw a popup - independent of map because want it fixed on screen not fixed on map.
1841 //
1842
1843 function drawPopup(type,html)
1844 {
1845 var popup=popups[type];
1846
1847 if(html===null)
1848 {
1849 popup.style.display="none";
1850 return;
1851 }
1852
1853 if(popup.style.display=="none")
1854 {
1855 var map_div=document.getElementById("map");
1856
1857 popup.style.left =map_div.offsetParent.offsetLeft+map_div.offsetLeft+60 + "px";
1858 popup.style.top = map_div.offsetTop +30 + "px";
1859 popup.style.width =map_div.clientWidth-120 + "px";
1860
1861 popup.style.display="";
1862 }
1863
1864 var close="<span style='float: right; cursor: pointer;' onclick='highlight(\""+type+"\",-1,\"clear\")'>X</span>";
1865
1866 popup.innerHTML=close+html;
1867 }
1868
1869
1870 //
1871 // Remove a GPX trace
1872 //
1873
1874 function removeGPXTrace(type)
1875 {
1876 map.removeLayer(layerGPX[type]);
1877 layerGPX[type].destroy();
1878 layerGPX[type]=null;
1879
1880 displayStatus(type,"no_info");
1881
1882 document.getElementById(type + "_links").style.display = "none";
1883
1884 document.getElementById(type + "_route").innerHTML = "";
1885
1886 hideshow_hide(type);
1887 }
1888
1889
1890 ////////////////////////////////////////////////////////////////////////////////
1891 /////////////////////////////// Server handling ////////////////////////////////
1892 ////////////////////////////////////////////////////////////////////////////////
1893
1894 //
1895 // Define an AJAX request object
1896 //
1897
1898 function ajaxGET(url,success,failure,state)
1899 {
1900 var ajaxRequest=new XMLHttpRequest();
1901
1902 function ajaxGOT(options) {
1903 if(this.readyState==4)
1904 if(this.status==200)
1905 { if(typeof(options.success)=="function") options.success(this,options.state); }
1906 else
1907 { if(typeof(options.failure)=="function") options.failure(this,options.state); }
1908 }
1909
1910 ajaxRequest.onreadystatechange = function(){ ajaxGOT.call(ajaxRequest,{success: success, failure: failure, state: state}); };
1911 ajaxRequest.open("GET", url, true);
1912 ajaxRequest.send(null);
1913 }
1914
1915
1916 //
1917 // Display data statistics
1918 //
1919
1920 function displayStatistics() // called from router.html
1921 {
1922 // Use AJAX to get the statistics
1923
1924 ajaxGET("statistics.cgi", runStatisticsSuccess);
1925 }
1926
1927
1928 //
1929 // Success in running data statistics generation.
1930 //
1931
1932 function runStatisticsSuccess(response)
1933 {
1934 document.getElementById("statistics_data").innerHTML="<pre>" + response.responseText + "</pre>";
1935 document.getElementById("statistics_link").style.display="none";
1936 }
1937
1938
1939 //
1940 // Submit form - perform the routing
1941 //
1942
1943 function findRoute(type) // called from router.html
1944 {
1945 tab_select("results");
1946
1947 hideshow_hide("help_options");
1948 hideshow_hide("shortest");
1949 hideshow_hide("quickest");
1950
1951 displayStatus("result","running");
1952
1953 var url="router.cgi" + "?" + buildURLArguments(true) + ";type=" + type;
1954
1955 // Destroy the existing layer(s)
1956
1957 highlight("shortest",-1,"clear");
1958 highlight("quickest",-1,"clear");
1959
1960 if(markersmoved || paramschanged)
1961 {
1962 if(layerGPX.shortest!==null)
1963 removeGPXTrace("shortest");
1964 if(layerGPX.quickest!==null)
1965 removeGPXTrace("quickest");
1966 markersmoved=false;
1967 paramschanged=false;
1968 }
1969 else if(layerGPX[type]!==null)
1970 removeGPXTrace(type);
1971
1972 // Use AJAX to run the router
1973
1974 routing_type=type;
1975
1976 ajaxGET(url, runRouterSuccess, runRouterFailure);
1977 }
1978
1979
1980 //
1981 // Success in running router.
1982 //
1983
1984 function runRouterSuccess(response)
1985 {
1986 var lines=response.responseText.split("\n");
1987
1988 var uuid=lines[0];
1989 var success=lines[1];
1990
1991 var link;
1992
1993 // Update the status message
1994
1995 if(success=="ERROR")
1996 {
1997 displayStatus("result","error");
1998 hideshow_show("help_route");
1999
2000 link=document.getElementById("router_log_error");
2001 link.href="results.cgi?uuid=" + uuid + ";type=router;format=log";
2002
2003 return;
2004 }
2005 else
2006 {
2007 displayStatus("result","complete");
2008 hideshow_hide("help_route");
2009
2010 link=document.getElementById("router_log_complete");
2011 link.href="results.cgi?uuid=" + uuid + ";type=router;format=log";
2012 }
2013
2014 // Update the routing result message
2015
2016 link=document.getElementById(routing_type + "_html");
2017 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";
2018
2019 link=document.getElementById(routing_type + "_gpx_track");
2020 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";
2021
2022 link=document.getElementById(routing_type + "_gpx_route");
2023 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-route";
2024
2025 link=document.getElementById(routing_type + "_text_all");
2026 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text-all";
2027
2028 link=document.getElementById(routing_type + "_text");
2029 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text";
2030
2031 document.getElementById(routing_type + "_links").style.display = "";
2032
2033 // Add a GPX layer
2034
2035 var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";
2036
2037 layerGPX[routing_type] = new OpenLayers.Layer.Vector("GPX (" + routing_type + ")",
2038 {
2039 displayInLayerSwitcher: false,
2040 protocol: new OpenLayers.Protocol.HTTP({url: url, format: new OpenLayers.Format.GPX()}),
2041 strategies: [new OpenLayers.Strategy.Fixed()],
2042 style: gpx_style[routing_type],
2043 projection: map.displayProjection
2044 });
2045
2046 map.addLayer(layerGPX[routing_type]);
2047
2048 hideshow_show(routing_type);
2049
2050 displayResult(routing_type,uuid);
2051 }
2052
2053
2054 //
2055 // Failure in running router.
2056 //
2057
2058 function runRouterFailure(response)
2059 {
2060 displayStatus("result","failed");
2061 }
2062
2063
2064 //
2065 // Display the status
2066 //
2067
2068 function displayStatus(type,subtype,content)
2069 {
2070 var child=document.getElementById(type + "_status").firstChild;
2071
2072 do
2073 {
2074 if(child.id !== undefined)
2075 child.style.display="none";
2076
2077 child=child.nextSibling;
2078 }
2079 while(child !== null);
2080
2081 var chosen_status=document.getElementById(type + "_status_" + subtype);
2082
2083 chosen_status.style.display="";
2084
2085 if(content !== undefined)
2086 chosen_status.innerHTML=content;
2087 }
2088
2089
2090 //
2091 // Display the route
2092 //
2093
2094 function displayResult(type,uuid)
2095 {
2096 routing_type = type;
2097
2098 // Add the route
2099
2100 var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";
2101
2102 // Use AJAX to get the route
2103
2104 ajaxGET(url, getRouteSuccess, getRouteFailure);
2105 }
2106
2107
2108 //
2109 // Success in getting route.
2110 //
2111
2112 function getRouteSuccess(response)
2113 {
2114 var lines=response.responseText.split("\n");
2115
2116 routepoints[routing_type]=[];
2117
2118 var points=routepoints[routing_type];
2119
2120 var table=0;
2121 var point=0;
2122 var total_table,total_word;
2123
2124 for(var line=0;line<lines.length;line++)
2125 {
2126 var thisline=lines[line];
2127
2128 if(table===0)
2129 {
2130 if(thisline.match("<table>"))
2131 table=1;
2132 else
2133 continue;
2134 }
2135
2136 if(thisline.match("</table>"))
2137 break;
2138
2139 if(thisline.match("<tr class='([a-z])'>"))
2140 {
2141 var rowtype=RegExp.$1;
2142
2143 if(rowtype=="c")
2144 {
2145 thisline.match(": *([-0-9.]+) *([-0-9.]+)");
2146 points[point]={lat: Number(RegExp.$1), lon: Number(RegExp.$2), html: "", highway: "", distance: "", total: ""};
2147
2148 point++;
2149 }
2150 else if(rowtype=="n")
2151 {
2152 points[point-1].html += thisline;
2153 }
2154 else if(rowtype=="s")
2155 {
2156 thisline.match("<span class='h'>([^<]+)</span>");
2157 points[point-1].highway = RegExp.$1;
2158
2159 thisline.match("<span class='d'>([^<]+)</span>");
2160 points[point-1].distance = RegExp.$1;
2161
2162 thisline.match("(<span class='j'>[^<]+</span>)");
2163 points[point-1].total = RegExp.$1;
2164
2165 thisline.match("^(.*).<span class='j'>");
2166
2167 points[point-1].html += RegExp.$1;
2168 }
2169 else if(rowtype=="t")
2170 {
2171 points[point-1].html += thisline;
2172
2173 thisline.match("<span class='j'>([^<]+)</span>");
2174 points[point-1].total = RegExp.$1;
2175
2176 thisline.match("<td>(.*)");
2177 points[point-1].highway = RegExp.$1;
2178 }
2179 }
2180 }
2181
2182 displayStatus(routing_type,"info",points[point-1].total.bold());
2183
2184 var result="<table onmouseout='highlight(\"" + routing_type + "\",-1,\"clear\")'>";
2185
2186 for(var p=0;p<point;p++)
2187 {
2188 if(p!=point-1)
2189 points[p].html += "<tr><td>" + points[p].total;
2190
2191 result=result + "<tr onmouseover='highlight(\"" + routing_type + "\"," + p + ",\"show\")' " +
2192 "onclick='highlight(\"" + routing_type + "\"," + p + ",\"zoom\")'>" +
2193 "<td class='distance' title='" + points[p].distance + "'>#" + (p+1) +
2194 "<td class='highway'>" + points[p].highway;
2195 }
2196
2197 result=result + "</table>";
2198
2199 document.getElementById(routing_type + "_route").innerHTML=result;
2200 }
2201
2202
2203 //
2204 // Failure in getting route.
2205 //
2206
2207 function getRouteFailure(response)
2208 {
2209 document.getElementById(routing_type + "_route").innerHTML = "";
2210 }
2211
2212
2213 //
2214 // Perform a search
2215 //
2216
2217 function DoSearch(marker)
2218 {
2219 // Use AJAX to get the search result
2220
2221 var search=routino.point[marker].search;
2222
2223 var mapbounds=map.getExtent().clone();
2224 mapbounds.transform(epsg900913,epsg4326);
2225
2226 var url="search.cgi";
2227
2228 url=url + "?marker=" + marker;
2229 url=url + ";lonmin=" + format5f(mapbounds.left);
2230 url=url + ";latmin=" + format5f(mapbounds.bottom);
2231 url=url + ";lonmax=" + format5f(mapbounds.right);
2232 url=url + ";latmax=" + format5f(mapbounds.top);
2233 url=url + ";search=" + encodeURIComponent(search);
2234
2235 ajaxGET(url,runSearchSuccess);
2236 }
2237
2238
2239 var searchresults=[];
2240
2241 //
2242 // Success in running search.
2243 //
2244
2245 function runSearchSuccess(response)
2246 {
2247 var lines=response.responseText.split("\n");
2248
2249 var marker=lines[0];
2250 var cpuinfo=lines[1]; // not used
2251 var message=lines[2];
2252
2253 if(message !== "")
2254 {
2255 alert(message);
2256 return;
2257 }
2258
2259 searchresults[marker]=[];
2260
2261 for(var line=3;line<lines.length;line++)
2262 {
2263 var thisline=lines[line];
2264
2265 if(thisline==="")
2266 break;
2267
2268 thisline.match("([-.0-9]+) ([-.0-9]+) (.*)");
2269
2270 searchresults[marker][searchresults[marker].length]={lat: Number(RegExp.$1), lon: Number(RegExp.$2), name: RegExp.$3};
2271 }
2272
2273 if(searchresults[marker].length==1)
2274 {
2275 formSetSearch(marker,searchresults[marker][0].name);
2276 formSetCoords(marker,searchresults[marker][0].lon,searchresults[marker][0].lat);
2277 markerAddMap(marker);
2278 }
2279 else
2280 {
2281 var results=document.getElementById("searchresults" + marker);
2282
2283 var innerHTML="<td colspan=\"3\">";
2284
2285 for(var n=0;n<searchresults[marker].length;n++)
2286 {
2287 if(n>0)
2288 innerHTML+="<br>";
2289
2290 innerHTML+="<a href=\"#\" onclick=\"choseSearchResult(" + marker + "," + n + ")\">" +
2291 searchresults[marker][n].name +
2292 "</a>";
2293 }
2294
2295 results.innerHTML=innerHTML;
2296
2297 results.style.display="";
2298 }
2299 }
2300
2301
2302 //
2303 // Display search results.
2304 //
2305
2306 function choseSearchResult(marker,n)
2307 {
2308 if(n>=0)
2309 {
2310 formSetSearch(marker,searchresults[marker][n].name);
2311 formSetCoords(marker,searchresults[marker][n].lon,searchresults[marker][n].lat);
2312 markerAddMap(marker);
2313 }
2314 }
2315
2316
2317 //
2318 // Clear search results.
2319 //
2320
2321 function clearSearchResult(marker)
2322 {
2323 document.getElementById("searchresults" + marker).style.display="none";
2324 }