Imported Upstream version 1.5.1
[routino] / web / www / routino / router.js
1 //
2 // Routino router web page Javascript
3 //
4 // Part of the Routino routing software.
5 //
6 // This file Copyright 2008-2010 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 /////////////////////////// Routino default profile ////////////////////////////
24 ////////////////////////////////////////////////////////////////////////////////
25
26 var routino={ // contains all default Routino options (generated using "--help-profile-json").
27
28   // Default transport type
29   transport: 'motorcar',
30
31   // Transport types
32   transports: { foot: 1, horse: 2, wheelchair: 3, bicycle: 4, moped: 5, motorbike: 6, motorcar: 7, goods: 8, hgv: 9, psv: 10 },
33
34   // Highway types
35   highways: { motorway: 1, trunk: 2, primary: 3, secondary: 4, tertiary: 5, unclassified: 6, residential: 7, service: 8, track: 9, cycleway: 10, path: 11, steps: 12, ferry: 13 },
36
37   // Property types
38   properties: { paved: 1, multilane: 2, bridge: 3, tunnel: 4, footroute: 5, bicycleroute: 6 },
39
40   // Restriction types
41   restrictions: { oneway: 1, weight: 2, height: 3, width: 4, length: 5 },
42
43   // Allowed highways
44   profile_highway: {
45         motorway: { foot:   0, horse:   0, wheelchair:   0, bicycle:   0, moped:   0, motorbike: 100, motorcar: 100, goods: 100, hgv: 100, psv: 100 },
46            trunk: { foot:  40, horse:  25, wheelchair:  40, bicycle:  30, moped:  90, motorbike: 100, motorcar: 100, goods: 100, hgv: 100, psv: 100 },
47          primary: { foot:  50, horse:  50, wheelchair:  50, bicycle:  70, moped: 100, motorbike:  90, motorcar:  90, goods:  90, hgv:  90, psv:  90 },
48        secondary: { foot:  60, horse:  50, wheelchair:  60, bicycle:  80, moped:  90, motorbike:  80, motorcar:  80, goods:  80, hgv:  80, psv:  80 },
49         tertiary: { foot:  70, horse:  75, wheelchair:  70, bicycle:  90, moped:  80, motorbike:  70, motorcar:  70, goods:  70, hgv:  70, psv:  70 },
50     unclassified: { foot:  80, horse:  75, wheelchair:  80, bicycle:  90, moped:  70, motorbike:  60, motorcar:  60, goods:  60, hgv:  60, psv:  60 },
51      residential: { foot:  90, horse:  75, wheelchair:  90, bicycle:  90, moped:  60, motorbike:  50, motorcar:  50, goods:  50, hgv:  50, psv:  50 },
52          service: { foot:  90, horse:  75, wheelchair:  90, bicycle:  90, moped:  80, motorbike:  80, motorcar:  80, goods:  80, hgv:  80, psv:  80 },
53            track: { foot:  95, horse: 100, wheelchair:  95, bicycle:  90, moped:   0, motorbike:   0, motorcar:   0, goods:   0, hgv:   0, psv:   0 },
54         cycleway: { foot:  95, horse:  90, wheelchair:  95, bicycle: 100, moped:   0, motorbike:   0, motorcar:   0, goods:   0, hgv:   0, psv:   0 },
55             path: { foot: 100, horse: 100, wheelchair: 100, bicycle:  90, moped:   0, motorbike:   0, motorcar:   0, goods:   0, hgv:   0, psv:   0 },
56            steps: { foot:  80, horse:   0, wheelchair:   0, bicycle:   0, moped:   0, motorbike:   0, motorcar:   0, goods:   0, hgv:   0, psv:   0 },
57            ferry: { foot:  20, horse:  20, wheelchair:  20, bicycle:  20, moped:  20, motorbike:  20, motorcar:  20, goods:  20, hgv:  20, psv:  20 }
58      },
59
60   // Speed limits
61   profile_speed: {
62         motorway: { foot:   0, horse:   0, wheelchair:   0, bicycle:   0, moped:  48, motorbike: 112, motorcar: 112, goods:  96, hgv:  89, psv:  89 },
63            trunk: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:  48, motorbike:  96, motorcar:  96, goods:  96, hgv:  80, psv:  80 },
64          primary: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:  48, motorbike:  96, motorcar:  96, goods:  96, hgv:  80, psv:  80 },
65        secondary: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:  48, motorbike:  88, motorcar:  88, goods:  88, hgv:  80, psv:  80 },
66         tertiary: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:  48, motorbike:  80, motorcar:  80, goods:  80, hgv:  80, psv:  80 },
67     unclassified: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:  48, motorbike:  64, motorcar:  64, goods:  64, hgv:  64, psv:  64 },
68      residential: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:  48, motorbike:  48, motorcar:  48, goods:  48, hgv:  48, psv:  48 },
69          service: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:  32, motorbike:  32, motorcar:  32, goods:  32, hgv:  32, psv:  32 },
70            track: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:  16, motorbike:  16, motorcar:  16, goods:  16, hgv:  16, psv:  16 },
71         cycleway: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:   0, motorbike:   0, motorcar:   0, goods:   0, hgv:   0, psv:   0 },
72             path: { foot:   4, horse:   8, wheelchair:   4, bicycle:  20, moped:   0, motorbike:   0, motorcar:   0, goods:   0, hgv:   0, psv:   0 },
73            steps: { foot:   4, horse:   0, wheelchair:   4, bicycle:   0, moped:   0, motorbike:   0, motorcar:   0, goods:   0, hgv:   0, psv:   0 },
74            ferry: { foot:  10, horse:  10, wheelchair:  10, bicycle:  10, moped:  10, motorbike:  10, motorcar:  10, goods:  10, hgv:  10, psv:  10 }
75      },
76
77   // Highway properties
78   profile_property: {
79            paved: { foot:  50, horse:  20, wheelchair:  90, bicycle:  50, moped: 100, motorbike: 100, motorcar: 100, goods: 100, hgv: 100, psv: 100 },
80        multilane: { foot:  25, horse:  25, wheelchair:  25, bicycle:  25, moped:  35, motorbike:  60, motorcar:  60, goods:  60, hgv:  60, psv:  60 },
81           bridge: { foot:  50, horse:  50, wheelchair:  50, bicycle:  50, moped:  50, motorbike:  50, motorcar:  50, goods:  50, hgv:  50, psv:  50 },
82           tunnel: { foot:  50, horse:  50, wheelchair:  50, bicycle:  50, moped:  50, motorbike:  50, motorcar:  50, goods:  50, hgv:  50, psv:  50 },
83        footroute: { foot:  55, horse:  50, wheelchair:  55, bicycle:  50, moped:  50, motorbike:  50, motorcar:  45, goods:  45, hgv:  45, psv:  45 },
84     bicycleroute: { foot:  55, horse:  50, wheelchair:  55, bicycle:  60, moped:  50, motorbike:  50, motorcar:  45, goods:  45, hgv:  45, psv:  45 }
85      },
86
87   // Restrictions
88   profile_restrictions: {
89           oneway: { foot:    0, horse:    1, wheelchair:    0, bicycle:    1, moped:    1, motorbike:    1, motorcar:    1, goods:    1, hgv:    1, psv:    1 },
90           weight: { foot:  0.0, horse:  0.0, wheelchair:  0.0, bicycle:  0.0, moped:  0.0, motorbike:  0.0, motorcar:  0.0, goods:  5.0, hgv: 10.0, psv: 15.0 },
91           height: { foot:  0.0, horse:  0.0, wheelchair:  0.0, bicycle:  0.0, moped:  0.0, motorbike:  0.0, motorcar:  0.0, goods:  2.5, hgv:  3.0, psv:  3.0 },
92            width: { foot:  0.0, horse:  0.0, wheelchair:  0.0, bicycle:  0.0, moped:  0.0, motorbike:  0.0, motorcar:  0.0, goods:  2.0, hgv:  2.5, psv:  2.5 },
93           length: { foot:  0.0, horse:  0.0, wheelchair:  0.0, bicycle:  0.0, moped:  0.0, motorbike:  0.0, motorcar:  0.0, goods:  5.0, hgv:  6.0, psv:  6.0 }
94      }
95
96 }; // end of routino variable
97
98 // Make a deep copy of the routino profile.
99
100 var routino_default={};
101 for(var l1 in routino)
102    if(typeof(routino[l1])!='object')
103       routino_default[l1]=routino[l1];
104    else
105      {
106       routino_default[l1]={};
107       for(var l2 in routino[l1])
108          if(typeof(routino[l1][l2])!='object')
109             routino_default[l1][l2]=Number(routino[l1][l2]);
110          else
111            {
112             routino_default[l1][l2]={};
113             for(var l3 in routino[l1][l2])
114                routino_default[l1][l2][l3]=Number(routino[l1][l2][l3]);
115            }
116      }
117
118
119 ////////////////////////////////////////////////////////////////////////////////
120 //////////////////////////////// Form handling /////////////////////////////////
121 ////////////////////////////////////////////////////////////////////////////////
122
123 //
124 // Form initialisation - fill in the uninitialised parts
125 //
126
127 function form_init()
128 {
129  // Update the routino variable with the URL settings (from the HTML).
130
131  for(var lang=0;lang< document.forms["form"].elements["language"].length;lang++)
132     if(document.forms["form"].elements["language"][lang].checked)
133        formSetLanguage(document.forms["form"].elements["language"][lang].value);
134
135  var transport=null;
136
137  for(var key in routino.transports)
138     if(document.forms["form"].elements["transport"][routino.transports[key]-1].checked)
139        transport=key;
140
141  if(transport==null)
142     formSetTransport(routino.transport);
143  else
144    {
145     routino.transport=transport;
146
147     for(var key in routino.profile_highway)
148       {
149        if(document.forms["form"].elements["highway-" + key].value=="")
150           document.forms["form"].elements["highway-" + key].value=routino.profile_highway[key][routino.transport];
151        else
152           formSetHighway(key);
153       }
154
155     for(var key in routino.profile_speed)
156       {
157        if(document.forms["form"].elements["speed-" + key].value=="")
158           document.forms["form"].elements["speed-" + key].value=routino.profile_speed[key][routino.transport];
159        else
160           formSetSpeed(key);
161       }
162
163     for(var key in routino.profile_property)
164       {
165        if(document.forms["form"].elements["property-" + key].value=="")
166           document.forms["form"].elements["property-" + key].value=routino.profile_property[key][routino.transport];
167        else
168           formSetProperty(key);
169       }
170
171     for(var key in routino.restrictions)
172       {
173        if(key=="oneway")
174           formSetRestriction(key);
175        else
176          {
177           if(document.forms["form"].elements["restrict-" + key].value=="")
178              document.forms["form"].elements["restrict-" + key].value=routino.profile_restrictions[key][routino.transport];
179           else
180              formSetRestriction(key);
181          }
182       }
183    }
184
185  // Delete the extra empty waypoints
186
187  var filled=0;
188
189  for(var marker=nmarkers;marker>=1;marker--)
190    {
191     var lon=document.forms["form"].elements["lon" + marker].value;
192     var lat=document.forms["form"].elements["lat" + marker].value;
193
194     if(lon != "" && lat != "")
195       {
196        filled++;
197        markerAddMap(marker);
198       }
199     else if(filled==0)
200        markerRemove(marker);
201    }
202
203  // Get the home location cookie and compare to each waypoint
204
205  var cookies=document.cookie.split('; ');
206
207  for(var cookie=0;cookie<cookies.length;cookie++)
208     if(cookies[cookie].substr(0,"Routino-home".length)=="Routino-home")
209       {
210        var data=cookies[cookie].split(/[=:;]/);
211
212        if(data[1]=="lon") homelon=Number(data[2]);
213        if(data[3]=="lat") homelat=Number(data[4]);
214       }
215
216  if(homelon!=null && homelat!=null)
217    {
218     for(var marker=nmarkers;marker>=1;marker--)
219       {
220        var lon=document.forms["form"].elements["lon" + marker].value;
221        var lat=document.forms["form"].elements["lat" + marker].value;
222
223        if(lon==homelon && lat==homelat)
224           updateIcon(marker);
225       }
226
227     // If the first location is empty and the cookie is set then fill it.
228
229     if(document.forms["form"].elements["lon1"].value=="" && document.forms["form"].elements["lat1"].value=="")
230       {
231        document.forms["form"].elements["lon1"].value=homelon;
232        document.forms["form"].elements["lat1"].value=homelat;
233
234        markerAddMap(1);
235       }
236    }
237
238  updateCustomURL();
239 }
240
241
242 //
243 // Change of language in the form
244 //
245
246 function formSetLanguage(type)
247 {
248  routino.language=type;
249
250  updateCustomURL();
251 }
252
253
254 //
255 // Change of transport in the form
256 //
257
258 function formSetTransport(type)
259 {
260  routino.transport=type;
261
262  for(var key in routino.transports)
263     document.forms["form"].elements["transport"][routino.transports[key]-1].checked=(key==routino.transport);
264
265  for(var key in routino.profile_highway)
266     document.forms["form"].elements["highway-" + key].value=routino.profile_highway[key][routino.transport];
267
268  for(var key in routino.profile_speed)
269     document.forms["form"].elements["speed-" + key].value=routino.profile_speed[key][routino.transport];
270
271  for(var key in routino.profile_property)
272     document.forms["form"].elements["property-" + key].value=routino.profile_property[key][routino.transport];
273
274  for(var key in routino.restrictions)
275    {
276     if(key=="oneway")
277        document.forms["form"].elements["restrict-" + key].checked=routino.profile_restrictions[key][routino.transport];
278     else
279        document.forms["form"].elements["restrict-" + key].value=routino.profile_restrictions[key][routino.transport];
280    }
281
282  paramschanged=true;
283
284  updateCustomURL();
285 }
286
287
288 //
289 // Change of highway in the form
290 //
291
292 function formSetHighway(type)
293 {
294  routino.profile_highway[type][routino.transport]=document.forms["form"].elements["highway-" + type].value;
295
296  paramschanged=true;
297
298  updateCustomURL();
299 }
300
301
302 //
303 // Change of Speed in the form
304 //
305
306 function formSetSpeed(type)
307 {
308  routino.profile_speed[type][routino.transport]=document.forms["form"].elements["speed-" + type].value;
309
310  paramschanged=true;
311
312  updateCustomURL();
313 }
314
315
316 //
317 // Change of Property in the form
318 //
319
320 function formSetProperty(type)
321 {
322  routino.profile_property[type][routino.transport]=document.forms["form"].elements["property-" + type].value;
323
324  paramschanged=true;
325
326  updateCustomURL();
327 }
328
329
330 //
331 // Change of oneway rule in the form
332 //
333
334 function formSetRestriction(type)
335 {
336  if(type=="oneway")
337     routino.profile_restrictions[type][routino.transport]=document.forms["form"].elements["restrict-" + type].checked;
338  else
339     routino.profile_restrictions[type][routino.transport]=document.forms["form"].elements["restrict-" + type].value;
340
341  paramschanged=true;
342
343  updateCustomURL();
344 }
345
346
347 //
348 // Set the feature coordinates from the form when the form changes.
349 //
350
351 function formSetCoords(marker)
352 {
353  var lonlat=map.getCenter().clone();
354
355  lonlat.transform(map.getProjectionObject(),epsg4326);
356
357  var lon=document.forms["form"].elements["lon" + marker].value;
358  var lat=document.forms["form"].elements["lat" + marker].value;
359
360  if(lon!="")
361    {
362     if(lon<-180) lon=-180;
363     if(lon>+180) lon=+180;
364     lonlat.lon=lon;
365    }
366
367  if(lat!="")
368    {
369     if(lat<-90 ) lat=-90 ;
370     if(lat>+90 ) lat=+90 ;
371     lonlat.lat=lat;
372    }
373
374  var point = lonlat.clone();
375
376  point.transform(epsg4326,map.getProjectionObject());
377
378  markers[marker].move(point);
379
380  markersmoved=true;
381
382  coordsSetForm(marker);
383 }
384
385
386 //
387 // Set the feature coordinates in the form.
388 //
389
390 function coordsSetForm(marker)
391 {
392  var lonlat = new OpenLayers.LonLat(markers[marker].geometry.x, markers[marker].geometry.y);
393  lonlat.transform(map.getProjectionObject(),epsg4326);
394
395  var lon=format5f(lonlat.lon);
396  var lat=format5f(lonlat.lat);
397
398  document.forms["form"].elements["lon" + marker].value=lon;
399  document.forms["form"].elements["lat" + marker].value=lat;
400
401  updateIcon(marker);
402
403  updateCustomURL();
404 }
405
406
407 //
408 // Format a number in printf("%.5f") format.
409 //
410
411 function format5f(number)
412 {
413  var newnumber=Math.floor(number*100000+0.5);
414  var delta=0;
415
416  if(newnumber>=0 && newnumber<100000) delta= 100000;
417  if(newnumber<0 && newnumber>-100000) delta=-100000;
418
419  var string=String(newnumber+delta);
420
421  var intpart =string.substring(0,string.length-5);
422  var fracpart=string.substring(string.length-5,string.length);
423
424  if(delta>0) intpart="0";
425  if(delta<0) intpart="-0";
426
427  return(intpart + "." + fracpart);
428 }
429
430
431 //
432 // Build a set of URL arguments
433 //
434
435 function buildURLArguments(all)
436 {
437  var url="?";
438
439  url=url + "transport=" + routino.transport;
440
441  for(var marker=1;marker<=vismarkers;marker++)
442     if(markers[marker].style.display == "" || all)
443       {
444        url=url + ";lon" + marker + "=" + document.forms["form"].elements["lon" + marker].value;
445        url=url + ";lat" + marker + "=" + document.forms["form"].elements["lat" + marker].value;
446       }
447
448  for(var key in routino.profile_highway)
449     if(routino.profile_highway[key][routino.transport]!=routino_default.profile_highway[key][routino.transport])
450        url=url + ";highway-" + key + "=" + routino.profile_highway[key][routino.transport];
451
452  for(var key in routino.profile_speed)
453     if(routino.profile_speed[key][routino.transport]!=routino_default.profile_speed[key][routino.transport])
454        url=url + ";speed-" + key + "=" + routino.profile_speed[key][routino.transport];
455
456  for(var key in routino.profile_property)
457     if(routino.profile_property[key][routino.transport]!=routino_default.profile_property[key][routino.transport])
458        url=url + ";property-" + key + "=" + routino.profile_property[key][routino.transport];
459
460  for(var key in routino.restrictions)
461     if(routino.profile_restrictions[key][routino.transport]!=routino_default.profile_restrictions[key][routino.transport])
462        url=url + ";" + key + "=" + routino.profile_restrictions[key][routino.transport];
463
464  if(routino.language)
465     url=url + ";language=" + routino.language;
466
467  return(url);
468 }
469
470
471 //
472 // Update custom URL
473 //
474
475 function updateCustomURL()
476 {
477  var visualiser_url=document.getElementById("visualiser_url");
478  var link_url      =document.getElementById("link_url");
479  var edit_url      =document.getElementById("edit_url");
480
481  visualiser_url.href="customvisualiser.cgi?" + map_args;
482  link_url.href="customrouter.cgi" + buildURLArguments(1) + ";" + map_args;
483  edit_url.href="http://www.openstreetmap.org/edit?" + map_args;
484 }
485
486
487 //
488 // Block the use of the return key to submit the form
489 //
490
491 function block_return_key()
492 {
493  var form=document.getElementById("form");
494
495  if(form.addEventListener)
496     form.addEventListener('keyup', discardReturnKey, false);
497  else if(form.attachEvent)
498     form.attachEvent('keyup', discardReturnKey); // Internet Explorer
499 }
500
501 //
502 // Function to discard the return key if pressed
503 //
504
505 function discardReturnKey(ev)
506 {
507  if(ev.keyCode==13)
508     return(false);
509
510  return(true);
511 }
512
513
514 ////////////////////////////////////////////////////////////////////////////////
515 ///////////////////////////////// Map handling /////////////////////////////////
516 ////////////////////////////////////////////////////////////////////////////////
517
518 var map;
519 var layerMapOSM, layerVectors, layerGPX;
520 var epsg4326, epsg900913;
521 var map_args;
522
523 // 
524 // Initialise the 'map' object
525 //
526
527 function map_init(lat,lon,zoom)
528 {
529  // Default configuration:
530  // UK coordinate range
531  // West -11.0, South 49.5, East 2.0, North 61.0
532  // Zoom level 4 to 15
533
534  // EDIT THIS below to change the visible map limits
535
536  var westedge  = -11.0;          // Minimum longitude (degrees)
537  var eastedge  =   2.0;          // Maximum longitude (degrees)
538  var southedge =  49.5;          // Minimum latitude (degrees)
539  var northedge =  61.0;          // Maximum latitude (degrees)
540  var zoomout   =     4;          // Minimum zoom
541  var zoomin    =    15;          // Maximum zoom
542
543  // EDIT THIS above to change the visible map limits
544
545  //
546  // Create the map
547  //
548
549  epsg4326=new OpenLayers.Projection("EPSG:4326");
550  epsg900913=new OpenLayers.Projection("EPSG:900913");
551
552  map = new OpenLayers.Map ("map",
553                            {
554                             controls:[
555                                       new OpenLayers.Control.Navigation(),
556                                       new OpenLayers.Control.PanZoomBar(),
557                                       new OpenLayers.Control.ScaleLine(),
558                                       new OpenLayers.Control.LayerSwitcher()
559                                       ],
560
561                             projection: epsg900913,
562                             displayProjection: epsg4326,
563
564                             minZoomLevel: zoomout,
565                             numZoomLevels: zoomin-zoomout+1,
566                             maxResolution: 156543.0339 / Math.pow(2,zoomout),
567
568                             maxExtent:        new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
569                             restrictedExtent: new OpenLayers.Bounds(westedge,southedge,eastedge,northedge).transform(epsg4326,epsg900913),
570
571                             units: "m"
572                            });
573
574  map.events.register("moveend", map, mapMoved);
575
576  // Add a map tile layer (OpenStreetMap tiles, direct access)
577
578  layerMapOSM = new OpenLayers.Layer.TMS("Original OSM map",
579                                         "http://tile.openstreetmap.org/",
580                                         {
581                                          emptyUrl: "http://openstreetmap.org/openlayers/img/404.png",
582                                          type: 'png',
583                                          getURL: limitedUrl,
584                                          displayOutsideMaxExtent: true,
585                                          buffer: 1
586                                         });
587  map.addLayer(layerMapOSM);
588
589  // Get a URL for the tile; limited to map restricted extent.
590
591  function limitedUrl(bounds)
592  {
593   var z = map.getZoom() + map.minZoomLevel;
594
595   if (z>=7 && (bounds.right  < map.restrictedExtent.left ||
596                bounds.left   > map.restrictedExtent.right ||
597                bounds.top    < map.restrictedExtent.bottom ||
598                bounds.bottom > map.restrictedExtent.top))
599      return this.emptyUrl;
600
601   var res = map.getResolution();
602   var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
603   var limit = Math.pow(2, z);
604
605   if (y < 0 || y >= limit)
606     return this.emptyUrl;
607
608   var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
609
610   x = ((x % limit) + limit) % limit;
611   return this.url + z + "/" + x + "/" + y + "." + this.type;
612  }
613
614  // Define a GPX layer but don't add it yet
615
616  layerGPX={shortest: null, quickest: null};
617
618  gpx_style={shortest: new OpenLayers.Style({},{strokeWidth: 3, strokeColor: "#00FF00"}),
619             quickest: new OpenLayers.Style({},{strokeWidth: 3, strokeColor: "#0000FF"})};
620  
621  // Add a vectors layer
622  
623  layerVectors = new OpenLayers.Layer.Vector("Markers");
624  map.addLayer(layerVectors);
625
626  // A set of markers
627
628  nmarkers=99;
629  vismarkers=0;
630  markers={};
631  markersmoved=false;
632  paramschanged=false;
633
634  for(var marker=1;marker<=nmarkers;marker++)
635    {
636     if(document.forms["form"].elements["lon" + marker] != undefined)
637       {
638        markers[marker] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0),{},
639                                                        new OpenLayers.Style({},{externalGraphic: 'icons/marker-' + marker + '-red.png',
640                                                                                 fillColor: "white",
641                                                                                 graphicYOffset: -25,
642                                                                                 graphicWidth: 21,
643                                                                                 graphicHeight: 25,
644                                                                                 display: "none"}));
645
646        layerVectors.addFeatures([markers[marker]]);
647       }
648     else
649       {
650        nmarkers=marker-1;
651        vismarkers=marker-1;
652        break;
653       }
654    }
655
656  // A function to drag the markers
657
658  var drag = new OpenLayers.Control.DragFeature(layerVectors,
659                                                {onDrag:     dragMove,
660                                                 onComplete: dragComplete });
661  map.addControl(drag);
662  drag.activate();
663
664  // Markers to highlight a selected point
665
666  for(var highlight in highlights)
667    {
668     highlights[highlight] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0),{},
669                                                           new OpenLayers.Style({},{strokeColor: route_dark_colours[highlight],
670                                                                                    fillColor: "white",
671                                                                                    pointRadius: 10,
672                                                                                    strokeWidth: 4,
673                                                                                    fillOpacity: 0,
674                                                                                    display: "none"}));
675
676     layerVectors.addFeatures([highlights[highlight]]);
677    }
678
679  // A popup for routing results
680
681  for(var popup in popups)
682     popups[popup] = createPopup(popup);
683
684  // Set the map centre to the limited range specified
685
686  map.setCenter(map.restrictedExtent.getCenterLonLat(), map.getZoomForExtent(map.restrictedExtent,true));
687  map.maxResolution = map.getResolution();
688
689  // Move the map
690
691  if(lon != 'lon' && lat != 'lat' && zoom != 'zoom')
692    {
693     var lonlat = new OpenLayers.LonLat(lon,lat).transform(epsg4326,map.getProjectionObject());
694
695     map.moveTo(lonlat,zoom-map.minZoomLevel);
696    }
697 }
698
699
700 //
701 // Map has moved
702 //
703
704 function mapMoved()
705 {
706  var centre = map.getCenter().clone();
707
708  var lonlat = centre.transform(map.getProjectionObject(),epsg4326);
709
710  var zoom = this.getZoom() + map.minZoomLevel;
711
712  map_args="lat=" + lonlat.lat + ";lon=" + lonlat.lon + ";zoom=" + zoom;
713
714  updateCustomURL();
715 }
716
717
718 //
719 // OpenLayers.Control.DragFeature callback for a drag occuring.
720 //
721
722 function dragMove(feature,pixel)
723 {
724  for(var marker in markers)
725     if(feature==markers[marker])
726       {
727        markersmoved=true;
728
729        coordsSetForm(marker);
730       }
731 }
732
733
734 //
735 // OpenLayers.Control.DragFeature callback for completing a drag.
736 //
737
738 function dragComplete(feature,pixel)
739 {
740  for(var marker in markers)
741     if(feature==markers[marker])
742       {
743        markersmoved=true;
744
745        coordsSetForm(marker);
746       }
747 }
748
749
750 ////////////////////////////////////////////////////////////////////////////////
751 /////////////////////////////// Marker handling ////////////////////////////////
752 ////////////////////////////////////////////////////////////////////////////////
753
754 var nmarkers, vismarkers, markers, markersmoved, paramschanged;
755 var homelat=null, homelon=null;
756
757
758 //
759 // Toggle a marker on the map.
760 //
761
762 function markerToggleMap(marker)
763 {
764  if(markers[marker].style.display == "")
765     markerRemoveMap(marker);
766  else
767     markerAddMap(marker);
768 }
769
770
771 //
772 // Show a marker on the map.
773 //
774
775 function markerAddMap(marker)
776 {
777  markers[marker].style.display = "";
778
779  formSetCoords(marker);
780
781  updateIcon(marker);
782
783  markersmoved=true;
784 }
785
786
787 //
788 // Remove a marker from the map.
789 //
790
791 function markerRemoveMap(marker)
792 {
793  markers[marker].style.display = "none";
794
795  updateIcon(marker);
796
797  markersmoved=true;
798 }
799
800
801 //
802 // Centre the marker on the map
803 //
804
805 function markerCentre(marker)
806 {
807  document.forms["form"].elements["lon" + marker].value="";
808  document.forms["form"].elements["lat" + marker].value="";
809
810  formSetCoords(marker);
811
812  markersmoved=true;
813 }
814
815
816 //
817 // Clear the current marker.
818 //
819
820 function markerRemove(marker)
821 {
822  for(var marker2=marker;marker2<vismarkers;marker2++)
823    {
824     document.forms["form"].elements["lon" + marker2].value=document.forms["form"].elements["lon" + (marker2+1)].value;
825     document.forms["form"].elements["lat" + marker2].value=document.forms["form"].elements["lat" + (marker2+1)].value;
826
827     if(markers[marker2+1].style.display=="")
828        markerAddMap(marker2);
829     else
830        markerRemoveMap(marker2);
831    }
832
833  markerRemoveMap(vismarkers);
834
835  var marker_tr=document.getElementById("point" + vismarkers);
836
837  marker_tr.style.display="none";
838
839  vismarkers--;
840
841  if(vismarkers==1)
842     markerAddAfter(1);
843
844  updateCustomURL();
845 }
846
847
848 //
849 // Add a marker before the current one.
850 //
851
852 function markerAddBefore(marker)
853 {
854  if(vismarkers==nmarkers || marker==1)
855     return false;
856
857  vismarkers++;
858
859  var marker_tr=document.getElementById("point" + vismarkers);
860
861  marker_tr.style.display="";
862
863  for(var marker2=vismarkers;marker2>marker;marker2--)
864    {
865     document.forms["form"].elements["lon" + marker2].value=document.forms["form"].elements["lon" + (marker2-1)].value;
866     document.forms["form"].elements["lat" + marker2].value=document.forms["form"].elements["lat" + (marker2-1)].value;
867
868     if(markers[marker2-1].style.display=="")
869        markerAddMap(marker2);
870     else
871        markerRemoveMap(marker2);
872    }
873
874  document.forms["form"].elements["lon" + marker].value="";
875  document.forms["form"].elements["lat" + marker].value="";
876  markers[marker].style.display="none";
877
878  markerRemoveMap(marker);
879
880  updateCustomURL();
881 }
882
883
884 //
885 // Add a marker after the current one.
886 //
887
888 function markerAddAfter(marker)
889 {
890  if(vismarkers==nmarkers)
891     return false;
892
893  vismarkers++;
894
895  var marker_tr=document.getElementById("point" + vismarkers);
896
897  marker_tr.style.display="";
898
899  for(var marker2=vismarkers;marker2>(marker+1);marker2--)
900    {
901     document.forms["form"].elements["lon" + marker2].value=document.forms["form"].elements["lon" + (marker2-1)].value;
902     document.forms["form"].elements["lat" + marker2].value=document.forms["form"].elements["lat" + (marker2-1)].value;
903
904     if(markers[marker2-1].style.display=="")
905        markerAddMap(marker2);
906     else
907        markerRemoveMap(marker2);
908    }
909
910  document.forms["form"].elements["lon" + (marker+1)].value="";
911  document.forms["form"].elements["lat" + (marker+1)].value="";
912  markers[marker+1].style.display="none";
913
914  markerRemoveMap(marker+1);
915
916  updateCustomURL();
917 }
918
919
920 //
921 // Set this marker as the home location.
922 //
923
924 function markerHome(marker)
925 {
926  if(markerHomeCookie(marker))
927     for(marker=1;marker<=nmarkers;marker++)
928        updateIcon(marker);
929 }
930
931
932 //
933 // Update an icon to set colours and home or normal marker.
934 //
935
936 function updateIcon(marker)
937 {
938  var lon=document.forms["form"].elements["lon" + marker].value;
939  var lat=document.forms["form"].elements["lat" + marker].value;
940
941  if(lon==homelon && lat==homelat)
942    {
943     if(markers[marker].style.display=="")
944        document.images["waypoint" + marker].src="icons/marker-home-red.png";
945     else
946        document.images["waypoint" + marker].src="icons/marker-home-grey.png";
947
948     markers[marker].style.externalGraphic="icons/marker-home-red.png";
949    }
950  else
951    {
952     if(markers[marker].style.display=="")
953        document.images["waypoint" + marker].src="icons/marker-" + marker + "-red.png";
954     else
955        document.images["waypoint" + marker].src="icons/marker-" + marker + "-grey.png";
956
957     markers[marker].style.externalGraphic="icons/marker-" + marker + "-red.png";
958    }
959
960  layerVectors.drawFeature(markers[marker]);
961 }
962
963
964 //
965 // Set or clear the home marker icon
966 //
967
968 function markerHomeCookie(marker)
969 {
970  var lon=document.forms["form"].elements["lon" + marker].value;
971  var lat=document.forms["form"].elements["lat" + marker].value;
972
973  if(lon=="" || lat=="")
974     return(false);
975
976  var cookie;
977  var date = new Date();
978
979  if((homelat==null && homelon==null) ||
980     (homelat!=lat  && homelon!=lon))
981    {
982     cookie="Routino-home=lon:" + lon + ":lat:" + lat;
983
984     date.setUTCFullYear(date.getUTCFullYear()+5);
985
986     homelat=lat;
987     homelon=lon;
988    }
989  else
990    {
991     cookie="Routino-home=unset";
992
993     date.setUTCFullYear(date.getUTCFullYear()-1);
994
995     homelat=null;
996     homelon=null;
997    }
998
999  document.cookie=cookie + ";expires=" + date.toGMTString();
1000
1001  return(true);
1002 }
1003
1004
1005 //
1006 // Move this marker up.
1007 //
1008
1009 function markerMoveUp(marker)
1010 {
1011  if(marker==1)
1012     return false;
1013
1014  markerSwap(marker,marker-1);
1015 }
1016
1017
1018 //
1019 // Move this marker down.
1020 //
1021
1022 function markerMoveDown(marker)
1023 {
1024  if(marker==vismarkers)
1025     return false;
1026
1027  markerSwap(marker,marker+1);
1028 }
1029
1030
1031 //
1032 // Swap a pair of markers.
1033 //
1034
1035 function markerSwap(marker1,marker2)
1036 {
1037  var lon=document.forms["form"].elements["lon" + marker1].value;
1038  var lat=document.forms["form"].elements["lat" + marker1].value;
1039  var display=markers[marker1].style.display;
1040
1041  document.forms["form"].elements["lon" + marker1].value=document.forms["form"].elements["lon" + marker2].value;
1042  document.forms["form"].elements["lat" + marker1].value=document.forms["form"].elements["lat" + marker2].value;
1043  if(markers[marker2].style.display=="")
1044     markerAddMap(marker1);
1045  else
1046     markerRemoveMap(marker1);
1047
1048  document.forms["form"].elements["lon" + marker2].value=lon;
1049  document.forms["form"].elements["lat" + marker2].value=lat;
1050  if(display=="")
1051     markerAddMap(marker2);
1052  else
1053     markerRemoveMap(marker2);
1054
1055  updateCustomURL();
1056 }
1057
1058
1059 //
1060 // Reverse the markers.
1061 //
1062
1063 function markersReverse()
1064 {
1065  for(var marker=1;marker<=vismarkers/2;marker++)
1066     markerSwap(marker,vismarkers+1-marker);
1067
1068  updateCustomURL();
1069 }
1070
1071
1072 ////////////////////////////////////////////////////////////////////////////////
1073 //////////////////////////// Route results handling ////////////////////////////
1074 ////////////////////////////////////////////////////////////////////////////////
1075
1076 var route_light_colours={shortest: "#60C060", quickest: "#6060C0"};
1077 var route_dark_colours ={shortest: "#408040", quickest: "#404080"};
1078
1079 var highlights={shortest: null, quickest: null};
1080 var popups={shortest: null, quickest: null};
1081 var routepoints={shortest: {}, quickest: {}};
1082 var gpx_style={shortest: null, quickest: null};
1083
1084 //
1085 // Zoom to a specific item in the route
1086 //
1087
1088 function zoomTo(type,line)
1089 {
1090  var lonlat = new OpenLayers.LonLat(routepoints[type][line].lon,routepoints[type][line].lat).transform(epsg4326,map.getProjectionObject());
1091
1092  map.moveTo(lonlat,map.numZoomLevels-2);
1093 }
1094
1095
1096 //
1097 // Highlight a specific item in the route
1098 //
1099
1100 function highlight(type,line)
1101 {
1102  if(line==-1)
1103    {
1104     highlights[type].style.display = "none";
1105
1106     drawPopup(popups[type],null);
1107    }
1108  else
1109    {
1110     // Marker
1111
1112     var lonlat = new OpenLayers.LonLat(routepoints[type][line].lon,routepoints[type][line].lat).transform(epsg4326,map.getProjectionObject());
1113
1114     highlights[type].move(lonlat);
1115
1116     if(highlights[type].style.display = "none")
1117        highlights[type].style.display = "";
1118
1119     // Popup
1120
1121     drawPopup(popups[type],"<table>" + routepoints[type][line].html + "</table>");
1122    }
1123
1124  layerVectors.drawFeature(highlights[type]);
1125 }
1126
1127
1128 //
1129 // Create a popup - not using OpenLayers because want it fixed on screen not fixed on map.
1130 //
1131
1132 function createPopup(type)
1133 {
1134  var popup=document.createElement('div');
1135
1136  popup.className = "popup";
1137
1138  popup.innerHTML = "<span></span>";
1139
1140  popup.style.display = "none";
1141
1142  popup.style.position = "fixed";
1143  popup.style.top = "-4000px";
1144  popup.style.left = "-4000px";
1145  popup.style.zIndex = "100";
1146
1147  popup.style.padding = "5px";
1148
1149  popup.style.opacity=0.85;
1150  popup.style.backgroundColor=route_light_colours[type];
1151  popup.style.border="4px solid " + route_dark_colours[type];
1152
1153  document.body.appendChild(popup);
1154
1155  return(popup);
1156 }
1157
1158
1159 //
1160 // Draw a popup - not using OpenLayers because want it fixed on screen not fixed on map.
1161 //
1162
1163 function drawPopup(popup,html)
1164 {
1165  if(html==null)
1166    {
1167     popup.style.display="none";
1168     return;
1169    }
1170
1171  if(popup.style.display=="none")
1172    {
1173     var map_div=document.getElementById("map");
1174
1175     popup.style.left  =map_div.offsetParent.offsetLeft+map_div.offsetLeft+60 + "px";
1176     popup.style.top   =                                map_div.offsetTop +30 + "px";
1177     popup.style.width =map_div.clientWidth-100 + "px";
1178
1179     popup.style.display="";
1180    }
1181
1182  popup.innerHTML=html;
1183 }
1184
1185
1186 //
1187 // Remove a GPX trace
1188 //
1189
1190 function removeGPXTrace(type)
1191 {
1192  map.removeLayer(layerGPX[type]);
1193  layerGPX[type].destroy();
1194  layerGPX[type]=null;
1195
1196  displayStatus(type,"no_info");
1197
1198  var div_links=document.getElementById(type + "_links");
1199  div_links.style.display = "none";
1200
1201  var div_route=document.getElementById(type + "_route");
1202  div_route.innerHTML = "";
1203
1204  hideshow_hide(type);
1205 }
1206
1207
1208 ////////////////////////////////////////////////////////////////////////////////
1209 /////////////////////////////// Server handling ////////////////////////////////
1210 ////////////////////////////////////////////////////////////////////////////////
1211
1212 //
1213 // Display data statistics
1214 //
1215
1216 function displayStatistics()
1217 {
1218  // Use AJAX to get the statistics
1219
1220  OpenLayers.loadURL("statistics.cgi",null,null,runStatisticsSuccess);
1221 }
1222
1223
1224 //
1225 // Success in running data statistics generation.
1226 //
1227
1228 function runStatisticsSuccess(response)
1229 {
1230  var statistics_data=document.getElementById("statistics_data");
1231  var statistics_link=document.getElementById("statistics_link");
1232
1233  statistics_data.innerHTML="<pre>" + response.responseText + "</pre>";
1234
1235  statistics_link.style.display="none";
1236 }
1237
1238
1239 //
1240 // Submit form - perform the routing
1241 //
1242
1243 function findRoute(type)
1244 {
1245  tab_select("results");
1246
1247  hideshow_hide('help_options');
1248  hideshow_hide('shortest');
1249  hideshow_hide('quickest');
1250
1251  displayStatus("result","running");
1252
1253  var url="router.cgi" + buildURLArguments(0) + ";type=" + type;
1254
1255  // Destroy the existing layer(s)
1256
1257  if(markersmoved || paramschanged)
1258    {
1259     if(layerGPX.shortest!=null)
1260        removeGPXTrace("shortest");
1261     if(layerGPX.quickest!=null)
1262        removeGPXTrace("quickest");
1263     markersmoved=false;
1264     paramschanged=false;
1265    }
1266  else if(layerGPX[type]!=null)
1267     removeGPXTrace(type);
1268
1269  // Use AJAX to run the router
1270
1271  routing_type=type;
1272
1273  OpenLayers.loadURL(url,null,null,runRouterSuccess,runRouterFailure);
1274 }
1275
1276
1277 //
1278 // Success in running router.
1279 //
1280
1281 function runRouterSuccess(response)
1282 {
1283  var lines=response.responseText.split('\n');
1284
1285  var uuid=lines[0];
1286  var cpuinfo=lines[1];
1287  var distinfo=lines[2];
1288  var message=lines[3];
1289
1290  // Update the status message
1291
1292  if(message!="")
1293    {
1294     displayStatus("result","error");
1295     hideshow_show('help_route');
1296     return;
1297    }
1298  else
1299    {
1300     displayStatus("result","complete");
1301     hideshow_hide('help_route');
1302    }
1303
1304  // Update the routing result message
1305
1306  displayStatus(routing_type,"info",distinfo.bold());
1307
1308  var link;
1309
1310  link=document.getElementById(routing_type + "_html");
1311  link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";
1312  link=document.getElementById(routing_type + "_gpx_track");
1313  link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";
1314  link=document.getElementById(routing_type + "_gpx_route");
1315  link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-route";
1316  link=document.getElementById(routing_type + "_text_all");
1317  link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text-all";
1318  link=document.getElementById(routing_type + "_text");
1319  link.href="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=text";
1320
1321  var div_links=document.getElementById(routing_type + "_links");
1322  div_links.style.display = "";
1323
1324  // Add a GPX layer
1325
1326  var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=gpx-track";
1327
1328  layerGPX[routing_type] = new OpenLayers.Layer.GML("GPX (" + routing_type + ")", url,
1329                                                    {
1330                                                     format:     OpenLayers.Format.GPX,
1331                                                     style:      gpx_style[routing_type],
1332                                                     projection: map.displayProjection
1333                                                    });
1334
1335  map.addLayer(layerGPX[routing_type]);
1336
1337  hideshow_show(routing_type);
1338
1339  displayResult(routing_type,uuid);
1340 }
1341
1342
1343 //
1344 // Failure in running router.
1345 //
1346
1347 function runRouterFailure(response)
1348 {
1349  displayStatus("result","failed");
1350 }
1351
1352
1353 //
1354 // Display the status
1355 //
1356
1357 function displayStatus(type,subtype,content)
1358 {
1359  var div_status=document.getElementById(type + "_status");
1360
1361  var child=div_status.firstChild;
1362
1363  do
1364    {
1365     if(child.id != undefined)
1366        child.style.display="none";
1367
1368     child=child.nextSibling;
1369    }
1370  while(child != undefined);
1371
1372  var span_status=document.getElementById(type + "_status_" + subtype);
1373
1374  span_status.style.display="";
1375
1376  if(content != null)
1377     span_status.innerHTML=content;
1378 }
1379
1380
1381 //
1382 // Display the route
1383 //
1384
1385 function displayResult(type,uuid)
1386 {
1387  routing_type = type;
1388
1389  // Add the route
1390
1391  var url="results.cgi?uuid=" + uuid + ";type=" + routing_type + ";format=html";
1392
1393  // Use AJAX to get the route
1394
1395  OpenLayers.loadURL(url,null,null,getRouteSuccess,getRouteFailure);
1396 }
1397
1398
1399 //
1400 // Success in getting route.
1401 //
1402
1403 function getRouteSuccess(response)
1404 {
1405  var lines=response.responseText.split('\n');
1406  var div_route=document.getElementById(routing_type + "_route");
1407
1408  routepoints[routing_type]=[];
1409
1410  var points=routepoints[routing_type];
1411
1412  var table=0;
1413  var point=0;
1414  var total_table,total_word;
1415
1416  for(var line=0;line<lines.length;line++)
1417    {
1418     var thisline=lines[line];
1419
1420     if(table==0)
1421       {
1422        if(thisline.match('<table>'))
1423           table=1;
1424        else
1425           continue;
1426       }
1427
1428     if(thisline.match('</table>'))
1429        break;
1430
1431     if(thisline.match('<tr class=\'([a-z])\'>'))
1432       {
1433        var rowtype=RegExp.$1;
1434
1435        if(rowtype=='c')
1436          {
1437           thisline.match('<td class=\'r\'> *([-0-9.]+) *([-0-9.]+)');
1438           points[point]={lat: Number(RegExp.$1), lon: Number(RegExp.$2), html: "", highway: "", distance: "", total: ""};
1439
1440           point++;
1441          }
1442        else if(rowtype=='n')
1443          {
1444           points[point-1].html += thisline;
1445          }
1446        else if(rowtype=='s')
1447          {
1448           thisline.match('<span class=\'h\'>([^<]+)</span>');
1449           points[point-1].highway = RegExp.$1;
1450
1451           thisline.match('<span class=\'d\'>([^<]+)</span>');
1452           points[point-1].distance = RegExp.$1;
1453
1454           thisline.match('(<span class=\'j\'>[^<]+</span>)');
1455           points[point-1].total = RegExp.$1;
1456
1457           thisline.match('^(.*).<span class=\'j\'>');
1458
1459           points[point-1].html += RegExp.$1;
1460          }
1461        else if(rowtype=='t')
1462          {
1463           points[point-1].html += thisline;
1464
1465           thisline.match('^(.*<td class=\'r\'>)');
1466           total_table = RegExp.$1;
1467
1468           thisline.match('<td class=\'l\'>([^<]+)<');
1469           total_word = RegExp.$1;
1470
1471           thisline.match('<span class=\'j\'>([^<]+)</span>');
1472           points[point-1].total = RegExp.$1;
1473          }
1474       }
1475    }
1476
1477  var result="<table onmouseout='highlight(\"" + routing_type + "\",-1)'>";
1478
1479  for(var p=0;p<point-1;p++)
1480    {
1481     points[p].html += total_table + points[p].total;
1482
1483     result=result + "<tr onclick='zoomTo(\"" + routing_type + "\"," + p + ")'" +
1484                     " onmouseover='highlight(\"" + routing_type + "\"," + p + ")'>" +
1485                     "<td class='distance' title='" + points[p].distance + "'>#" + (p+1) +
1486                     "<td class='highway'>" + points[p].highway;
1487    }
1488
1489  result=result + "<tr onclick='zoomTo(\"" + routing_type + "\"," + p + ")'" +
1490                  " onmouseover='highlight(\"" + routing_type + "\"," + p + ")'>" +
1491                  "<td colspan='2'>" + total_word + " " + points[p].total;
1492
1493  result=result + "</table>";
1494
1495  div_route.innerHTML=result;
1496 }
1497
1498
1499 //
1500 // Failure in getting route.
1501 //
1502
1503 function getRouteFailure(response)
1504 {
1505  var div_route=document.getElementById(routing_type + "_route");
1506  div_route.innerHTML = "";
1507 }