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 1796 - (show annotations) (download) (as text)
Mon Sep 7 17:50:20 2015 UTC (9 years, 6 months ago) by amb
File MIME type: application/javascript
File size: 51431 byte(s)
Merge some of the translation phrases together to simplify them.
Change the HTML output and web pages to work with this.

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 + "=" + format5f(routino.point[marker].lon);
656 url=url + ";lat" + marker + "=" + format5f(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-window.scrollX-dragged_icon_x+8,
1081 e.clientY-rect.top -window.scrollY-dragged_icon_y+21));
1082
1083 formSetCoords(dragged_marker,lonlat.lng,lonlat.lat);
1084
1085 if(!routino.point[dragged_marker].active)
1086 markerToggleMap(dragged_marker);
1087 }
1088
1089
1090 ////////////////////////////////////////////////////////////////////////////////
1091 /////////////////////////////// Marker handling ////////////////////////////////
1092 ////////////////////////////////////////////////////////////////////////////////
1093
1094 //
1095 // Toggle a marker on the map.
1096 //
1097
1098 function markerToggleMap(marker) // called from router.html
1099 {
1100 if(!routino.point[marker].used)
1101 {
1102 routino.point[marker].used=true;
1103 markerCentre(marker);
1104 markerCoords(marker);
1105 }
1106
1107 markerAddRemoveMap(marker,!routino.point[marker].active);
1108
1109 updateSearchButtons();
1110 }
1111
1112
1113 //
1114 // Show or hide a marker on the map.
1115 //
1116
1117 function markerAddRemoveMap(marker,active)
1118 {
1119 if(active)
1120 markerAddMap(marker);
1121 else
1122 markerRemoveMap(marker);
1123 }
1124
1125
1126 //
1127 // Show a marker on the map.
1128 //
1129
1130 function markerAddMap(marker)
1131 {
1132 clearSearchResult(marker);
1133
1134 layerVectors.addLayer(markers[marker]);
1135 routino.point[marker].active=true;
1136 routino.point[marker].used=true;
1137
1138 updateIcon(marker);
1139
1140 markersmoved=true;
1141
1142 updateURLs();
1143 }
1144
1145
1146 //
1147 // Remove a marker from the map.
1148 //
1149
1150 function markerRemoveMap(marker)
1151 {
1152 clearSearchResult(marker);
1153
1154 layerVectors.removeLayer(markers[marker]);
1155 routino.point[marker].active=false;
1156
1157 updateIcon(marker);
1158
1159 markersmoved=true;
1160
1161 updateURLs();
1162 }
1163
1164
1165 //
1166 // Display search string for the marker
1167 //
1168
1169 function markerSearch(marker) // called from router.html
1170 {
1171 clearSearchResult(marker);
1172
1173 document.getElementById("coords" + marker).style.display="none";
1174 document.getElementById("search" + marker).style.display="";
1175 }
1176
1177
1178 //
1179 // Display coordinates for the marker
1180 //
1181
1182 function markerCoords(marker) // called from router.html
1183 {
1184 clearSearchResult(marker);
1185
1186 document.getElementById("search" + marker).style.display="none";
1187 document.getElementById("coords" + marker).style.display="";
1188 }
1189
1190
1191 //
1192 // Centre the marker on the map
1193 //
1194
1195 function markerCentre(marker) // called from router.html
1196 {
1197 if(!routino.point[marker].used)
1198 return;
1199
1200 clearSearchResult(marker);
1201
1202 var lonlat=map.getCenter();
1203
1204 formSetCoords(marker,lonlat.lng,lonlat.lat);
1205 }
1206
1207
1208 //
1209 // Centre the map on the marker
1210 //
1211
1212 function markerRecentre(marker) // called from router.html
1213 {
1214 if(!routino.point[marker].used)
1215 return;
1216
1217 clearSearchResult(marker);
1218
1219 var lon=routino.point[marker].lon;
1220 var lat=routino.point[marker].lat;
1221
1222 var lonlat = L.latLng(lat,lon);
1223
1224 map.panTo(lonlat);
1225 }
1226
1227
1228 //
1229 // Clear the current marker.
1230 //
1231
1232 function markerRemove(marker) // called from router.html
1233 {
1234 clearSearchResult(marker);
1235
1236 for(var m=marker;m<vismarkers;m++)
1237 markerCopy(m,m+1);
1238
1239 markerRemoveForm(vismarkers--);
1240
1241 if(vismarkers==1)
1242 markerAddAfter(1);
1243
1244 updateSearchButtons();
1245 }
1246
1247
1248 //
1249 // Add a marker before the current one.
1250 //
1251
1252 function markerAddBefore(marker)
1253 {
1254 if(vismarkers==mapprops.maxmarkers || marker==1)
1255 return false;
1256
1257 clearSearchResult(marker);
1258
1259 markerAddForm(++vismarkers);
1260
1261 for(var m=vismarkers;m>marker;m--)
1262 markerCopy(m,m-1);
1263
1264 markerClearForm(marker-1);
1265 }
1266
1267
1268 //
1269 // Add a marker after the current one.
1270 //
1271
1272 function markerAddAfter(marker) // called from router.html
1273 {
1274 if(vismarkers==mapprops.maxmarkers)
1275 return false;
1276
1277 clearSearchResult(marker);
1278
1279 markerAddForm(++vismarkers);
1280
1281 for(var m=vismarkers;m>(marker+1);m--)
1282 markerCopy(m,m-1);
1283
1284 markerClearForm(marker+1);
1285 }
1286
1287
1288 //
1289 // Set this marker as the home location.
1290 //
1291
1292 function markerHome(marker) // called from router.html
1293 {
1294 if(!routino.point[marker].used)
1295 {
1296 markerMoveHome(marker);
1297 }
1298 else
1299 {
1300 clearSearchResult(marker);
1301
1302 markerSetClearHome(marker,!routino.point[marker].home);
1303 }
1304 }
1305
1306
1307 //
1308 // Set this marker as the current location.
1309 //
1310
1311 function markerLocate(marker) // called from router.html
1312 {
1313 clearSearchResult(marker);
1314
1315 if(navigator.geolocation)
1316 navigator.geolocation.getCurrentPosition(
1317 function(position) {
1318 formSetCoords(marker,position.coords.longitude,position.coords.latitude);
1319 markerAddMap(marker);
1320 });
1321 }
1322
1323
1324 //
1325 // Update the search buttons enable/disable.
1326 //
1327
1328 function updateSearchButtons()
1329 {
1330 var markersactive=0;
1331
1332 for(var m=1;m<=vismarkers;m++)
1333 if(routino.point[m].active)
1334 markersactive++;
1335
1336 if(markersactive<2)
1337 {
1338 document.getElementById("shortest").disabled="disabled";
1339 document.getElementById("quickest").disabled="disabled";
1340 }
1341 else
1342 {
1343 document.getElementById("shortest").disabled="";
1344 document.getElementById("quickest").disabled="";
1345 }
1346 }
1347
1348
1349 //
1350 // Update an icon to set colours and home or normal marker.
1351 //
1352
1353 function updateIcon(marker)
1354 {
1355 if(routino.point[marker].home)
1356 {
1357 if(routino.point[marker].active)
1358 document.getElementById("icon" + marker).src="icons/marker-home-red.png";
1359 else
1360 document.getElementById("icon" + marker).src="icons/marker-home-grey.png";
1361
1362 markers[marker].setIcon(icons.home);
1363 }
1364 else
1365 {
1366 if(routino.point[marker].active)
1367 document.getElementById("icon" + marker).src="icons/marker-" + marker + "-red.png";
1368 else
1369 document.getElementById("icon" + marker).src="icons/marker-" + marker + "-grey.png";
1370
1371 markers[marker].setIcon(icons[marker]);
1372 }
1373
1374 markers[marker].update();
1375 }
1376
1377
1378 //
1379 // Move the marker to the home location
1380 //
1381
1382 function markerMoveHome(marker)
1383 {
1384 if(homelon===null || homelat===null)
1385 return;
1386
1387 routino.point[marker].home=true;
1388 routino.point[marker].used=true;
1389
1390 formSetCoords(marker,homelon,homelat);
1391 markerAddMap(marker);
1392 }
1393
1394
1395 //
1396 // Set or clear the home marker icon
1397 //
1398
1399 function markerSetClearHome(marker,home)
1400 {
1401 var cookie;
1402 var date = new Date();
1403
1404 if(home)
1405 {
1406 homelat=routino.point[marker].lat;
1407 homelon=routino.point[marker].lon;
1408
1409 cookie="Routino-home=lon:" + homelon + ":lat:" + homelat;
1410
1411 date.setUTCFullYear(date.getUTCFullYear()+5);
1412
1413 routino.point[marker].home=true;
1414 }
1415 else
1416 {
1417 homelat=null;
1418 homelon=null;
1419
1420 cookie="Routino-home=unset";
1421
1422 date.setUTCFullYear(date.getUTCFullYear()-1);
1423
1424 routino.point[marker].home=false;
1425 }
1426
1427 document.cookie=cookie + ";expires=" + date.toGMTString();
1428
1429 updateIcon(marker);
1430
1431 for(var m=1;m<=mapprops.maxmarkers;m++)
1432 markerCheckHome(m);
1433 }
1434
1435
1436 //
1437 // Check if a marker is the home marker
1438 //
1439
1440 function markerCheckHome(marker)
1441 {
1442 var home=routino.point[marker].home;
1443
1444 if(routino.point[marker].lon==homelon && routino.point[marker].lat==homelat)
1445 routino.point[marker].home=true;
1446 else
1447 routino.point[marker].home=false;
1448
1449 if(home!=routino.point[marker].home)
1450 updateIcon(marker);
1451 }
1452
1453
1454 //
1455 // Move this marker up.
1456 //
1457
1458 function markerMoveUp(marker) // called from router.html
1459 {
1460 if(marker==1)
1461 {
1462 for(var m=1;m<vismarkers;m++)
1463 markerSwap(m,m+1);
1464 }
1465 else
1466 markerSwap(marker,marker-1);
1467 }
1468
1469
1470 //
1471 // Move this marker down.
1472 //
1473
1474 function markerMoveDown(marker) // called from router.html
1475 {
1476 if(marker==vismarkers)
1477 {
1478 for(var m=vismarkers;m>1;m--)
1479 markerSwap(m,m-1);
1480 }
1481 else
1482 markerSwap(marker,marker+1);
1483 }
1484
1485
1486 //
1487 // Copy a marker from one place to another.
1488 //
1489
1490 function markerCopy(marker1,marker2)
1491 {
1492 for(var element in routino.point[marker2])
1493 routino.point[marker1][element]=routino.point[marker2][element];
1494
1495 document.getElementById("search" + marker1).style.display=document.getElementById("search" + marker2).style.display;
1496
1497 document.getElementById("coords" + marker1).style.display=document.getElementById("coords" + marker2).style.display;
1498
1499 document.forms["form"].elements["search" + marker1].value=document.forms["form"].elements["search" + marker2].value;
1500
1501 formSetCoords(marker1,routino.point[marker1].lon,routino.point[marker1].lat);
1502
1503 markerAddRemoveMap(marker1,routino.point[marker1].active);
1504 }
1505
1506
1507 //
1508 // Swap a pair of markers.
1509 //
1510
1511 function markerSwap(marker1,marker2)
1512 {
1513 for(var element in routino.point[marker2])
1514 {
1515 var temp=routino.point[marker1][element];
1516 routino.point[marker1][element]=routino.point[marker2][element];
1517 routino.point[marker2][element]=temp;
1518 }
1519
1520 var search_display=document.getElementById("search" + marker1).style.display;
1521 document.getElementById("search" + marker1).style.display=document.getElementById("search" + marker2).style.display;
1522 document.getElementById("search" + marker2).style.display=search_display;
1523
1524 var coords_display=document.getElementById("coords" + marker1).style.display;
1525 document.getElementById("coords" + marker1).style.display=document.getElementById("coords" + marker2).style.display;
1526 document.getElementById("coords" + marker2).style.display=coords_display;
1527
1528 var search_value=document.forms["form"].elements["search" + marker1].value;
1529 document.forms["form"].elements["search" + marker1].value=document.forms["form"].elements["search" + marker2].value;
1530 document.forms["form"].elements["search" + marker2].value=search_value;
1531
1532 formSetCoords(marker1,routino.point[marker1].lon,routino.point[marker1].lat);
1533 formSetCoords(marker2,routino.point[marker2].lon,routino.point[marker2].lat);
1534
1535 markerAddRemoveMap(marker1,routino.point[marker1].active);
1536 markerAddRemoveMap(marker2,routino.point[marker2].active);
1537 }
1538
1539
1540 //
1541 // Reverse the markers.
1542 //
1543
1544 function markersReverse() // called from router.html
1545 {
1546 for(var marker=1;marker<=vismarkers/2;marker++)
1547 markerSwap(marker,vismarkers+1-marker);
1548
1549 markersmoved=true;
1550
1551 updateURLs();
1552 }
1553
1554
1555 //
1556 // Close the loop.
1557 //
1558
1559 function markersLoop() // called from router.html
1560 {
1561 if(vismarkers==mapprops.maxmarkers)
1562 return false;
1563
1564 if(routino.point[vismarkers].lon==routino.point[1].lon && routino.point[vismarkers].lat==routino.point[1].lat)
1565 {
1566 if(routino.point[vismarkers].active)
1567 return false;
1568 else
1569 {
1570 markerToggleMap(vismarkers);
1571 return true;
1572 }
1573 }
1574
1575 if(routino.point[vismarkers].used)
1576 markerAddForm(++vismarkers);
1577
1578 markerCopy(vismarkers,1);
1579
1580 markersmoved=true;
1581
1582 updateURLs();
1583
1584 updateSearchButtons();
1585 }
1586
1587
1588 //
1589 // Display the form for a marker
1590 //
1591
1592 function markerAddForm(marker)
1593 {
1594 document.getElementById("waypoint" + marker).style.display="";
1595 }
1596
1597
1598 //
1599 // Hide the form for a marker
1600 //
1601
1602 function markerRemoveForm(marker)
1603 {
1604 document.getElementById("waypoint" + marker).style.display="none";
1605
1606 markerClearForm(marker);
1607 }
1608
1609
1610 //
1611 // Clear the form for a marker
1612 //
1613
1614 function markerClearForm(marker)
1615 {
1616 markerRemoveMap(marker);
1617 markerCoords(marker);
1618
1619 formSetCoords(marker,"","");
1620 formSetSearch(marker,"");
1621
1622 updateIcon(marker);
1623
1624 routino.point[marker].used=false;
1625 routino.point[marker].home=false;
1626 routino.point[marker].active=false;
1627 }
1628
1629
1630 ////////////////////////////////////////////////////////////////////////////////
1631 //////////////////////////// Route results handling ////////////////////////////
1632 ////////////////////////////////////////////////////////////////////////////////
1633
1634 var route_light_colours={shortest: "#60C060", quickest: "#6060C0"};
1635 var route_dark_colours ={shortest: "#408040", quickest: "#404080"};
1636
1637 var highlights={shortest: null, quickest: null};
1638 var popups={shortest: null, quickest: null};
1639 var routepoints={shortest: {}, quickest: {}};
1640
1641 //
1642 // Highlight a specific item in the route
1643 //
1644
1645 function highlight(type,line,action)
1646 {
1647 if(action == "clear")
1648 {
1649 layerVectors.removeLayer(highlights[type]);
1650
1651 drawPopup(type,null);
1652 }
1653 else if(action == "zoom")
1654 {
1655 var lonlat = L.latLng(routepoints[type][line].lat,routepoints[type][line].lon);
1656
1657 map.setView(lonlat,mapprops.zoomin-2);
1658 }
1659 else
1660 {
1661 // Marker
1662
1663 var lonlat = L.latLng(routepoints[type][line].lat,routepoints[type][line].lon);
1664
1665 highlights[type].setLatLng(lonlat);
1666
1667 layerVectors.addLayer(highlights[type]);
1668
1669 // Popup
1670
1671 drawPopup(type,"<table>" + routepoints[type][line].html + "</table>");
1672 }
1673
1674 highlights[type].redraw();
1675 }
1676
1677
1678 //
1679 // Create a popup - independent of map because want it fixed on screen not fixed on map.
1680 //
1681
1682 function createPopup(type)
1683 {
1684 var popup=document.createElement("div");
1685
1686 popup.className = "popup";
1687
1688 popup.innerHTML = "<span></span>";
1689
1690 popup.style.display = "none";
1691
1692 popup.style.position = "fixed";
1693 popup.style.top = "-4000px";
1694 popup.style.left = "-4000px";
1695 popup.style.zIndex = "100";
1696
1697 popup.style.padding = "5px";
1698
1699 popup.style.opacity=0.85;
1700 popup.style.backgroundColor=route_light_colours[type];
1701 popup.style.border="4px solid " + route_dark_colours[type];
1702
1703 document.body.appendChild(popup);
1704
1705 return(popup);
1706 }
1707
1708
1709 //
1710 // Draw a popup - independent of map because want it fixed on screen not fixed on map.
1711 //
1712
1713 function drawPopup(type,html)
1714 {
1715 var popup=popups[type];
1716
1717 if(html===null)
1718 {
1719 popup.style.display="none";
1720 return;
1721 }
1722
1723 if(popup.style.display=="none")
1724 {
1725 var map_div=document.getElementById("map");
1726
1727 popup.style.left =map_div.offsetParent.offsetLeft+map_div.offsetLeft+60 + "px";
1728 popup.style.top = map_div.offsetTop +30 + "px";
1729 popup.style.width =map_div.clientWidth-120 + "px";
1730
1731 popup.style.display="";
1732 }
1733
1734 var close="<span style='float: right; cursor: pointer;' onclick='highlight(\""+type+"\",-1,\"clear\")'>X</span>";
1735
1736 popup.innerHTML=close+html;
1737 }
1738
1739
1740 //
1741 // Remove a GPX trace
1742 //
1743
1744 function removeGPXTrace(type)
1745 {
1746 map.removeLayer(layerGPX[type]);
1747 layerGPX[type]=null;
1748
1749 displayStatus(type,"no_info");
1750
1751 document.getElementById(type + "_links").style.display = "none";
1752
1753 document.getElementById(type + "_route").innerHTML = "";
1754
1755 hideshow_hide(type);
1756 }
1757
1758
1759 ////////////////////////////////////////////////////////////////////////////////
1760 /////////////////////////////// Server handling ////////////////////////////////
1761 ////////////////////////////////////////////////////////////////////////////////
1762
1763 //
1764 // Define an AJAX request object
1765 //
1766
1767 function ajaxGET(url,success,failure,state)
1768 {
1769 var ajaxRequest=new XMLHttpRequest();
1770
1771 function ajaxGOT(options) {
1772 if(this.readyState==4)
1773 if(this.status==200)
1774 { if(typeof(options.success)=="function") options.success(this,options.state); }
1775 else
1776 { if(typeof(options.failure)=="function") options.failure(this,options.state); }
1777 }
1778
1779 ajaxRequest.onreadystatechange = function(){ ajaxGOT.call(ajaxRequest,{success: success, failure: failure, state: state}); };
1780 ajaxRequest.open("GET", url, true);
1781 ajaxRequest.send(null);
1782 }
1783
1784
1785 //
1786 // Display data statistics
1787 //
1788
1789 function displayStatistics() // called from router.html
1790 {
1791 // Use AJAX to get the statistics
1792
1793 ajaxGET("statistics.cgi", runStatisticsSuccess);
1794 }
1795
1796
1797 //
1798 // Success in running data statistics generation.
1799 //
1800
1801 function runStatisticsSuccess(response)
1802 {
1803 document.getElementById("statistics_data").innerHTML="<pre>" + response.responseText + "</pre>";
1804 document.getElementById("statistics_link").style.display="none";
1805 }
1806
1807
1808 //
1809 // Submit form - perform the routing
1810 //
1811
1812 function findRoute(type) // called from router.html
1813 {
1814 tab_select("results");
1815
1816 hideshow_hide("help_options");
1817 hideshow_hide("shortest");
1818 hideshow_hide("quickest");
1819
1820 displayStatus("result","running");
1821
1822 var url="router.cgi" + "?" + buildURLArguments(true) + ";type=" + type;
1823
1824 // Destroy the existing layer(s)
1825
1826 highlight("shortest",-1,"clear");
1827 highlight("quickest",-1,"clear");
1828
1829 if(markersmoved || paramschanged)
1830 {
1831 if(layerGPX.shortest!==null)
1832 removeGPXTrace("shortest");
1833 if(layerGPX.quickest!==null)
1834 removeGPXTrace("quickest");
1835 markersmoved=false;
1836 paramschanged=false;
1837 }
1838 else if(layerGPX[type]!==null)
1839 removeGPXTrace(type);
1840
1841 // Use AJAX to run the router
1842
1843 routing_type=type;
1844
1845 ajaxGET(url, runRouterSuccess, runRouterFailure);
1846 }
1847
1848
1849 //
1850 // Success in running router.
1851 //
1852
1853 function runRouterSuccess(response)
1854 {
1855 var lines=response.responseText.split("\n");
1856
1857 var uuid=lines[0];
1858 var success=lines[1];
1859
1860 var link;
1861
1862 // Update the status message
1863
1864 if(success=="ERROR")
1865 {
1866 displayStatus("result","error");
1867 hideshow_show("help_route");
1868
1869 link=document.getElementById("router_log_error");
1870 link.href="results.cgi?uuid=" + uuid + ";type=router;format=log";
1871
1872 return;
1873 }
1874 else
1875 {
1876 displayStatus("result","complete");
1877 hideshow_hide("help_route");
1878
1879 link=document.getElementById("router_log_complete");
1880 link.href="results.cgi?uuid=" + uuid + ";type=router;format=log";
1881 }
1882
1883 // Update the routing result message
1884
1885 link=document.getElementById(routing_type + "_html");
1886 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";
1887
1888 link=document.getElementById(routing_type + "_gpx_track");
1889 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";
1890
1891 link=document.getElementById(routing_type + "_gpx_route");
1892 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-route";
1893
1894 link=document.getElementById(routing_type + "_text_all");
1895 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text-all";
1896
1897 link=document.getElementById(routing_type + "_text");
1898 link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text";
1899
1900 document.getElementById(routing_type + "_links").style.display = "";
1901
1902 // Add a GPX layer
1903
1904 var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";
1905
1906 ajaxGET(url, runGPXSuccess);
1907
1908 hideshow_show(routing_type);
1909
1910 displayResult(routing_type,uuid);
1911 }
1912
1913
1914 //
1915 // Success in getting GPX.
1916 //
1917
1918 function runGPXSuccess(response)
1919 {
1920 var lines=response.responseText.split("\n");
1921
1922 var coords=[];
1923 var segment=-1;
1924
1925 for(var line=0;line<lines.length;line++)
1926 {
1927 if(lines[line].match(/^<trkseg>/))
1928 {
1929 segment++;
1930 coords[segment]=[];
1931 }
1932 if(lines[line].match(/^<trkpt lat="([-0-9.]+)" lon="([-0-9.]+)"/))
1933 {
1934 var lat=RegExp.$1;
1935 var lon=RegExp.$2;
1936
1937 coords[segment].push(L.latLng(lat,lon));
1938 }
1939 }
1940
1941 var colour;
1942
1943 if(routing_type == "shortest")
1944 colour="#00FF00";
1945 else
1946 colour="#0000FF";
1947
1948 layerGPX[routing_type] = L.multiPolyline(coords,{weight: 3, stroke: true, color: colour, opacity: 1.0,
1949 fill: false});
1950
1951 map.addLayer(layerGPX[routing_type]);
1952 }
1953
1954
1955 //
1956 // Failure in running router.
1957 //
1958
1959 function runRouterFailure(response)
1960 {
1961 displayStatus("result","failed");
1962 }
1963
1964
1965 //
1966 // Display the status
1967 //
1968
1969 function displayStatus(type,subtype,content)
1970 {
1971 var child=document.getElementById(type + "_status").firstChild;
1972
1973 do
1974 {
1975 if(child.id !== undefined)
1976 child.style.display="none";
1977
1978 child=child.nextSibling;
1979 }
1980 while(child !== null);
1981
1982 var chosen_status=document.getElementById(type + "_status_" + subtype);
1983
1984 chosen_status.style.display="";
1985
1986 if(content !== undefined)
1987 chosen_status.innerHTML=content;
1988 }
1989
1990
1991 //
1992 // Display the route
1993 //
1994
1995 function displayResult(type,uuid)
1996 {
1997 routing_type = type;
1998
1999 // Add the route
2000
2001 var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";
2002
2003 // Use AJAX to get the route
2004
2005 ajaxGET(url, getRouteSuccess, getRouteFailure);
2006 }
2007
2008
2009 //
2010 // Success in getting route.
2011 //
2012
2013 function getRouteSuccess(response)
2014 {
2015 var lines=response.responseText.split("\n");
2016
2017 routepoints[routing_type]=[];
2018
2019 var points=routepoints[routing_type];
2020
2021 var table=0;
2022 var point=0;
2023 var total_table,total_word;
2024
2025 for(var line=0;line<lines.length;line++)
2026 {
2027 var thisline=lines[line];
2028
2029 if(table===0)
2030 {
2031 if(thisline.match("<table>"))
2032 table=1;
2033 else
2034 continue;
2035 }
2036
2037 if(thisline.match("</table>"))
2038 break;
2039
2040 if(thisline.match("<tr class='([a-z])'>"))
2041 {
2042 var rowtype=RegExp.$1;
2043
2044 if(rowtype=="c")
2045 {
2046 thisline.match(": *([-0-9.]+) *([-0-9.]+)");
2047 points[point]={lat: Number(RegExp.$1), lon: Number(RegExp.$2), html: "", highway: "", distance: "", total: ""};
2048
2049 point++;
2050 }
2051 else if(rowtype=="n")
2052 {
2053 points[point-1].html += thisline;
2054 }
2055 else if(rowtype=="s")
2056 {
2057 thisline.match("<span class='h'>([^<]+)</span>");
2058 points[point-1].highway = RegExp.$1;
2059
2060 thisline.match("<span class='d'>([^<]+)</span>");
2061 points[point-1].distance = RegExp.$1;
2062
2063 thisline.match("(<span class='j'>[^<]+</span>)");
2064 points[point-1].total = RegExp.$1;
2065
2066 thisline.match("^(.*).<span class='j'>");
2067
2068 points[point-1].html += RegExp.$1;
2069 }
2070 else if(rowtype=="t")
2071 {
2072 points[point-1].html += thisline;
2073
2074 thisline.match("<span class='j'>([^<]+)</span>");
2075 points[point-1].total = RegExp.$1;
2076
2077 thisline.match("<td>(.*)");
2078 points[point-1].highway = RegExp.$1;
2079 }
2080 }
2081 }
2082
2083 displayStatus(routing_type,"info",points[point-1].total.bold());
2084
2085 var result="<table onmouseout='highlight(\"" + routing_type + "\",-1,\"clear\")'>";
2086
2087 for(var p=0;p<point;p++)
2088 {
2089 if(p!=point-1)
2090 points[p].html += "<tr><td>" + points[p].total;
2091
2092 result=result + "<tr onmouseover='highlight(\"" + routing_type + "\"," + p + ",\"show\")'>" +
2093 "<td onclick='highlight(\"" + routing_type + "\"," + p + ",\"zoom\")'" +
2094 " class='distance' title='" + points[p].distance + "'>#" + (p+1) +
2095 "<td class='highway'>" + points[p].highway;
2096 }
2097
2098 result=result + "</table>";
2099
2100 document.getElementById(routing_type + "_route").innerHTML=result;
2101 }
2102
2103
2104 //
2105 // Failure in getting route.
2106 //
2107
2108 function getRouteFailure(response)
2109 {
2110 document.getElementById(routing_type + "_route").innerHTML = "";
2111 }
2112
2113
2114 //
2115 // Perform a search
2116 //
2117
2118 function DoSearch(marker)
2119 {
2120 // Use AJAX to get the search result
2121
2122 var search=routino.point[marker].search;
2123
2124 var mapbounds=map.getBounds();
2125
2126 var url="search.cgi";
2127
2128 url=url + "?marker=" + marker;
2129 url=url + ";lonmin=" + format5f(mapbounds.getWest());
2130 url=url + ";latmin=" + format5f(mapbounds.getSouth());
2131 url=url + ";lonmax=" + format5f(mapbounds.getEast());
2132 url=url + ";latmax=" + format5f(mapbounds.getNorth());
2133 url=url + ";search=" + encodeURIComponent(search);
2134
2135 ajaxGET(url,runSearchSuccess);
2136 }
2137
2138
2139 var searchresults=[];
2140
2141 //
2142 // Success in running search.
2143 //
2144
2145 function runSearchSuccess(response)
2146 {
2147 var lines=response.responseText.split("\n");
2148
2149 var marker=lines[0];
2150 var cpuinfo=lines[1]; // not used
2151 var message=lines[2];
2152
2153 if(message !== "")
2154 {
2155 alert(message);
2156 return;
2157 }
2158
2159 searchresults[marker]=[];
2160
2161 for(var line=3;line<lines.length;line++)
2162 {
2163 var thisline=lines[line];
2164
2165 if(thisline==="")
2166 break;
2167
2168 thisline.match("([-.0-9]+) ([-.0-9]+) (.*)");
2169
2170 searchresults[marker][searchresults[marker].length]={lat: Number(RegExp.$1), lon: Number(RegExp.$2), name: RegExp.$3};
2171 }
2172
2173 if(searchresults[marker].length==1)
2174 {
2175 formSetSearch(marker,searchresults[marker][0].name);
2176 formSetCoords(marker,searchresults[marker][0].lon,searchresults[marker][0].lat);
2177 markerAddMap(marker);
2178 }
2179 else
2180 {
2181 var results=document.getElementById("searchresults" + marker);
2182
2183 var innerHTML="<td colspan=\"3\">";
2184
2185 for(var n=0;n<searchresults[marker].length;n++)
2186 {
2187 if(n>0)
2188 innerHTML+="<br>";
2189
2190 innerHTML+="<a href=\"#\" onclick=\"choseSearchResult(" + marker + "," + n + ")\">" +
2191 searchresults[marker][n].name +
2192 "</a>";
2193 }
2194
2195 results.innerHTML=innerHTML;
2196
2197 results.style.display="";
2198 }
2199 }
2200
2201
2202 //
2203 // Display search results.
2204 //
2205
2206 function choseSearchResult(marker,n)
2207 {
2208 if(n>=0)
2209 {
2210 formSetSearch(marker,searchresults[marker][n].name);
2211 formSetCoords(marker,searchresults[marker][n].lon,searchresults[marker][n].lat);
2212 markerAddMap(marker);
2213 }
2214 }
2215
2216
2217 //
2218 // Clear search results.
2219 //
2220
2221 function clearSearchResult(marker)
2222 {
2223 document.getElementById("searchresults" + marker).style.display="none";
2224 }