From 4b40f1253fa7fb2ce46e6784ecca65a4cfc1d457 Mon Sep 17 00:00:00 2001 From: DennisSchiefer Date: Wed, 14 Mar 2012 16:30:11 +0100 Subject: [PATCH] added legal headers, beautified comments, moved language settings to config, moved timeout settings to config, corrected bug with route link and via nodes removed old files --- WebContent/L.DashedPolyline.js | 23 +++- WebContent/L.MouseMarker.js | 23 ++++ WebContent/OSRM.Browser.js | 18 +++ WebContent/OSRM.GUI.js | 20 ++- WebContent/OSRM.JSONP.js | 52 +++++--- WebContent/OSRM.Localization.js | 45 +++++-- WebContent/OSRM.Markers.js | 39 ++++-- WebContent/OSRM.Route.js | 30 ++++- WebContent/OSRM.Routing.js | 12 -- WebContent/OSRM.base.js | 21 +++ WebContent/OSRM.config.js | 22 +++- WebContent/OSRM.debug.js | 19 ++- WebContent/geocoder.js | 173 +++++++++++++----------- WebContent/main.css | 26 +++- WebContent/main.html | 17 +++ WebContent/main.js | 69 +++++----- WebContent/routing.js | 224 ++++++++++++++++++-------------- WebContent/test.html | 27 ---- WebContent/utils.js | 19 ++- WebContent/via.js | 21 +++ 20 files changed, 598 insertions(+), 302 deletions(-) delete mode 100644 WebContent/OSRM.Routing.js delete mode 100644 WebContent/test.html diff --git a/WebContent/L.DashedPolyline.js b/WebContent/L.DashedPolyline.js index 099018c80..1fa0f6794 100644 --- a/WebContent/L.DashedPolyline.js +++ b/WebContent/L.DashedPolyline.js @@ -1,4 +1,25 @@ -// dashed polyline +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// Leaflet extension: Dashed Polyline +// [adds dashed optionally dashed lines when using SVG or VML rendering] + + +// dashed polyline class L.DashedPolyline = L.Polyline.extend({ initialize: function(latlngs, options) { L.Polyline.prototype.initialize.call(this, latlngs, options); diff --git a/WebContent/L.MouseMarker.js b/WebContent/L.MouseMarker.js index 807a78924..1b983b220 100644 --- a/WebContent/L.MouseMarker.js +++ b/WebContent/L.MouseMarker.js @@ -1,3 +1,26 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// Leaflet extension: MouseMarker +// [marker class that propagates modifier and button presses] +// [currently deactivated: propagation mousemove events] + + +// extended marker class L.MouseMarker = L.Marker.extend({ initialize: function (latlng, options) { L.Marker.prototype.initialize.apply(this, arguments); diff --git a/WebContent/OSRM.Browser.js b/WebContent/OSRM.Browser.js index 7ecc0afbe..860761c59 100644 --- a/WebContent/OSRM.Browser.js +++ b/WebContent/OSRM.Browser.js @@ -1,4 +1,22 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + // OSRM browser detection +// [simple detection routines to respect some browser peculiarities] (function() { diff --git a/WebContent/OSRM.GUI.js b/WebContent/OSRM.GUI.js index 4c81fafd3..4867c3128 100644 --- a/WebContent/OSRM.GUI.js +++ b/WebContent/OSRM.GUI.js @@ -1,4 +1,22 @@ -// GUI functionality +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM GUI functionality +// [responsible for all non-routing related GUI behaviour] OSRM.GUI = { diff --git a/WebContent/OSRM.JSONP.js b/WebContent/OSRM.JSONP.js index 38af68549..c37fa1ef5 100644 --- a/WebContent/OSRM.JSONP.js +++ b/WebContent/OSRM.JSONP.js @@ -1,39 +1,54 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + // OSRM JSONP call wrapper -// w/ DOM cleaning, fencing, timout handling +// [wrapper for JSONP calls with DOM cleaning, fencing, timout handling] + OSRM.JSONP = { + + // storage to keep track of unfinished JSONP calls fences: {}, callbacks: {}, timeouts: {}, timers: {}, - TIMEOUT: OSRM.DEFAULTS.JSONP_TIMEOUT, - late: function() { },//console.log("reply too late");}, - empty: function() { },//console.log("empty callback");}, - + // default callback routines + late: function() { /*OSRM.debug.log("[jsonp] reply too late");*/ }, + empty: function() { /*OSRM.debug.log("[jsonp] empty callback");*/ }, + + + // init JSONP call call: function(source, callback_function, timeout_function, timeout, id) { // only one active JSONP call per id if (OSRM.JSONP.fences[id] == true) return false; OSRM.JSONP.fences[id] = true; -// console.log("[status] jsonp init for "+id); -// console.log("[status] jsonp request ",source); - // wrap timeout function OSRM.JSONP.timeouts[id] = function(response) { timeout_function(response); -// var jsonp = document.getElementById('jsonp_'+id); // clean DOM -// if(jsonp) -// jsonp.parentNode.removeChild(jsonp); OSRM.JSONP.callbacks[id] = OSRM.JSONP.late; // clean functions OSRM.JSONP.timeouts[id] = OSRM.JSONP.late; OSRM.JSONP.fences[id] = undefined; // clean fence -// console.log("timeout: "+id); // at the end - otherwise racing conditions may happen -// document.getElementById('information-box').innerHTML += "timeout:" + id + "
"; +// OSRM.debug.log("[jsonp] timout handling: "+id); }; // wrap callback function @@ -46,18 +61,14 @@ OSRM.JSONP = { callback_function(response); // actual wrapped callback -// var jsonp = document.getElementById('jsonp_'+id); // clean DOM -// if(jsonp) -// jsonp.parentNode.removeChild(jsonp); OSRM.JSONP.callbacks[id] = OSRM.JSONP.late; // clean functions OSRM.JSONP.timeouts[id] = OSRM.JSONP.late; OSRM.JSONP.fences[id] = undefined; // clean fence -// console.log("[status] jsonp response for "+id); // at the end - otherwise racing conditions may happen -// document.getElementById('information-box').innerHTML += "callback:" + id + "
"; +// OSRM.debug.log("[jsonp] response handling: "+id); }; - // clean DOM (cannot reuse script element with all browsers, unfortunately) + // clean DOM (unfortunately, script elements cannot be reused by all browsers) var jsonp = document.getElementById('jsonp_'+id); if(jsonp) jsonp.parentNode.removeChild(jsonp); @@ -71,7 +82,8 @@ OSRM.JSONP = { // start timeout timer OSRM.JSONP.timers[id] = setTimeout(OSRM.JSONP.timeouts[id], timeout); - + +// OSRM.debug.log("[jsonp] init: "+id); return true; } }; \ No newline at end of file diff --git a/WebContent/OSRM.Localization.js b/WebContent/OSRM.Localization.js index bddd726c9..48d02d2f9 100644 --- a/WebContent/OSRM.Localization.js +++ b/WebContent/OSRM.Localization.js @@ -1,19 +1,42 @@ -// localization +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM localization +// [basic localization options] + OSRM.Localization = { -language: "en", - + +// if existing, return localized string -> English string -> input string translate: function(text) { - if( OSRM.Localization[OSRM.Localization.language][text] ) - return OSRM.Localization[OSRM.Localization.language][text]; - else if( OSRM.Localization[OSRM.Localization.language][text] ) - return OSRM.Localization[OSRM.Localization.language][text]; + if( OSRM.Localization[OSRM.DEFAULTS.LANGUAGE][text] ) + return OSRM.Localization[OSRM.DEFAULTS.LANGUAGE][text]; + else if( OSRM.Localization["en"][text] ) + return OSRM.Localization["en"][text]; else return text; }, }; + +// shorter call to translate function OSRM.loc = OSRM.Localization.translate; + +// German language support OSRM.Localization["de"] = { //gui "GUI_START": "Start", @@ -23,13 +46,13 @@ OSRM.Localization["de"] = { "GUI_ROUTE": "Route", "GUI_REVERSE": "Umdrehen", "GUI_OPTIONS": "Optionen", -"GUI_HIGHLIGHT_UNNAMED_ROADS": "Unbenannte Stra�en hervorheben", +"GUI_HIGHLIGHT_UNNAMED_ROADS": "Unbenannte Straßen hervorheben", "GUI_START_TOOLTIP": "Startposition eingeben", "GUI_END_TOOLTIP": "Zielposition eingeben", "GUI_LEGAL_NOTICE": "GUI2 v0.1 120313 - OSRM hosting by KIT - Geocoder by OSM", // geocoder "SEARCH_RESULTS": "Suchergebnisse", -"TIMED_OUT": "Zeit�berschreitung", +"TIMED_OUT": "Zeitüberschreitung", "NO_RESULTS_FOUND": "Keine Ergebnisse gefunden", // routing "ROUTE_DESCRIPTION": "Routenbeschreibung", @@ -40,9 +63,11 @@ OSRM.Localization["de"] = { "DISTANCE": "Distanz", "DURATION": "Dauer", "YOUR_ROUTE_IS_BEING_COMPUTED": "Ihre Route wird berechnet", -"NO_ROUTE_FOUND": "Keine Route hierher m�glich", +"NO_ROUTE_FOUND": "Keine Route hierher möglich", }; + +// English language support OSRM.Localization["en"] = { //gui "GUI_START": "Start", diff --git a/WebContent/OSRM.Markers.js b/WebContent/OSRM.Markers.js index ff11c7d72..4b2e2599e 100644 --- a/WebContent/OSRM.Markers.js +++ b/WebContent/OSRM.Markers.js @@ -1,8 +1,25 @@ -// OSRM.Marker class -// + sub-classes +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM markers +// [base marker class, derived highlight marker and route marker classes, marker management] -// base class +// base marker class (wraps Leaflet markers) OSRM.Marker = function( label, style, position ) { this.label = label ? label : "marker"; this.position = position ? position : new L.LatLng(0,0); @@ -52,7 +69,7 @@ toString: function() { }); -// highlight marker +// highlight marker class (cannot be dragged) OSRM.HighlightMarker = function( label, style, position) { OSRM.HighlightMarker.prototype.base.constructor.apply( this, arguments ); this.label = label ? label : "highlight_marker"; @@ -65,7 +82,7 @@ toString: function() { }); -// route marker +// route marker class (draggable, invokes route drawing routines) OSRM.RouteMarker = function ( label, style, position ) { OSRM.RouteMarker.prototype.base.constructor.apply( this, arguments ); this.label = label ? label : "route_marker"; @@ -78,8 +95,6 @@ OSRM.RouteMarker = function ( label, style, position ) { OSRM.inheritFrom( OSRM.RouteMarker, OSRM.Marker ); OSRM.extend( OSRM.RouteMarker, { onClick: function(e) { -// if(!e.ctrlKey) -// return; for( var i=0; i easier way in Leaglet 0.4+ + // TODO: hack to put unnamed_route above old_route -> easier way in will be available Leaflet 0.4 _raiseUnnamedRoute: function() { if(this._unnamed_route.isShown()) { this._unnamed_route.hide(); diff --git a/WebContent/OSRM.Routing.js b/WebContent/OSRM.Routing.js deleted file mode 100644 index 7e879d487..000000000 --- a/WebContent/OSRM.Routing.js +++ /dev/null @@ -1,12 +0,0 @@ -// OSRM route class - - -OSRM.TheRoute = { - -}; -OSRM.extend( OSRM.TheRoute, { - -show: function() {}, -hide: function() {}, - -}); \ No newline at end of file diff --git a/WebContent/OSRM.base.js b/WebContent/OSRM.base.js index 8273b4964..61ed2caf3 100644 --- a/WebContent/OSRM.base.js +++ b/WebContent/OSRM.base.js @@ -1,8 +1,27 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + // OSRM base class +// [has to loaded before all other OSRM classes] OSRM = {}; OSRM.VERSION = '0.1'; + // inheritance helper function (convenience function) OSRM._inheritFromHelper = function() {}; OSRM.inheritFrom = function( sub_class, base_class ) { @@ -12,6 +31,7 @@ OSRM.inheritFrom = function( sub_class, base_class ) { sub_class.prototype.base = base_class.prototype; }; + // class prototype extending helper function (convenience function) OSRM.extend = function( target_class, properties ) { for( property in properties ) { @@ -19,6 +39,7 @@ OSRM.extend = function( target_class, properties ) { } }; + // usage: // SubClass = function() { // SubClass.prototype.base.constructor.apply(this, arguments); diff --git a/WebContent/OSRM.config.js b/WebContent/OSRM.config.js index 70c62b6a9..3322b8437 100644 --- a/WebContent/OSRM.config.js +++ b/WebContent/OSRM.config.js @@ -1,5 +1,22 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + // OSRM config file -// (has to be loaded directly after OSRM.base!) +// [has to be loaded directly after OSRM.base] OSRM.DEFAULTS = { HOST_ROUTING_URL: 'http://router.project-osrm.org/viaroute', @@ -11,4 +28,5 @@ OSRM.DEFAULTS = { ONLOAD_LONGITUDE: 10.10, ONLOAD_SOURCE: "", ONLOAD_TARGET: "", -}; \ No newline at end of file + LANGUAGE: "en", +}; diff --git a/WebContent/OSRM.debug.js b/WebContent/OSRM.debug.js index 9a1605872..3ef9465a3 100644 --- a/WebContent/OSRM.debug.js +++ b/WebContent/OSRM.debug.js @@ -1,5 +1,22 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + // debug code for OSRM -// (works faster than console.log in time-critical events) +// [works better than console.log in older browsers and for logging event handling] OSRM.debug = {}; diff --git a/WebContent/geocoder.js b/WebContent/geocoder.js index 2df228ba0..ea1a8b843 100644 --- a/WebContent/geocoder.js +++ b/WebContent/geocoder.js @@ -1,11 +1,31 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM geocoding routines +// [geocoder query, management and display of geocoder results] +// [TODO: better separation of GUI and geocoding routines, reverse geocoding] + // some constants OSRM.GEOCODE_POST = 'http://nominatim.openstreetmap.org/search?format=json'; -OSRM.REVERSE_GEOCODE_POST = 'http://nominatim.openstreetmap.org/reverse?format=json'; OSRM.SOURCE_MARKER_LABEL = "source"; OSRM.TARGET_MARKER_LABEL = "target"; -// update locations in input boxes +// update geo coordinates in input boxes function updateLocation(marker_id) { if (marker_id == OSRM.SOURCE_MARKER_LABEL) { document.getElementById("input-source-name").value = my_markers.route[0].getPosition().lat.toFixed(6) + ", " + my_markers.route[0].getPosition().lng.toFixed(6); @@ -13,77 +33,11 @@ function updateLocation(marker_id) { document.getElementById("input-target-name").value = my_markers.route[my_markers.route.length-1].getPosition().lat.toFixed(6) + ", " + my_markers.route[my_markers.route.length-1].getPosition().lng.toFixed(6); } } -function updateReverseGeocoder(marker_id) { - if (marker_id == OSRM.SOURCE_MARKER_LABEL) { - document.getElementById("input-source-name").value = my_markers.route[0].getPosition().lat.toFixed(6) + ", " + my_markers.route[0].getPosition().lng.toFixed(6); - callReverseGeocoder("source", my_markers.route[0].getPosition().lat, my_markers.route[0].getPosition().lng); - } else if (marker_id == OSRM.TARGET_MARKER_LABEL) { - document.getElementById("input-target-name").value = my_markers.route[my_markers.route.length-1].getPosition().lat.toFixed(6) + ", " + my_markers.route[my_markers.route.length-1].getPosition().lng.toFixed(6); - callReverseGeocoder("target", my_markers.route[my_markers.route.length-1].getPosition().lat, my_markers.route[my_markers.route.length-1].getPosition().lng); - } -} -function updateLocations() { - if( my_markers.route[0] && my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) { - document.getElementById("input-source-name").value = my_markers.route[0].getPosition().lat.toFixed(6) + ", " + my_markers.route[0].getPosition().lng.toFixed(6); - callReverseGeocoder("source", my_markers.route[0].getPosition().lat, my_markers.route[0].getPosition().lng); - //OSRM.debug.log("[call1] reverse geocoder"); - } - - if( my_markers.route[my_markers.route.length-1] && my_markers.route[ my_markers.route.length-1 ].label == OSRM.TARGET_MARKER_LABEL) { - document.getElementById("input-target-name").value = my_markers.route[my_markers.route.length-1].getPosition().lat.toFixed(6) + ", " + my_markers.route[my_markers.route.length-1].getPosition().lng.toFixed(6); - callReverseGeocoder("target", my_markers.route[my_markers.route.length-1].getPosition().lat, my_markers.route[my_markers.route.length-1].getPosition().lng); - } -} -function timeout_ReverseGeocoder() { - //OSRM.debug.log("[timeout] reverse geocoder"); -} - -//prepare request and call reverse geocoder -function callReverseGeocoder(marker_id, lat, lon) { - //build request - if (marker_id == OSRM.SOURCE_MARKER_LABEL) { - var src= OSRM.REVERSE_GEOCODE_POST + "&lat=" + lat + "&lon=" + lon; - OSRM.JSONP.call( src, showReverseGeocoderResults_Source, timeout_ReverseGeocoder, OSRM.JSONP.TIMEOUT, "reverse_geocoder_source" ); - //OSRM.debug.log("[call2] reverse geocoder"); - } else if (marker_id == OSRM.TARGET_MARKER_LABEL) { - var src = OSRM.REVERSE_GEOCODE_POST + "&lat=" + lat + "&lon=" + lon; - OSRM.JSONP.call( src, showReverseGeocoderResults_Target, timeout_ReverseGeocoder, OSRM.JSONP.TIMEOUT, "reverse_geocoder_target" ); - } -} -//processing JSONP response of reverse geocoder -//(with wrapper functions for source/target jsonp) -function showReverseGeocoderResults_Source(response) { showReverseGeocoderResults(OSRM.SOURCE_MARKER_LABEL, response); } -function showReverseGeocoderResults_Target(response) { showReverseGeocoderResults(OSRM.TARGET_MARKER_LABEL, response); } -function showReverseGeocoderResults(marker_id, response) { - //OSRM.debug.log("[inner] reverse geocoder"); - if(response){ - if(response.address == undefined) - return; - - var address = ""; - if( response.address.road) - address += response.address.road; - if( response.address.city) { - if( response.address.road) - address += ", "; - address += response.address.city; - } - if( address == "" ) - return; - - if(marker_id == OSRM.SOURCE_MARKER_LABEL) - document.getElementById("input-source-name").value = address; - else if(marker_id == OSRM.TARGET_MARKER_LABEL) - document.getElementById("input-target-name").value = address; - } -} - - -// prepare request and call geocoder +// process input request and call geocoder if needed function callGeocoder(marker_id, query) { - //geo coordinate given? + //geo coordinates given -> go directly to drawing results if(query.match(/^\s*[-+]?[0-9]*\.?[0-9]+\s*[,;]\s*[-+]?[0-9]*\.?[0-9]+\s*$/)){ var coord = query.split(/[,;]/); onclickGeocoderResult(marker_id, coord[0], coord[1]); @@ -91,13 +45,13 @@ function callGeocoder(marker_id, query) { return; } - //build request + //build request if (marker_id == OSRM.SOURCE_MARKER_LABEL) { var src= OSRM.GEOCODE_POST + "&q=" + query; - OSRM.JSONP.call( src, showGeocoderResults_Source, showGeocoderResults_Timeout, OSRM.JSONP.TIMEOUT, "geocoder_source" ); + OSRM.JSONP.call( src, showGeocoderResults_Source, showGeocoderResults_Timeout, OSRM.DEFAULTS.JSONP_TIMEOUT, "geocoder_source" ); } else if (marker_id == OSRM.TARGET_MARKER_LABEL) { var src = OSRM.GEOCODE_POST + "&q=" + query; - OSRM.JSONP.call( src, showGeocoderResults_Target, showGeocoderResults_Timeout, OSRM.JSONP.TIMEOUT, "geocoder_target" ); + OSRM.JSONP.call( src, showGeocoderResults_Target, showGeocoderResults_Timeout, OSRM.DEFAULTS.JSONP_TIMEOUT, "geocoder_target" ); } } @@ -117,7 +71,7 @@ function onclickGeocoderResult(marker_id, lat, lon) { getRoute(OSRM.FULL_DESCRIPTION); } -// processing JSONP response of geocoder +// process JSONP response of geocoder // (with wrapper functions for source/target jsonp) function showGeocoderResults_Source(response) { showGeocoderResults(OSRM.SOURCE_MARKER_LABEL, response); } function showGeocoderResults_Target(response) { showGeocoderResults(OSRM.TARGET_MARKER_LABEL, response); } @@ -162,3 +116,74 @@ function showGeocoderResults_Timeout() { document.getElementById('information-box-headline').innerHTML = OSRM.loc("SEARCH_RESULTS")+":"; document.getElementById('information-box').innerHTML = "

