com.graphhopper.maps.js.main-template.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of graphhopper-web-bundle Show documentation
Show all versions of graphhopper-web-bundle Show documentation
Use the GraphHopper routing engine as a web-service
var Flatpickr = require('flatpickr');
require('flatpickr/dist/l10n');
var L = require('leaflet');
require('leaflet-contextmenu');
require('leaflet-loading');
require('leaflet.heightgraph');
var moment = require('moment');
require('./lib/leaflet_numbered_markers.js');
global.jQuery = require('jquery');
global.$ = global.jQuery;
require('./lib/jquery-ui-custom-1.12.0.min.js');
require('./lib/jquery.history.js');
require('./lib/jquery.autocomplete.js');
var ghenv = require("./config/options.js").options;
console.log(ghenv.environment);
var GHInput = require('./graphhopper/GHInput.js');
var GHRequest = require('./graphhopper/GHRequest.js');
var host = ghenv.routing.host;
if (!host) {
if (location.port === '') {
host = location.protocol + '//' + location.hostname;
} else {
host = location.protocol + '//' + location.hostname + ":" + location.port;
}
}
var AutoComplete = require('./autocomplete.js');
if (ghenv.environment === 'development') {
var autocomplete = AutoComplete.prototype.createStub();
} else {
var autocomplete = new AutoComplete(ghenv.geocoding.host, ghenv.geocoding.api_key);
}
var mapLayer = require('./map.js');
var nominatim = require('./nominatim.js');
var routeManipulation = require('./routeManipulation.js');
var gpxExport = require('./gpxexport.js');
var messages = require('./messages.js');
var translate = require('./translate.js');
var customModelEditor = require('custom-model-editor/dist/index.js');
var format = require('./tools/format.js');
var urlTools = require('./tools/url.js');
var tileLayers = require('./config/tileLayers.js');
if(ghenv.with_tiles)
tileLayers.enableVectorTiles();
var debug = false;
var ghRequest = new GHRequest(host, ghenv.routing.api_key);
var bounds = {};
var metaVersionInfo;
// usage: log('inside coolFunc',this,arguments);
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
if (global.window) {
window.log = function () {
log.history = log.history || []; // store logs to an array for reference
log.history.push(arguments);
if (this.console && debug) {
console.log(Array.prototype.slice.call(arguments));
}
};
}
$(document).ready(function (e) {
// fixing cross domain support e.g in Opera
jQuery.support.cors = true;
gpxExport.addGpxExport(ghRequest);
// we start without encoded values, they will be loaded later
var cmEditor = customModelEditor.create({}, function (element) {
$("#custom-model-editor").append(element);
});
cmEditor.validListener = function(valid) {
$("#custom-model-search-button").prop('disabled', !valid);
};
ghRequest.cmEditor = cmEditor;
ghRequest.cmEditorActive = false;
var toggleCustomModelBox = function(sendRoute) {
$("#custom-model-box").toggle();
ghRequest.cmEditorActive = !ghRequest.cmEditorActive;
// avoid default action, so use a different search button
$("#searchButton").toggle();
mapLayer.adjustMapSize();
cmEditor.cm.refresh();
cmEditor.cm.focus();
cmEditor.cm.setCursor(cmEditor.cm.lineCount());
if (sendRoute)
sendCustomData();
};
$("#custom-model-button").click(function() {
toggleCustomModelBox(true);
});
function showCustomModelExample() {
cmEditor.value =
"{"
+ "\n \"speed\": ["
+ "\n {"
+ "\n \"if\": \"road_class == MOTORWAY\","
+ "\n \"multiply_by\": 0.8"
+ "\n }"
+ "\n ],"
+ "\n \"priority\": ["
+ "\n {"
+ "\n \"if\": \"road_environment == TUNNEL\","
+ "\n \"multiply_by\": 0.0"
+ "\n },"
+ "\n {"
+ "\n \"if\": \"max_weight < 3\","
+ "\n \"multiply_by\": 0.0"
+ "\n }"
+ "\n ]"
+ "\n}";
cmEditor.cm.focus();
cmEditor.cm.setCursor(0);
cmEditor.cm.execCommand('selectAll');
cmEditor.cm.refresh();
}
$("#custom-model-example").click(function () {
showCustomModelExample();
return false;
});
$("#export-link").click(function (e) {
try {
e.preventDefault();
var url = location.href;
if(url.indexOf("?") > 0)
url = url.substring(0, url.indexOf("?")) + ghRequest.createHistoryURL() + "&layer=" + encodeURIComponent(tileLayers.activeLayerName);
if(ghRequest.cmEditorActive) {
var text = cmEditor.value.replaceAll("&","%26");
url += "&custom_model=" + new URLSearchParams(JSON.stringify(JSON.parse(text))).toString();
}
navigator.clipboard.writeText(url).then(() => { alert('Link copied to clipboard'); });
} catch(e) { console.warn(e); }
});
var sendCustomData = function () {
ghRequest.ignoreCustomErrors = false;
mySubmit();
};
var sendCustomDataIgnoreErrors = function () {
ghRequest.ignoreCustomErrors = true;
mySubmit();
}
cmEditor.setExtraKey('Ctrl-Enter', sendCustomDataIgnoreErrors);
$("#custom-model-search-button").click(sendCustomData);
if (isProduction())
$('#hosting').show();
var History = window.History;
if (History.enabled) {
History.Adapter.bind(window, 'statechange', function () {
// No need for workaround?
// Chrome and Safari always emit a popstate event on page load, but Firefox doesn’t
// https://github.com/defunkt/jquery-pjax/issues/143#issuecomment-6194330
var state = History.getState();
initFromParams(state.data, true);
});
}
$('#locationform').submit(function (e) {
// no page reload
e.preventDefault();
mySubmit();
});
var urlParams = urlTools.parseUrlWithHisto();
var customModelJSON = urlParams.custom_model;
if(customModelJSON) {
toggleCustomModelBox(false);
cmEditor.value = customModelJSON; // if json parsing fails we still have the partial custom model in the box
try {
var tmpObj = JSON.parse(customModelJSON);
cmEditor.value = JSON.stringify(tmpObj, null, 2);
} catch(e) {
console.warn('cannot pretty print custom model: ' + e);
}
} else {
// todo: the idea was to highlight everything so if we start typing the example is overwritten. But unfortunately
// this does not work. And not even sure this is so useful?
showCustomModelExample();
}
$.when(ghRequest.fetchTranslationMap(urlParams.locale), ghRequest.getInfo())
.then(function (arg1, arg2) {
// init translation retrieved from first call (fetchTranslationMap)
var translations = arg1[0];
autocomplete.setLocale(translations.locale);
ghRequest.setLocale(translations.locale);
translate.init(translations);
// init bounding box from getInfo result
var json = arg2[0];
var tmp = json.bbox;
bounds.initialized = true;
bounds.minLon = tmp[0];
bounds.minLat = tmp[1];
bounds.maxLon = tmp[2];
bounds.maxLat = tmp[3];
nominatim.setBounds(bounds);
var profilesDiv = $("#profiles");
function createButton(profile, hide) {
var vehicle = profile.vehicle;
var profileName = profile.name;
var button = $("");
if (hide)
button.hide();
button.attr('id', profileName);
button.html("");
button.click(function () {
ghRequest.setProfile(profileName);
ghRequest.removeLegacyParameters();
resolveAll();
if (ghRequest.route.isResolved())
routeLatLng(ghRequest);
});
return button;
}
if (json.profiles) {
var profiles = json.profiles;
// first sort alphabetically to maintain a consistent order, then move certain elements to front/back
profiles.sort(function (a, b) {
return a.vehicle < b.vehicle ? -1 : a.vehicle > b.vehicle ? 1 : 0;
});
// the desired order is car,foot,bike,,motorcycle
var firstVehicles = ["car", "foot", "bike"];
for (var i=firstVehicles.length-1; i>=0; --i) {
profiles = moveToFront(profiles, function(p) { return p.vehicle === firstVehicles[i]; });
}
var lastVehicles = ["mtb", "motorcycle"];
for (var i=0; i= 0;
if (profiles.length > 0)
ghRequest.setProfile(profiles[0].name);
var numVehiclesWhenCollapsed = 3;
var hiddenVehicles = [];
for (var i = 0; i < profiles.length; ++i) {
var btn = createButton(profiles[i], !showAllProfiles && i >= numVehiclesWhenCollapsed);
profilesDiv.append(btn);
if (i >= numVehiclesWhenCollapsed)
hiddenVehicles.push(btn);
}
if (!showAllProfiles && profiles.length > numVehiclesWhenCollapsed) {
var moreBtn = $(" ...").click(function () {
moreBtn.hide();
for (var i in hiddenVehicles) {
hiddenVehicles[i].show();
}
});
profilesDiv.append($("?"));
profilesDiv.append(moreBtn);
}
}
$("button#" + profiles[0].name).addClass("selectprofile");
metaVersionInfo = messages.extractMetaVersionInfo(json);
// a very simplistic helper system that shows the possible entries and encoded values
if(json.encoded_values) {
const categories = {};
Object.keys(json.encoded_values).forEach((k) => {
const v = json.encoded_values[k];
if (v.length == 2 && v[0] === 'true' && v[1] === 'false') {
categories[k] = {type: 'boolean'};
} else if (v.length === 2 && v[0] === '>number' && v[1] === 'Refresh' + '
Status: ' + err.statusText + '
' + host);
bounds = {
"minLon": -180,
"minLat": -90,
"maxLon": 180,
"maxLat": 90
};
nominatim.setBounds(bounds);
mapLayer.initMap(bounds, setStartCoord, setIntermediateCoord, setEndCoord, urlParams.layer, urlParams.use_miles);
});
var language_code = urlParams.locale && urlParams.locale.split('-', 1)[0];
if (language_code != 'en') {
// A few language codes are different in GraphHopper and Flatpickr.
var flatpickr_locale;
switch (language_code) {
case 'ca': // Catalan
flatpickr_locale = 'cat';
break;
case 'el': // Greek
flatpickr_locale = 'gr';
break;
default:
flatpickr_locale = language_code;
}
if (Flatpickr.l10ns.hasOwnProperty(flatpickr_locale)) {
Flatpickr.localize(Flatpickr.l10ns[flatpickr_locale]);
}
}
$(window).resize(function () {
mapLayer.adjustMapSize();
});
$("#locationpoints").sortable({
items: ".pointDiv",
cursor: "n-resize",
containment: "parent",
handle: ".pointFlag",
update: function (event, ui) {
var origin_index = $(ui.item[0]).data('index');
sortable_items = $("#locationpoints > div.pointDiv");
$(sortable_items).each(function (index) {
var data_index = $(this).data('index');
if (origin_index === data_index) {
//log(data_index +'>'+ index);
ghRequest.route.move(data_index, index);
if (!routeIfAllResolved())
checkInput();
return false;
}
});
}
});
$('#locationpoints > div.pointAdd').click(function () {
ghRequest.route.add(new GHInput());
checkInput();
});
checkInput();
});
function profileDisplayName(profileName) {
// custom profile names like 'my_car' cannot be translated and will be returned like 'web.my_car', so we remove
// the 'web.' prefix in this case
return translate.tr(profileName).replace("web.", "");
}
/**
* Takes an array and returns another array with the same elements but sorted such that all elements matching the given
* condition come first.
*/
function moveToFront(arr, condition) {
return arr.filter(condition).concat(arr.filter(function (e) { return !condition(e); }))
}
function initFromParams(params, doQuery) {
ghRequest.init(params);
var flatpickr = new Flatpickr(document.getElementById("input_date_0"), {
defaultDate: new Date(),
allowInput: true, /* somehow then does not sync!? */
minuteIncrement: 15,
time_24hr: true,
enableTime: true
});
if (ghRequest.isPublicTransit())
$(".time_input").show();
else
$(".time_input").hide();
if (ghRequest.getEarliestDepartureTime()) {
flatpickr.setDate(ghRequest.getEarliestDepartureTime());
}
var count = 0;
var singlePointIndex;
if (params.point)
for (var key = 0; key < params.point.length; key++) {
if (params.point[key] !== "") {
count++;
singlePointIndex = key;
}
}
var routeNow = params.point && count >= 2;
if (routeNow) {
resolveCoords(params.point, doQuery);
} else if (params.point && count === 1) {
ghRequest.route.set(params.point[singlePointIndex], singlePointIndex, true);
resolveIndex(singlePointIndex).done(function () {
mapLayer.focus(ghRequest.route.getIndex(singlePointIndex), 15, singlePointIndex);
});
}
}
function resolveCoords(pointsAsStr, doQuery) {
for (var i = 0, l = pointsAsStr.length; i < l; i++) {
var pointStr = pointsAsStr[i];
var coords = ghRequest.route.getIndex(i);
if (!coords || pointStr !== coords.input || !coords.isResolved())
ghRequest.route.set(pointStr, i, true);
}
checkInput();
if (ghRequest.route.isResolved()) {
resolveAll();
routeLatLng(ghRequest, doQuery);
} else {
// at least one text input from user -> wait for resolve as we need the coord for routing
$.when.apply($, resolveAll()).done(function () {
routeLatLng(ghRequest, doQuery);
});
}
}
var FROM = 'from', TO = 'to';
function getToFrom(index) {
if (index === 0)
return FROM;
else if (index === (ghRequest.route.size() - 1))
return TO;
return -1;
}
function checkInput() {
var template = $('#pointTemplate').html(),
len = ghRequest.route.size();
// remove deleted points
if ($('#locationpoints > div.pointDiv').length > len) {
$('#locationpoints > div.pointDiv:gt(' + (len - 1) + ')').remove();
}
// properly unbind previously click handlers
$("#locationpoints .pointDelete").off();
var deleteClickHandler = function () {
var index = $(this).parent().data('index');
ghRequest.route.removeSingle(index);
mapLayer.clearLayers();
checkInput();
routeLatLng(ghRequest, false);
};
// console.log("## new checkInput");
for (var i = 0; i < len; i++) {
var div = $('#locationpoints > div.pointDiv').eq(i);
// console.log(div.length + ", index:" + i + ", len:" + len);
if (div.length === 0) {
$('#locationpoints > div.pointAdd').before(translate.nanoTemplate(template, {id: i}));
div = $('#locationpoints > div.pointDiv').eq(i);
}
var toFrom = getToFrom(i);
div.data("index", i);
div.find(".pointFlag").attr("src",
(toFrom === FROM) ? 'img/marker-small-green.png' :
((toFrom === TO) ? 'img/marker-small-red.png' : 'img/marker-small-blue.png'));
if (len > 2) {
div.find(".pointDelete").click(deleteClickHandler).prop('disabled', false).removeClass('ui-state-disabled');
} else {
div.find(".pointDelete").prop('disabled', true).addClass('ui-state-disabled');
}
autocomplete.showListForIndex(ghRequest, routeIfAllResolved, i);
if (translate.isI18nIsInitialized()) {
var input = div.find(".pointInput");
if (i === 0)
$(input).attr("placeholder", translate.tr("from_hint"));
else if (i === (len - 1))
$(input).attr("placeholder", translate.tr("to_hint"));
else
$(input).attr("placeholder", translate.tr("via_hint"));
}
}
}
function setToStart(e) {
var latlng = e.relatedTarget.getLatLng(),
index = ghRequest.route.getIndexByCoord(latlng);
ghRequest.route.move(index, 0);
routeIfAllResolved();
}
function setToEnd(e) {
var latlng = e.relatedTarget.getLatLng(),
index = ghRequest.route.getIndexByCoord(latlng);
ghRequest.route.move(index, -1);
routeIfAllResolved();
}
function setStartCoord(e) {
ghRequest.route.set(e.latlng.wrap(), 0);
resolveFrom();
routeIfAllResolved();
}
function setIntermediateCoord(e) {
var routeLayers = mapLayer.getSubLayers("route");
var routeSegments = routeLayers.map(function (rl) {
return {
coordinates: rl.getLatLngs(),
wayPoints: rl.feature.properties.snapped_waypoints.coordinates.map(function (wp) {
return L.latLng(wp[1], wp[0]);
})
};
});
var index = routeManipulation.getIntermediatePointIndex(routeSegments, e.latlng);
ghRequest.route.add(e.latlng.wrap(), index);
ghRequest.do_zoom = false;
resolveIndex(index);
routeIfAllResolved();
}
function deleteCoord(e) {
var latlng = e.relatedTarget.getLatLng();
ghRequest.route.removeSingle(latlng);
mapLayer.clearLayers();
routeLatLng(ghRequest, false);
}
function setEndCoord(e) {
var index = ghRequest.route.size() - 1;
ghRequest.route.set(e.latlng.wrap(), index);
resolveTo();
routeIfAllResolved();
}
function routeIfAllResolved(doQuery) {
if (ghRequest.route.isResolved()) {
routeLatLng(ghRequest, doQuery);
return true;
}
return false;
}
function setFlag(coord, index) {
if (coord.lat) {
var toFrom = getToFrom(index);
// intercept openPopup
var marker = mapLayer.createMarker(index, coord, setToEnd, setToStart, deleteCoord, ghRequest);
marker._openPopup = marker.openPopup;
marker.openPopup = function () {
var latlng = this.getLatLng(),
locCoord = ghRequest.route.getIndexFromCoord(latlng),
content;
if (locCoord.resolvedList && locCoord.resolvedList[0] && locCoord.resolvedList[0].locationDetails) {
var address = locCoord.resolvedList[0].locationDetails;
content = format.formatAddress(address);
// at last update the content and update
this._popup.setContent(content).update();
}
this._openPopup();
};
var _tempItem = {
text: translate.tr('set_start'),
icon: './img/marker-small-green.png',
callback: setToStart,
index: 1
};
if (toFrom === -1)
marker.options.contextmenuItems.push(_tempItem); // because the Mixin.ContextMenu isn't initialized
marker.on('dragend', function (e) {
mapLayer.clearLayers();
// inconsistent leaflet API: event.target.getLatLng vs. mouseEvent.latlng?
var latlng = e.target.getLatLng();
autocomplete.hide();
ghRequest.route.getIndex(index).setCoord(latlng.lat, latlng.lng);
resolveIndex(index);
// do not wait for resolving and avoid zooming when dragging
ghRequest.do_zoom = false;
routeLatLng(ghRequest, false);
});
}
}
function resolveFrom() {
return resolveIndex(0);
}
function resolveTo() {
return resolveIndex((ghRequest.route.size() - 1));
}
function resolveIndex(index) {
if(!ghRequest.route.getIndex(index))
return;
setFlag(ghRequest.route.getIndex(index), index);
if (index === 0) {
if (!ghRequest.to.isResolved())
mapLayer.setDisabledForMapsContextMenu('start', true);
else
mapLayer.setDisabledForMapsContextMenu('start', false);
} else if (index === (ghRequest.route.size() - 1)) {
if (!ghRequest.from.isResolved())
mapLayer.setDisabledForMapsContextMenu('end', true);
else
mapLayer.setDisabledForMapsContextMenu('end', false);
}
return nominatim.resolve(index, ghRequest.route.getIndex(index));
}
function resolveAll() {
var ret = [];
for (var i = 0, l = ghRequest.route.size(); i < l; i++) {
ret[i] = resolveIndex(i);
}
if(ghRequest.isPublicTransit())
ghRequest.setEarliestDepartureTime(
moment($("#input_date_0").val(), 'YYYY-MM-DD HH:mm').toISOString());
return ret;
}
function flagAll() {
for (var i = 0, l = ghRequest.route.size(); i < l; i++) {
setFlag(ghRequest.route.getIndex(i), i);
}
}
function createRouteCallback(request, routeResultsDiv, urlForHistory, doZoom) {
return function (json) {
routeResultsDiv.html("");
if (json.message) {
var tmpErrors = json.message;
console.log(tmpErrors);
if (json.hints) {
for (var m = 0; m < json.hints.length; m++) {
routeResultsDiv.append("" + json.hints[m].message + "");
}
} else {
routeResultsDiv.append("" + tmpErrors + "");
}
return;
}
function createClickHandler(geoJsons, currentLayerIndex, tabHeader, oneTab, hasElevation, details, selectedDetail, detailSelected) {
return function () {
var currentGeoJson = geoJsons[currentLayerIndex];
mapLayer.eachLayer(function (layer) {
// skip markers etc
if (!layer.setStyle)
return;
var doHighlight = layer.feature === currentGeoJson;
layer.setStyle(doHighlight ? highlightRouteStyle : alternativeRouteStye);
if (doHighlight) {
if (!L.Browser.ie && !L.Browser.opera)
layer.bringToFront();
}
});
if (hasElevation) {
mapLayer.clearElevation();
mapLayer.addElevation(currentGeoJson, details, selectedDetail, detailSelected);
}
headerTabs.find("li").removeClass("current");
routeResultsDiv.find("div").removeClass("current");
tabHeader.addClass("current");
oneTab.addClass("current");
};
}
var headerTabs = $("
");
if (json.paths.length > 1) {
routeResultsDiv.append(headerTabs);
routeResultsDiv.append("");
}
// the routing layer uses the geojson properties.style for the style, see map.js
var defaultRouteStyle = {color: "#00cc33", "weight": 5, "opacity": 0.6};
var highlightRouteStyle = {color: "#00cc33", "weight": 6, "opacity": 0.8};
var alternativeRouteStye = {color: "darkgray", "weight": 6, "opacity": 0.8};
var geoJsons = [];
var firstHeader;
// Create buttons to toggle between SI and imperial units.
var createUnitsChooserButtonClickHandler = function (useMiles) {
return function () {
mapLayer.updateScale(useMiles);
ghRequest.useMiles = useMiles;
resolveAll();
if (ghRequest.route.isResolved())
routeLatLng(ghRequest);
};
};
if(json.paths.length > 0 && json.paths[0].points_order) {
mapLayer.clearLayers();
var po = json.paths[0].points_order;
for (var i = 0; i < po.length; i++) {
setFlag(ghRequest.route.getIndex(po[i]), i);
}
}
for (var pathIndex = 0; pathIndex < json.paths.length; pathIndex++) {
var tabHeader = $("").append((pathIndex + 1) + "");
if (pathIndex === 0)
firstHeader = tabHeader;
headerTabs.append(tabHeader);
var path = json.paths[pathIndex];
var style = (pathIndex === 0) ? defaultRouteStyle : alternativeRouteStye;
var geojsonFeature = {
"type": "Feature",
"geometry": path.points,
"properties": {
"style": style,
name: "route",
snapped_waypoints: path.snapped_waypoints
}
};
geoJsons.push(geojsonFeature);
mapLayer.addDataToRoutingLayer(geojsonFeature);
var oneTab = $("");
routeResultsDiv.append(oneTab);
var detailSelected = function (id, type) {
ghRequest.selectedDetail = type.text;
}
tabHeader.click(createClickHandler(geoJsons, pathIndex, tabHeader, oneTab, request.hasElevation(), path.details, request.selectedDetail, detailSelected));
var routeInfo = $("");
if (path.description && path.description.length > 0) {
routeInfo.text(path.description);
routeInfo.append("
");
}
var tempDistance = translate.createDistanceString(path.distance, request.useMiles);
var tempRouteInfo;
if(request.isPublicTransit()) {
var tempArrTime = moment(ghRequest.getEarliestDepartureTime())
.add(path.time, 'milliseconds')
.format('LT');
if(path.transfers >= 0)
tempRouteInfo = translate.tr("pt_route_info", [tempArrTime, path.transfers, tempDistance]);
else
tempRouteInfo = translate.tr("pt_route_info_walking", [tempArrTime, tempDistance]);
} else {
var tmpDuration = translate.createTimeString(path.time);
tempRouteInfo = translate.tr("route_info", [tempDistance, tmpDuration]);
}
routeInfo.append(tempRouteInfo);
var kmButton = $("
© 2015 - 2024 Weber Informatics LLC | Privacy Policy