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 1656 - (show annotations) (download) (as text)
Sat May 16 15:33:49 2015 UTC (9 years, 10 months ago) by amb
File MIME type: application/javascript
File size: 51644 byte(s)
Allow dragging the waypoint icon up-and-down in the list and onto the
map.

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