"+OSRM.loc("TIMED_OUT")+".

"; } + + +// - [upcoming feature: reverse geocoding] - +//OSRM.REVERSE_GEOCODE_POST = 'http://nominatim.openstreetmap.org/reverse?format=json'; +// +//function updateReverseGeocoder(marker_id) { +// if (marker_id == OSRM.SOURCE_MARKER_LABEL) { +// document.getElementById("input-source-name").value = my_markers.route[0].getPosition().lat.toFixed(6) + ", " + my_markers.route[0].getPosition().lng.toFixed(6); +// callReverseGeocoder("source", my_markers.route[0].getPosition().lat, my_markers.route[0].getPosition().lng); +// } else if (marker_id == OSRM.TARGET_MARKER_LABEL) { +// document.getElementById("input-target-name").value = my_markers.route[my_markers.route.length-1].getPosition().lat.toFixed(6) + ", " + my_markers.route[my_markers.route.length-1].getPosition().lng.toFixed(6); +// callReverseGeocoder("target", my_markers.route[my_markers.route.length-1].getPosition().lat, my_markers.route[my_markers.route.length-1].getPosition().lng); +// } +//} +//function updateLocations() { +// if( my_markers.route[0] && my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) { +// document.getElementById("input-source-name").value = my_markers.route[0].getPosition().lat.toFixed(6) + ", " + my_markers.route[0].getPosition().lng.toFixed(6); +// callReverseGeocoder("source", my_markers.route[0].getPosition().lat, my_markers.route[0].getPosition().lng); +// //OSRM.debug.log("[call1] reverse geocoder"); +// } +// +// if( my_markers.route[my_markers.route.length-1] && my_markers.route[ my_markers.route.length-1 ].label == OSRM.TARGET_MARKER_LABEL) { +// document.getElementById("input-target-name").value = my_markers.route[my_markers.route.length-1].getPosition().lat.toFixed(6) + ", " + my_markers.route[my_markers.route.length-1].getPosition().lng.toFixed(6); +// callReverseGeocoder("target", my_markers.route[my_markers.route.length-1].getPosition().lat, my_markers.route[my_markers.route.length-1].getPosition().lng); +// } +//} +// +// +//function timeout_ReverseGeocoder() { +// //OSRM.debug.log("[timeout] reverse geocoder"); +//} +// +////prepare request and call reverse geocoder +//function callReverseGeocoder(marker_id, lat, lon) { +// //build request +// if (marker_id == OSRM.SOURCE_MARKER_LABEL) { +// var src= OSRM.REVERSE_GEOCODE_POST + "&lat=" + lat + "&lon=" + lon; +// OSRM.JSONP.call( src, showReverseGeocoderResults_Source, timeout_ReverseGeocoder, OSRM.DEFAULTS.JSONP_TIMEOUT, "reverse_geocoder_source" ); +// //OSRM.debug.log("[call2] reverse geocoder"); +// } else if (marker_id == OSRM.TARGET_MARKER_LABEL) { +// var src = OSRM.REVERSE_GEOCODE_POST + "&lat=" + lat + "&lon=" + lon; +// OSRM.JSONP.call( src, showReverseGeocoderResults_Target, timeout_ReverseGeocoder, OSRM.DEFAULTS.JSONP_TIMEOUT, "reverse_geocoder_target" ); +// } +//} +////processing JSONP response of reverse geocoder +////(with wrapper functions for source/target jsonp) +//function showReverseGeocoderResults_Source(response) { showReverseGeocoderResults(OSRM.SOURCE_MARKER_LABEL, response); } +//function showReverseGeocoderResults_Target(response) { showReverseGeocoderResults(OSRM.TARGET_MARKER_LABEL, response); } +//function showReverseGeocoderResults(marker_id, response) { +// //OSRM.debug.log("[inner] reverse geocoder"); +// if(response){ +// if(response.address == undefined) +// return; +// +// var address = ""; +// if( response.address.road) +// address += response.address.road; +// if( response.address.city) { +// if( response.address.road) +// address += ", "; +// address += response.address.city; +// } +// if( address == "" ) +// return; +// +// if(marker_id == OSRM.SOURCE_MARKER_LABEL) +// document.getElementById("input-source-name").value = address; +// else if(marker_id == OSRM.TARGET_MARKER_LABEL) +// document.getElementById("input-target-name").value = address; +// } +//} diff --git a/WebContent/main.css b/WebContent/main.css index e05f8bed3..e2ae5ad18 100644 --- a/WebContent/main.css +++ b/WebContent/main.css @@ -1,4 +1,24 @@ -/* styles for map */ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +/* OSRM CSS styles */ + + +/* map -> fullscreen */ body { padding: 0; margin: 0; @@ -241,7 +261,8 @@ html, body, #map { font-size:10px; } -/* generally useful styles (above buttons, so that they get their special cursor!)*/ + +/* utility styles (defined above buttons, so that buttons retain cursor:pointer)*/ .not-selectable { cursor:default; @@ -260,6 +281,7 @@ html, body, #map { user-select: text; } + /* buttons */ .button { diff --git a/WebContent/main.html b/WebContent/main.html index 8c14d1c58..6f476f6cf 100644 --- a/WebContent/main.html +++ b/WebContent/main.html @@ -1,3 +1,20 @@ + + diff --git a/WebContent/main.js b/WebContent/main.js index 7bee258b8..174b9a059 100644 --- a/WebContent/main.js +++ b/WebContent/main.js @@ -1,6 +1,27 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// OSRM initialization +// [initialization of maps, local strings, image prefetching] + var map; +// onload initialization routine function init() { prefetchImages(); prefetchIcons(); @@ -76,6 +97,7 @@ function centerOnGeolocation() { // init map function initMap() { + // setup tile servers var osmorgURL = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', osmorgAttribution = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 Mapnik', osmorgOptions = {maxZoom: 18, attribution: osmorgAttribution}; @@ -97,14 +119,16 @@ function initMap() { mapquest = new L.TileLayer(mapquestURL, mapquestOptions), cloudmade = new L.TileLayer(cloudmadeURL, cloudmadeOptions); + // setup map map = new L.Map('map', { center: new L.LatLng(51.505, -0.09), zoom: 13, - zoomAnimation: false, // uncomment to remove animations and hiding of routes during zoom + zoomAnimation: false, // false: removes animations and hiding of routes during zoom fadeAnimation: false, layers: [osmorg] }); + // add tileservers var baseMaps = { "osm.org": osmorg, "osm.de": osmde, @@ -116,12 +140,15 @@ function initMap() { var layersControl = new L.Control.Layers(baseMaps, overlayMaps); map.addControl(layersControl); + // move zoom markers getElementsByClassName(document,'leaflet-control-zoom')[0].style.left="420px"; getElementsByClassName(document,'leaflet-control-zoom')[0].style.top="5px"; - map.setView( new L.LatLng( OSRM.DEFAULTS.ONLOAD_LATITUDE, OSRM.DEFAULTS.ONLOAD_LONGITUDE-0.02), OSRM.DEFAULTS.ZOOM_LEVEL); + // initial map position and zoom + map.setView( new L.LatLng( OSRM.DEFAULTS.ONLOAD_LATITUDE, OSRM.DEFAULTS.ONLOAD_LONGITUDE), OSRM.DEFAULTS.ZOOM_LEVEL); map.on('zoomend', function(e) { getRoute(OSRM.FULL_DESCRIPTION); }); + // click on map to set source and target nodes map.on('click', function(e) { if( !my_markers.route[0] || my_markers.route[0].label != OSRM.SOURCE_MARKER_LABEL) { index = my_markers.setSource( e.latlng ); @@ -140,39 +167,10 @@ function initMap() { // updateReverseGeocoder("target"); } } ); - // onmousemove test -// map.on('mousemove', function(e) { console.log("pos: " + e.latlng); }); -// map.on('mousemove', function(e) { -// var objs = new Array; -// var obj = null; -// do { -// obj = document.elementFromPoint(e.layerPoint.x, e.layerPoint.y); -// -// if (obj == null) -// break; -// if (obj == document.body) -// break; -// if (obj instanceof SVGPathElement) -// break; -// -// objs.push(obj); -// obj.style.display = 'none'; -// } while(true); -// for(var i=0; i 0) my_markers.setSource( positions[0] ); + if(positions.length > 1) + my_markers.setTarget( positions[positions.length-1] ); for(var i=1; i 1) - my_markers.setTarget( positions[positions.length-1] ); for(var i=0; i= 0x20); - var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); - lat += dlat; - shift = 0; - result = 0; - do { - b = encoded.charCodeAt(index++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); - var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); - lng += dlng; - array.push([lat * precision, lng * precision]); - } - return array; -} -// display a transmitted route +// -- JSONP processing -- + +// process JSONP response of routing server function timeoutRouteSimple() { showNoRouteGeometry(); showNoRouteDescription(); @@ -68,10 +67,11 @@ function showRouteSimple(response) { showRouteDescriptionSimple(response); } updateHints(response); - + +// // TODO: hack to process final drag event, if it was fenced, but we are still dragging (alternative approach) // if(OSRM.pending) { // clearTimeout(OSRM.pendingTimer); -// OSRM.pendingTimer = setTimeout(timeoutDrag,100); // dirty dirty! +// OSRM.pendingTimer = setTimeout(timeoutDrag,100); // } } function showRoute(response) { @@ -92,6 +92,8 @@ function showRoute(response) { updateHints(response); } + +// show route geometry function showNoRouteGeometry() { var positions = []; for(var i=0; i'; route_desc += ""; - //route_desc += ''+(i+1)+'.'; - route_desc += ''; route_desc += '' + response.route_instructions[i][0] + ' on '; @@ -212,6 +214,8 @@ function showNoRouteDescription() { document.getElementById('information-box').innerHTML = "

