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.leaflet.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1812 - (show annotations) (download) (as text)
Sat Sep 26 10:52:35 2015 UTC (9 years, 6 months ago) by amb
File MIME type: application/javascript
File size: 51371 byte(s)
Fix bug with specifying 'oneway' or 'turns' in the URL arguments.

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