"+OSRM.loc("YOUR_ROUTE_IS_BEING_COMPUTED")+".

"; } + +// unnamed streets display function showRouteNonames(response) { // do not display unnamed streets? if( document.getElementById('option-highlight-nonames').checked == false) { @@ -252,14 +256,15 @@ function showRouteNonames(response) { my_route.showUnnamedRoute(all_positions); } -// function for dragging and drawing routes + +//-- main function -- + +// generate server calls to query routes function getRoute(do_description) { // if source or target are not set -> hide route if( my_markers.route.length < 2 ) { my_route.hideRoute(); - //my_markers.removeVias(); // TODO: do I need this? - //my_markers.highlight.hide(); return; } @@ -292,16 +297,17 @@ function getRoute(do_description) { } // do call - var called = OSRM.JSONP.call(source, callback, timeout, OSRM.JSONP.TIMEOUT, type); + var called = OSRM.JSONP.call(source, callback, timeout, OSRM.DEFAULTS.JSONP_TIMEOUT, type); - // TODO: guarantee to do last drag + // TODO: hack to process final drag event, if it was fenced, but we are still dragging if(called == false && !do_description) { clearTimeout(OSRM.pendingTimer); - OSRM.pendingTimer = setTimeout(timeoutDrag,OSRM.JSONP.TIMEOUT); + OSRM.pendingTimer = setTimeout(timeoutDrag,OSRM.DEFAULTS.JSONP_TIMEOUT); } else { clearTimeout(OSRM.pendingTimer); } +// // TODO: hack to process final drag event, if it was fenced, but we are still dragging (alternative approach) // if(called == false && !do_description) { // OSRM.pending = true; // } else { @@ -309,28 +315,42 @@ function getRoute(do_description) { // OSRM.pending = false; // } } - function timeoutDrag() { my_markers.route[OSRM.dragid].hint = undefined; getRoute(OSRM.NO_DESCRIPTION); } -function startRouting() { - getRoute(OSRM.FULL_DESCRIPTION); -} - -function resetRouting() { - document.getElementById('input-source-name').value = ""; - document.getElementById('input-target-name').value = ""; - - my_route.hideRoute(); - my_markers.removeAll(); - my_markers.highlight.hide(); - - document.getElementById('information-box').innerHTML = ""; - document.getElementById('information-box-headline').innerHTML = ""; + +//-- helper functions -- + +//decode compressed route geometry +function decodeRouteGeometry(encoded, precision) { + precision = Math.pow(10, -precision); + var len = encoded.length, index=0, lat=0, lng = 0, array = []; + while (index < len) { + var b, shift = 0, result = 0; + do { + b = encoded.charCodeAt(index++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1)); + lat += dlat; + shift = 0; + result = 0; + do { + b = encoded.charCodeAt(index++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1)); + lng += dlng; + array.push([lat * precision, lng * precision]); + } + return array; } +// update hints of all markers function updateHints(response) { var hint_locations = response.hint_data.locations; my_markers.checksum = response.hint_data.checksum; @@ -338,6 +358,7 @@ function updateHints(response) { my_markers.route[i].hint = hint_locations[i]; } +// snap all markers to the received route function snapRoute() { var positions = my_route.getPositions(); @@ -350,48 +371,8 @@ function snapRoute() { updateLocation( "target" ); } -function positionsToInput() { - if(my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) { - document.getElementById('input-source-name').value = my_markers.route[0].getPosition().lat.toFixed(6)+","+my_markers.route[0].getPosition().lng.toFixed(6); - } - if(my_markers.route[my_markers.route.length-1].label == OSRM.TARGET_MARKER_LABEL) { - document.getElementById('input-target-name').value = my_markers.route[my_markers.route.length-1].getPosition().lat.toFixed(6)+","+my_markers.route[my_markers.route.length-1].getPosition().lng.toFixed(6); - } -} - -function reverseRouting() { - // invert input boxes - var tmp = document.getElementById("input-source-name").value; - document.getElementById("input-source-name").value = document.getElementById("input-target-name").value; - document.getElementById("input-target-name").value = tmp; - - // invert route - my_markers.route.reverse(); - if(my_markers.route.length == 1) { - if(my_markers.route[0].label == OSRM.TARGET_MARKER_LABEL) { - my_markers.route[0].label = OSRM.SOURCE_MARKER_LABEL; - my_markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') ); - } else if(my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) { - my_markers.route[0].label = OSRM.TARGET_MARKER_LABEL; - my_markers.route[0].marker.setIcon( new L.Icon('images/marker-target.png') ); - } - } else if(my_markers.route.length > 1){ - my_markers.route[0].label = OSRM.SOURCE_MARKER_LABEL; - my_markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') ); - - my_markers.route[my_markers.route.length-1].label = OSRM.TARGET_MARKER_LABEL; - my_markers.route[my_markers.route.length-1].marker.setIcon( new L.Icon('images/marker-target.png') ); - } - - // recompute route - getRoute(OSRM.FULL_DESCRIPTION); - my_markers.highlight.hide(); -} - - - - -//-------------------- +// map driving instructions to images +// [TODO: better implementation, language-safe] function getDirectionIcon(name) { var directions = { "Turn left":"turn-left.png", @@ -420,4 +401,55 @@ function getDirectionIcon(name) { return directions[name]; else return "default.png"; -} \ No newline at end of file +} + + +// -- gui functions -- + +// click: button "route" +function startRouting() { + getRoute(OSRM.FULL_DESCRIPTION); +} + +// click: button "reset" +function resetRouting() { + document.getElementById('input-source-name').value = ""; + document.getElementById('input-target-name').value = ""; + + my_route.hideRoute(); + my_markers.removeAll(); + my_markers.highlight.hide(); + + document.getElementById('information-box').innerHTML = ""; + document.getElementById('information-box-headline').innerHTML = ""; +} + +// click: button "reverse" +function reverseRouting() { + // invert input boxes + var tmp = document.getElementById("input-source-name").value; + document.getElementById("input-source-name").value = document.getElementById("input-target-name").value; + document.getElementById("input-target-name").value = tmp; + + // invert route + my_markers.route.reverse(); + if(my_markers.route.length == 1) { + if(my_markers.route[0].label == OSRM.TARGET_MARKER_LABEL) { + my_markers.route[0].label = OSRM.SOURCE_MARKER_LABEL; + my_markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') ); + } else if(my_markers.route[0].label == OSRM.SOURCE_MARKER_LABEL) { + my_markers.route[0].label = OSRM.TARGET_MARKER_LABEL; + my_markers.route[0].marker.setIcon( new L.Icon('images/marker-target.png') ); + } + } else if(my_markers.route.length > 1){ + my_markers.route[0].label = OSRM.SOURCE_MARKER_LABEL; + my_markers.route[0].marker.setIcon( new L.Icon('images/marker-source.png') ); + + my_markers.route[my_markers.route.length-1].label = OSRM.TARGET_MARKER_LABEL; + my_markers.route[my_markers.route.length-1].marker.setIcon( new L.Icon('images/marker-target.png') ); + } + + // recompute route + getRoute(OSRM.FULL_DESCRIPTION); + my_markers.highlight.hide(); +} diff --git a/WebContent/test.html b/WebContent/test.html deleted file mode 100644 index 782af23ad..000000000 --- a/WebContent/test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - -

Test Javascript Snippets

-

This could be your output.

- - - - - diff --git a/WebContent/utils.js b/WebContent/utils.js index 6ddca0596..b45f9be62 100644 --- a/WebContent/utils.js +++ b/WebContent/utils.js @@ -1,4 +1,21 @@ -// compatibility mode for old browser +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// compatibility tools for old browsers function getElementsByClassName(node, classname) { var a = []; var re = new RegExp('(^| )'+classname+'( |$)'); diff --git a/WebContent/via.js b/WebContent/via.js index 89353eb1d..1b9a3c8bc 100644 --- a/WebContent/via.js +++ b/WebContent/via.js @@ -1,5 +1,25 @@ +/* +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. +*/ + +// store location of via points returned by server var via_points; + +// find route segment of current route geometry that is closest to the new via node (marked by index of its endpoint) function findNearestRouteSegment( new_via ) { var min_dist = Number.MAX_VALUE; var min_index = undefined; @@ -17,6 +37,7 @@ function findNearestRouteSegment( new_via ) { } +// find the correct index among all via nodes to insert the new via node, and insert it function findViaPosition( new_via_position ) { // find route segment that is closest to click position (marked by last index) var nearest_index = findNearestRouteSegment( new_via_position );